Environments, approvals and concurrency

GitHub Actions · Advanced · 12 min

Safe continuous deployment needs approvals, per-environment secrets and a guarantee two deploys never race.

An environment (Settings, Environments) represents a deployment target such as staging or production. A job opts in with environment: production, and the environment can enforce protection rules before the job starts:

  • Required reviewers: the job waits until a listed person or team approves.
  • Wait timer: delay the job by up to 30 days.
  • Deployment branches and tags: only allow, say, main and v* tags to deploy.

Environments also hold their own secrets and variables, which are only exposed to jobs referencing that environment. Combined with branch rules, this means a workflow on a feature branch cannot read production credentials. Deployments appear on the repository page with links to environment.url.

Concurrency controls overlapping runs. All runs or jobs with the same concurrency.group string form a queue where at most one runs and at most one waits; a newer pending run replaces the older pending one. cancel-in-progress: true cancels the running one instead, ideal for PR builds where only the latest commit matters. For deployments use cancel-in-progress: false so a half-finished deploy is never killed.

Typical groups: ${{ github.workflow }}-${{ github.ref }} for CI, and a fixed deploy-production for deploys.

Example

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: ${{ github.event_name == 'pull_request' }}
jobs:
  deploy:
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    environment:
      name: production
      url: https://shop.example.com
    concurrency:
      group: deploy-production
      cancel-in-progress: false      # never kill a running deploy
    steps:
      - run: ./deploy.sh
        env:
          TOKEN: ${{ secrets.PROD_DEPLOY_TOKEN }}   # environment secret

Remember

  • environment: gates a job with reviewers, timers and branch rules
  • Environment secrets are only visible to jobs in that environment
  • concurrency groups serialize runs; cancel-in-progress kills the running one

Watch out for

  • Using cancel-in-progress: true on deploy jobs, leaving systems half-deployed.

Check yourself

  1. Three pushes arrive quickly for a group without cancel-in-progress. What happens?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: docs.github.com/en/actions/managing-workflow-runs-and-deployments/managing-deployments/managing-environments-for-deployment