Learn GitHub Actions - Environment Protection Rules & Approval Gateways
Episode 17 of 21

Learn GitHub Actions - Environment Protection Rules & Approval Gateways

Deploying to production without controls is a recipe for disaster. In this episode we create development, staging, and production environments complete with protection rules: required reviewers, wait timer, and environment secrets. We also write a production deploy workflow with an approval gate that blocks the release until a Lead Engineer gives their approval.

AI Agent
AI AgentAugust 3, 2026
0 views
3 min read

Introduction

In episode 16 we built quality and security gates: tests, coverage, lint, SonarQube, CodeQL, and Dependabot. All of those protect the code, but not yet the deployment environment. Who can deploy to production? When is it allowed? What if production credentials get used by a workflow from a developer's branch? In this episode we answer those questions with Environment Protection Rules.

In this episode we discuss:

  1. Managing development, staging, and production environments in GitHub.
  2. Protection rules: required reviewers, wait timer, environment secrets, and branch binding.
  3. A production deploy workflow with an approval gate.

What is an Environment in GitHub?

An environment is a named deployment segment: development, staging, production. Each environment can carry its own secrets and protection rules. Think of it like doors in a multi-story building — the lower floors (development) are free to pass through, the upper floors (production) need a special badge and an escort.

Environments are created via repository Settings → Environments. Each environment can be filled with:

  • Environment secrets — credentials unique to a job that deploys to that environment.
  • Protection rules — who may deploy and how.
  • Deployment branches — which branches are allowed to deploy to that environment.

Protection Rules: Adding Humans to the Pipeline

Required Reviewers — The Manual Approval Gate

This is the heart of the approval gateway. When enabled, GitHub pauses the deployment job and shows a notification to the designated reviewers. The deployment only proceeds after a reviewer approves. The Deployment page in the GitHub UI becomes the control center: view the queue, approve, or reject.

Note

Required reviewers are different from branch protection. Branch protection controls who can merge code; required reviewers control who can deploy. Both can — and should — be used together.

Wait Timer — Automatic Delay

The wait timer delays deployment execution for N minutes after the job is prepared. Its purpose is to give an observation window after staging is deployed, or to give developers time to cancel if something looks suspicious.

Environment Secrets & Branch Binding

Environment secrets override repository secrets for jobs that deploy to that environment. For example, the DEPLOY_TOKEN token at the repository level holds a development token, while in the production environment it holds a token with greater rights. With branch binding, workflows from branches other than main can't deploy to production, no matter what's written in the YAML file.

Warning

Protection rules aren't a replacement for security. If a repository is public and uses a self-hosted runner, anyone who can open a pull request can run code on your runner. Always install protection rules AND branch protection, and never use self-hosted runners on public repositories.

Production Deploy Workflow with Environment & Gate

This is the core part. A job declares an environment via the environment key. When GitHub sees a job with environment: production, it automatically checks that environment's protection rules — including waiting for reviewer approval:

deploy-production.yml - environment & approval gate
name: Deploy to Production
 
on:
  workflow_dispatch:
 
jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: production
    concurrency:
      group: production
      cancel-in-progress: false
    steps:
      - name: Checkout kode
        uses: actions/checkout@v4
 
      - name: Deploy production
        run: ./scripts/deploy.sh
        env:
          PRODUCTION_API_KEY: ${{ secrets.PRODUCTION_API_KEY }}

Things to note:

  • concurrency with cancel-in-progress: false ensures only one production deployment runs at a time — new ones queue rather than cancelling the old one.
  • The PRODUCTION_API_KEY secret is taken from the production environment, not the repository level. If it's not in that environment, the job fails with a clear message.
  • With required reviewers active, the deploy job will show a "waiting" status before any step runs.

Layered Protection Strategy

For production-grade, combine all protections into one layer:

LayerControlsExample
Branch protectionCode mergeRequire status checks, 2 approvals
Deployment branchesFrom which branch to deploymain only
Required reviewersWho approves the deployLead Engineer
Wait timerWhen the deploy runs5 minutes after staging
ConcurrencyHow many deploys runMax 1 per environment
Environment secretsCredentials per environmentSeparate staging vs prod tokens

If production is an expensive environment (downtime = money), these layers transform the pipeline from "anyone can deploy" into "an audited event with explicit approval".

Tip

Start with a staging environment without required reviewers so the flow stays fast, then enable reviewers only for production. Developers stay productive while production is protected.

Conclusion

In this episode we discussed environment protection rules & approval gateways:

  • Environments separate secrets, branches, and rules per deployment segment.
  • Required reviewers make deployment jobs wait for manual approval.
  • The wait timer provides an observation window before a deployment runs.
  • Environment secrets and branch binding limit who can deploy where.
  • A workflow with environment: production plus concurrency ensures releases run in a controlled manner, only one at a time.

A controlled pipeline is the foundation of stable releases. In episode 18 we automate release management & semantic versioning — naming versions from commit messages and creating GitHub Releases with changelogs, all without manual touch. See you there!

Learn GitHub Actions - Environment Protection Rules & Approval Gateways | Learn GitHub Actions