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

Using Codefresh with Pulumi

    Codefresh is a CI/CD platform for Kubernetes and Argo CD, now part of Octopus Deploy. Its CI pipelines run each step as a container, so you run Pulumi in a pipeline step that uses the official pulumi/pulumi container image. That image ships the Pulumi CLI and every language runtime, so the same pipeline works with a Pulumi program written in any supported language and targeting any cloud provider Pulumi supports.

    This guide assumes Pulumi Cloud as the state backend. Pulumi can also run in CI/CD with a self-managed backend, but Pulumi Cloud is assumed throughout because it simplifies pipeline authentication and is the most common choice.

    How Pulumi works with Codefresh

    To apply infrastructure changes, Pulumi runs your program with the Pulumi CLI. A Codefresh freestyle step provides that environment: it runs a set of commands inside a container image you choose. Point the step at pulumi/pulumi and it can run any pulumi command — install, preview, up — exactly as you would on your own machine.

    No special setup is required on the Codefresh side, and Pulumi runs on both free and paid accounts. You wire up authentication through pipeline variables, described below.

    Codefresh’s GitOps offering is built on Argo CD. If you deploy with Argo CD rather than Codefresh CI pipelines, see the Argo CD guide and the Pulumi Kubernetes Operator.

    Prerequisites

    Before you begin, make sure you have:

    1. A Pulumi Cloud account and organization.
    2. A Codefresh account with a pipeline connected to 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 an encrypted variable on the pipeline itself, or — to reuse it across pipelines — create a shared configuration context and import it. 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.

    You can remove the static token entirely with OpenID Connect (OIDC): the pipeline exchanges a short-lived OIDC token issued by Codefresh for a temporary Pulumi access token, so no long-lived credential is stored anywhere.

    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 pipeline stores nothing but its Pulumi access token.
    • Pipeline variables. Set the provider’s credentials as encrypted pipeline variables — for example, AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY for AWS — and expose them to the freestyle step.
    Never commit cloud credentials or the Pulumi access token to your repository. Keep them in encrypted pipeline variables or a shared secret context so the values stay protected and access is auditable.

    Configure a Codefresh pipeline

    A Codefresh pipeline is defined in a codefresh.yml file. The following pipeline clones your repository and runs Pulumi against a stack:

    version: '1.0'
    stages:
      - clone
      - deploy
    steps:
      clone:
        title: Clone repository
        type: git-clone
        stage: clone
        repo: '${{CF_REPO_OWNER}}/${{CF_REPO_NAME}}'
        revision: '${{CF_REVISION}}'
      deploy:
        title: Deploy with Pulumi
        type: freestyle
        stage: deploy
        image: pulumi/pulumi
        working_directory: '${{clone}}/infra'
        environment:
          - PULUMI_ACCESS_TOKEN=${{PULUMI_ACCESS_TOKEN}}
        commands:
          - pulumi install
          - pulumi stack select acme/website/staging
          - pulumi up --yes
    

    The example assumes a Pulumi program in an infra/ directory. pulumi install installs the program’s language dependencies and required plugins, so the same step works for a program written in any supported language.

    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. Codefresh Git triggers distinguish pull request, branch, and tag events, so you can map each stage of the workflow to its own trigger.

    Preview infrastructure changes in a pull request

    When a pull request is opened, run a dry run instead of a deployment. Attach a Git trigger that fires on pull request events and have the freestyle step run pulumi preview:

        commands:
          - 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. Attach a Git trigger that fires on pushes to the main branch:

        commands:
          - 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:

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

    Configure this pipeline’s Git trigger to fire on tag push events rather than branch pushes. Promotion then becomes a single, traceable Git operation, and production never deploys from an untested commit.

    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 with short-lived, exchanged credentials.
    • Review Stacks — ephemeral environments for pull requests.
    • Argo CD — deploy Pulumi stacks with Argo CD, which underpins Codefresh GitOps.