Skip to content

Deployment environments

A GitHub Actions job that references an environment can only run once the protection rules of the environment are satisfied, and only then gets access to the secrets of the environment. Environments are therefore the right place for credentials that deploy or publish something.

Property Effect
deployment_branch_policy, branch_policies all: no restriction, protected: only protected branches, selected: only the branches and tags listed in branch_policies
reviewers, prevent_self_review users or teams who must approve the job, optionally not the person who triggered it
wait_timer minutes to wait before the job can run
secrets, variables values only available to jobs that use the environment

Users with GitHub Free can only configure environments for public repositories, and some protection rules have limited availability for private repositories, see Managing environments for deployment.

Protect publishing credentials

The following environment is only available to workflows running for a tag starting with v, and requires the approval of a release manager other than the person who triggered the workflow:

orgs.newOrg('my-project', 'my-org') {
  _repositories+:: [
    orgs.newRepo('my-library') {
      environments+: [
        orgs.newEnvironment('release') {
          deployment_branch_policy: "selected",
          branch_policies+: [
            "tag:v*", // (1)!
          ],
          reviewers+: [
            "@my-org/release-managers",
          ],
          prevent_self_review: true,
        },
      ],
    },
  ],
}
  1. Patterns for tags start with tag:, see Branch or Tag.

Open in the Playground

The publishing job of the workflow then references the environment:

jobs:
  publish:
    runs-on: ubuntu-latest
    environment: release
    steps:
      ...

Warning

An environment with deployment_branch_policy: "all" and no reviewers does not protect its secrets: a workflow running on any branch, e.g. a branch pushed by any user with write access, can use them. This also applies to environments used for publishing with OpenID Connect, as the trust configuration of the target system often identifies the repository, the workflow or the environment, but not the branch.

Recommendation

Restrict every environment that holds credentials or is trusted by an external system to the branches or tags that are allowed to deploy, and protect these branches and tags as well, see Protecting branches and Protecting tags and releases.

Require a manual approval

An environment without secrets can serve as a manual approval step, e.g. before an expensive workflow runs or before a workflow runs with elevated permissions:

orgs.newOrg('my-project', 'my-org') {
  _repositories+:: [
    orgs.newRepo('my-repo') {
      environments+: [
        orgs.newEnvironment('manual-approval') {
          reviewers+: [
            "@my-org/maintainers",
          ],
        },
      ],
    },
  ],
}

Open in the Playground

Up to 6 users or teams can be listed as reviewers, and the approval of one of them is sufficient.

GitHub Pages

When GitHub Pages is enabled for a repository, GitHub automatically creates an environment named github-pages. Declare it in the configuration, otherwise plan reports it as a resource to delete:

orgs.newOrg('my-project', 'my-org') {
  _repositories+:: [
    orgs.newRepo('my-website') {
      gh_pages_build_type: "workflow",
      environments+: [
        orgs.newEnvironment('github-pages') {
          deployment_branch_policy: "selected",
          branch_policies+: [
            "main",
          ],
        },
      ],
    },
  ],
}

Open in the Playground

See Common repository patterns for the other GitHub Pages settings.

Require a successful deployment before merging

A ruleset or a branch protection rule can require that changes were successfully deployed to an environment before they are merged. The required environments must be defined in the same repository:

orgs.newOrg('my-project', 'my-org') {
  _repositories+:: [
    orgs.newRepo('my-service') {
      environments+: [
        orgs.newEnvironment('staging'),
      ],
      rulesets: [
        orgs.newRepoRuleset('default-branch') {
          include_refs+: [
            "~DEFAULT_BRANCH",
          ],
          required_pull_request+: {
            required_approving_review_count: 1,
          },
          required_status_checks: null,
          requires_deployments: true,
          required_deployment_environments+: [
            "staging",
          ],
        },
      ],
    },
  ],
}

Open in the Playground

Environments created by GitHub features

Besides github-pages, some GitHub features create or use environments with a specific name. Before removing such an environment from the configuration, check whether it is still used. For example, GitHub moved the secrets of the Copilot cloud agent from an environment named copilot to dedicated agent secrets, see the GitHub changelog.