Using Bitbucket Pipelines with Pulumi
Bitbucket Pipelines is the CI/CD service built into Bitbucket Cloud. It runs the pipeline defined in a bitbucket-pipelines.yml file at the root of your repository, building and deploying your code on each push, pull request, or tag.
Pulumi runs in a pipeline as plain CLI commands, so this guide works with a Pulumi program written in any supported language and targeting any cloud provider.
Prerequisites
Before you begin, make sure you have:
- A Pulumi Cloud account and organization.
- A Bitbucket Cloud repository with Pipelines enabled.
- A Pulumi program committed to that repository. If you don’t have one yet, follow a Get started guide.
Authenticate with Pulumi Cloud
Give your pipeline a Pulumi Cloud identity in one of two ways. Choose one — you don’t need both:
- A stored access token — a long-lived Pulumi access token kept as a secured repository variable. Simplest to set up.
- OIDC token exchange — no stored secret; the pipeline exchanges a short-lived OIDC token for a Pulumi access token at runtime. Recommended.
Whichever you choose, Pulumi ESC (Environments, Secrets, and Configuration) then supplies cloud credentials, secrets, and configuration to your Pulumi program. Because ESC delivers those values the same way whether the consumer is a pipeline or a developer’s machine, a single environment definition works in both places — you don’t store separate cloud provider keys as repository variables.
Authenticate with a stored access token
Your pipeline authenticates to Pulumi Cloud with a single Pulumi access token, supplied through the PULUMI_ACCESS_TOKEN environment variable. Prefer an organization or team token over a personal token so the pipeline’s identity is not tied to an individual.
Add the token as a repository variable under Repository settings > Repository variables. Name it PULUMI_ACCESS_TOKEN and select the Secured checkbox so the value is encrypted and masked in build logs. Secured variables are exposed to every step of the pipeline as environment variables.
Authenticate without a stored token using OIDC
You can remove the static token entirely. Bitbucket Pipelines can issue a short-lived OpenID Connect (OIDC) token for any step that sets oidc: true, exposing it as the BITBUCKET_STEP_OIDC_TOKEN environment variable.
Register Bitbucket Pipelines as a trusted OIDC issuer in Pulumi Cloud, and your pipeline can exchange that OIDC token for a short-lived Pulumi access token at runtime — no long-lived credential is stored as a repository variable.
The trunk-based development workflow
The most common way to run Pulumi in CI/CD follows a trunk-based development model: work merges into a single main branch, and deployments flow outward from there.
Bitbucket Pipelines has three pipeline triggers that map directly onto the three stages of this workflow:
pull-requestsruns when a pull request is opened or updated — use it to preview changes.branchesruns when commits land on a branch — use it to deploy to staging on merge tomain.tagsruns when a tag is pushed — use it to promote to production.
The bitbucket-pipelines.yml below implements all three stages. It assumes a Pulumi program in an infra/ directory and stacks named acme/website/staging and acme/website/production:
# bitbucket-pipelines.yml
image: pulumi/pulumi:latest
pipelines:
# Pull request: preview the proposed changes.
pull-requests:
'**':
- step:
name: Preview infrastructure changes
script:
- cd infra
- pulumi install
- pulumi stack select acme/website/staging
- pulumi preview
# Merge to main: deploy to the staging environment.
branches:
main:
- step:
name: Deploy to staging
script:
- cd infra
- pulumi install
- pulumi stack select acme/website/staging
- pulumi up --yes
# Tag push: promote to production.
tags:
'release-*':
- step:
name: Deploy to production
script:
- cd infra
- pulumi install
- pulumi stack select acme/website/production
- pulumi up --yes
The pulumi/pulumi Docker image includes the Pulumi CLI and every language runtime, so the same pipeline works regardless of the language your program is written in. pulumi install installs the program’s language dependencies and required plugins.
pulumi preview reports the proposed changes without modifying any resources, giving reviewers a summary of what the merge would do. To let reviewers exercise the change in a live environment, pair the preview step with a Review Stack, which provisions an ephemeral stack for the pull request and destroys it when the pull request closes.
To promote a release, push a tag that matches the release-* pattern:
git tag release-2026-05-20
git push origin release-2026-05-20
Keeping production on its own stack and deploying it only from a tag makes each production update a single, traceable Git operation, and ensures production never deploys from an untested commit.
Cloud provider credentials
Your Pulumi program needs credentials for whichever cloud it manages. Supply them as Secured repository variables, or — better — use Pulumi ESC to broker short-lived cloud credentials so no provider keys are stored as repository variables at all.
Report results back to Bitbucket
The Pulumi Cloud Bitbucket version control integration posts pull request comments and commit status checks for every deployment, regardless of which CI/CD system triggers the run. Connecting it gives reviewers a summary of resource changes directly on the pull request.
The integration can also replace a hand-written pipeline entirely: with push-to-deploy and review stacks, Pulumi Cloud runs your updates on Pulumi-hosted infrastructure in response to Bitbucket events, with no bitbucket-pipelines.yml to maintain.
Additional resources
- Continuous delivery — overview of running Pulumi in CI/CD.
- Pulumi ESC — deliver credentials, secrets, and configuration to pipelines and developers consistently.
- OIDC issuers — exchange a CI/CD system’s OIDC token for a short-lived Pulumi access token.
- Bitbucket version control integration — pull request comments and commit statuses from Pulumi Cloud.
- Review Stacks — ephemeral environments created automatically for each pull request.
- CI/CD troubleshooting — diagnose common failures when running Pulumi in a pipeline.
Thank you for your feedback!
If you have a question about how to use Pulumi, reach out in Community Slack.
Open an issue on GitHub to report a problem or suggest an improvement.