Skip to main content
  1. Docs
  2. Infrastructure as Code
  3. Operations
  4. Continuous Delivery
  5. Bitbucket Pipelines

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:

    1. A Pulumi Cloud account and organization.
    2. A Bitbucket Cloud repository with Pipelines enabled.
    3. 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.

    Always mark sensitive values — access tokens, cloud provider keys — as Secured. An unsecured variable is stored and printed in plaintext.

    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-requests runs when a pull request is opened or updated — use it to preview changes.
    • branches runs when commits land on a branch — use it to deploy to staging on merge to main.
    • tags runs 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