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

Using TeamCity with Pulumi

    TeamCity is a CI/CD server from JetBrains, available both as self-hosted TeamCity On-Premises and as the hosted TeamCity Cloud. You run Pulumi in TeamCity by adding a build step that invokes the Pulumi CLI, so the same build configuration works with a Pulumi program written in any supported language and targeting any cloud provider Pulumi supports.

    This guide assumes Pulumi Cloud as your backend. Pulumi Cloud isn't required to run Pulumi in CI/CD — Pulumi also supports self-managed backends — but the access token, OIDC, and ESC features described here are specific to Pulumi Cloud.

    How Pulumi works with TeamCity

    A TeamCity build configuration is an ordered sequence of build steps. To apply infrastructure changes, Pulumi runs your program with the Pulumi CLI, so you add a Command Line build step that runs pulumi commands — install, preview, up — exactly as you would on your own machine.

    The Command Line runner can execute its script inside a Docker container. Point it at the official pulumi/pulumi image, which ships the Pulumi CLI and every language runtime, and the step works for a program in any supported language with no extra setup. If you prefer to run directly on the build agent, install the Pulumi CLI on the agent instead.

    You can define build configurations through the TeamCity UI or version-control them alongside your code with the Kotlin DSL.

    Prerequisites

    Before you begin, make sure you have:

    1. A Pulumi Cloud account and organization.
    2. A TeamCity project with a build configuration attached to a VCS root for your Git repository.
    3. A Pulumi program in that repository. If you don’t have one yet, follow a Get started guide.

    Authenticate with Pulumi Cloud

    When your pipeline uses Pulumi Cloud as its backend, it needs only a single Pulumi access token to operate. Pulumi reads the token from the PULUMI_ACCESS_TOKEN environment variable and authenticates without an interactive login.

    Store the token outside of source control. Add it as a build parameter of type Password named env.PULUMI_ACCESS_TOKEN so TeamCity keeps the value encrypted and masks it in build logs. Define it on a parent project to reuse it across every build configuration underneath. Prefer an organization or team token over a personal token so the pipeline’s identity isn’t tied to an individual.

    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.

    Provide cloud credentials

    When Pulumi runs, your program also needs credentials for the cloud provider it manages. You can supply them in one of two ways:

    • Pulumi ESC (recommended). Configure an ESC environment to broker short-lived cloud credentials through OIDC. Your program receives temporary credentials scoped to exactly what it needs, and the build stores nothing but its Pulumi access token.
    • Build parameters. Set the provider’s credentials as Password-type build parameters — for example, env.AWS_ACCESS_KEY_ID and env.AWS_SECRET_ACCESS_KEY for AWS — so they’re exposed as environment variables to the build step.
    Never commit cloud credentials or the Pulumi access token to your repository. Keep them in Password-type build parameters or an ESC environment so the values stay encrypted and access is auditable.

    Configure a TeamCity build

    Add a Command Line build step that runs Pulumi against a stack. Set the step’s runner to run inside the pulumi/pulumi Docker container, and use the following custom script:

    pulumi install
    pulumi stack select acme/website/staging
    pulumi up --yes
    

    pulumi install installs the program’s language dependencies and required plugins, so the same step works for a program written in any supported language. The step picks up the env.PULUMI_ACCESS_TOKEN build parameter automatically, so no pulumi login call is needed.

    If your Pulumi program lives in a subdirectory of the repository, set the build step’s Working directory to that path.

    Build a trunk-based CI/CD 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. In TeamCity, a VCS root’s branch specification controls which branches a build configuration watches, and a VCS trigger starts a build when those branches change — so you can map each stage of the workflow to its own build configuration.

    Preview infrastructure changes in a pull request

    When a pull request is opened, run a dry run instead of a deployment. Add the Pull Requests build feature so TeamCity discovers pull request branches, and have the Command Line step run pulumi preview:

    pulumi install
    pulumi stack select acme/website/staging
    pulumi preview
    

    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, use a Review Stack, which provisions an ephemeral stack for the pull request and destroys it when the pull request closes.

    Deploy to staging on merge to the main branch

    When a pull request merges, run pulumi up against an environment that receives continuous delivery, such as a shared development or staging environment. Use a build configuration whose VCS trigger fires on changes to the main branch:

    pulumi install
    pulumi stack select acme/website/staging
    pulumi up --yes
    

    Promote to production with a git tag

    Production updates should be deliberate. Keep production on its own stack and deploy it only when you push a release tag — for example, a moving production tag that you advance to a commit already validated in staging.

    Give the production build configuration a VCS root with a branch specification that watches tags, such as +:refs/tags/*, and target the production stack:

    pulumi install
    pulumi stack select acme/website/production
    pulumi up --yes
    

    Promotion then becomes a single, traceable Git operation, and production never deploys from an untested commit.

    Report results on pull requests

    Independently of TeamCity, Pulumi offers native version control integrations for popular Git hosts. With one configured, Pulumi Cloud posts infrastructure-change summaries as pull request comments and status checks, and links each stack update back to the commit and pull request that produced it. See the Version Control page for the integrations currently available.

    Speed up builds with caching

    A clean build agent starts with an empty plugin cache, so Pulumi re-downloads its provider plugins on every run. How you avoid that depends on your agents:

    • Persistent agents retain Pulumi’s plugin directory (~/.pulumi/plugins) between builds when the CLI runs directly on the agent, so the cache warms itself after the first run. If the step runs inside the pulumi/pulumi container, the plugin directory is discarded with the container — mount a persistent volume for it, or use the custom builder image described below.
    • Ephemeral or cloud agents start fresh each time. Bake the provider plugins into a custom builder image: derive it from the official pulumi/pulumi image, pulumi plugin install the providers your program uses, and run the Command Line step in that image. This is the most deterministic option even where a cache exists — see the plugins documentation.

    Additional resources

    • Continuous delivery — overview of running Pulumi in CI/CD.
    • CI/CD troubleshooting guide — diagnose common failures when running Pulumi in a pipeline.
    • Pulumi ESC — deliver credentials, secrets, and configuration to pipelines and developers consistently.
    • OIDC Issuers — eliminate static tokens on CI/CD systems that can issue OIDC tokens.
    • Review Stacks — ephemeral environments for pull requests.
    • Version Control — connect Pulumi Cloud to your Git host for pull request reporting.