Open-Source Wikis

/

Pulumi

/

How to contribute

/

Development workflow

pulumi/pulumi

Development workflow

The day-to-day loop for working on pulumi/pulumi.

Branching

  • Pulumi employees push directly to branches on the main repo. Nest under your own prefix: pulumipus/<feature>.
  • External contributors fork and push to a branch on the fork.

Inner loop for engine / CLI work

# 1. make changes
$EDITOR pkg/...

# 2. format + lint
mise exec -- make format
mise exec -- make lint

# 3. quick tests
mise exec -- make test_fast

# 4. focused tests
cd pkg && go test -count=1 -tags all -run TestSpecific ./engine/...

# 5. rebuild CLI to dogfood
mise exec -- make bin/pulumi
./bin/pulumi up   # or whatever

For SDK changes you generally need to rebuild that SDK and make install it (Node) before integration tests pick it up.

Inner loop for SDK work

Node.js — sdk/nodejs/

cd sdk/nodejs
mise exec -- make build
mise exec -- make install      # required before integration tests can yarn link
mise exec -- make test_fast
mise exec -- make lint

Python — sdk/python/

cd sdk/python
mise exec -- make build
mise exec -- make lint
mise exec -- make test_fast

Go — sdk/go/pulumi/

Go SDK tests run inside the regular Go module test infrastructure:

cd sdk
go test -count=1 ./go/pulumi/...

Working across modules

pulumi/pulumi is multiple Go modules. To edit sdk/go/pulumi and pkg/... simultaneously without replace directives:

mise exec -- make work     # generates a go.work file

go.work is gitignored and required only locally.

Changelog entries

Every PR needs an entry unless it has impact/no-changelog-required. Generate one interactively:

mise exec -- make changelog

The interactive prompt asks for type (feat, fix, chore), scope (e.g. cli/state, sdk/python), and a one-line message. The result lands as a YAML file in changelog/pending/. The full vocabulary is in changelog/config.yaml.

Examples (active imperative, no trailing period):

  • ✅ "Exit immediately from state edit when no change was made"
  • ✅ "Fix root and program paths to always be absolute"
  • ❌ "Fixes a bug" (passive, vague)
  • ❌ "Adds a feature." (period, vague)

Pulling in upstream changes

The default branch is master. If you've been on a topic branch for a while:

git fetch origin
git rebase origin/master
# resolve conflicts
mise exec -- make tidy_fix     # re-tidy go.mod across modules
mise exec -- make build_proto  # if proto/ changed

Force-push your branch (force-push to your own branch is fine; never to master).

Commit hygiene

Because PRs are squash-merged, individual commit messages within a PR are not preserved. Group commits however helps you most. The PR description is what ends up in the master log.

Code review expectations

  • Reviewers focus on correctness, scope creep, and public-surface changes.
  • Address every comment or explicitly say why you disagree.
  • Keep PRs scoped to one feature/fix. Big multi-feature PRs are hard to review and revert.
  • If you're using AI assistance, you're still responsible for the diff (see CONTRIBUTING.md "AI-Assisted Contributions").

Releasing

Release plumbing is documented at the bottom of CONTRIBUTING.md. The short version: scripts/set-version.py bumps sdk/.version, the freeze PR seals the next draft release on the GitHub Releases page, and pulumi-bot follows up with a go.mod cleanup PR that auto-merges. End-users download via curl -fsSL https://get.pulumi.com | sh.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Development workflow – Pulumi wiki | Factory