An environment attaches secrets, reviewers and a branch restriction to a job, which puts the gate somewhere a convention cannot be forgotten.
jobs:
deploy:
environment:
name: production
url: https://example.com
steps:
- run: ./bin/release "$DIGEST"
# configured on the repository rather than in this file:
# required reviewers: two
# wait timer: 5 minutes
# deployment branches: main only
# secrets: scoped to this environment
Scoping the secrets to the environment is what does the security work — a job without environment: production cannot read the production credentials at all, so a workflow added by anybody cannot deploy by accident. The wait timer is more useful than it looks: five minutes between approval and execution is enough to cancel a deploy somebody immediately regretted.