GitHub Actions Environments and Approvals

Deploying code to a live website carries risk. An environment is a named deployment target, such as staging or production, with its own rules and secrets. Approvals let a human check the work before GitHub pushes it to a sensitive target.

Environments in Simple Words

Think of a theater. Rehearsal happens in a practice room, and the real show happens on the main stage. Nobody opens the curtain on the main stage until the director says go. Staging is the practice room, production is the main stage, and the approval is the director's signal.

Create an Environment

Open your repository, choose Settings, then Environments, and select New environment. Type a name such as production. GitHub also creates environments automatically when a workflow mentions a new name.

Protection Rules

Required Reviewers

Pick specific people or teams who must approve. GitHub allows up to six reviewers, and one approval is enough to continue.

Wait Timer

A timer delays the job by a set number of minutes. The pause gives teams a window to cancel a bad release.

Deployment Branches

A branch rule limits which branches may deploy. Allowing only main blocks experimental branches from touching production.

Environment Secrets and Variables

Each environment holds its own secrets and variables. The production database password lives only in the production environment. Jobs targeting staging cannot read it.

Use an Environment in a Workflow

The environment key links a job to a target.

name: Deploy Site

on:
  push:
    branches: [ main ]

jobs:
  deploy-staging:
    runs-on: ubuntu-latest
    environment:
      name: staging
      url: https://staging.example.com
    steps:
      - run: echo "Deploying to staging"

  deploy-production:
    needs: deploy-staging
    runs-on: ubuntu-latest
    environment:
      name: production
      url: https://www.example.com
    steps:
      - run: echo "Deploying to production"
      - run: echo "API key length is ${#API_KEY}"
        env:
          API_KEY: ${{ secrets.PROD_API_KEY }}

The url value appears as a clickable link on the run summary page after the job succeeds.

Approval Flow Diagram

+--------+     +--------------+     +----------------+     +------------+
| Build  | --> | Staging      | --> | WAIT: reviewer | --> | Production |
| & test |     | auto deploy  |     | clicks Approve |     | deploy     |
+--------+     +--------------+     +----------------+     +------------+
                                           |
                                      Reject: stop

How a Reviewer Approves

When a job reaches a protected environment, the run pauses with a Waiting status. Reviewers receive a notification. They open the run, click Review deployments, tick the environment, add an optional comment, and choose Approve and deploy or Reject. Rejection fails the job and stops everything after it.

The secrets stay locked until approval arrives. A job cannot read environment secrets while it waits.

Separate Secrets Example

Secret NameStaging ValueProduction Value
DB_PASSWORDTest database passwordLive database password
API_URLhttps://api-staging.example.comhttps://api.example.com

The workflow code stays identical. The environment chooses which value the job receives.

Availability Notes

Environments work in public repositories on every plan. Private repositories need a paid plan for protection rules such as required reviewers. Check the current GitHub plan page for exact details.

Best Practices

  • Require approval for production only. Staging should flow automatically.
  • Name at least two reviewers so one absence never blocks a release.
  • Restrict deployment branches to protected branches.
  • Keep production secrets out of repository-level secrets.

The Deployments section on the repository home page lists every deployment with its status, time, and environment. The list gives teams a clear audit trail of what shipped and when.