Continuous Deployment & Environments
🚪 Continuous Deployment & Environments
The Spectrum, Made Concrete
Chapter 1's distinction — CI (automated test) → Continuous Delivery (automated build/package, human clicks deploy) → Continuous Deployment (automated all the way, no human gate) — is implemented, in GitHub Actions, entirely through one feature.
🌍 GitHub Environments
A first-class GitHub feature (Settings → Environments) letting a repo define named environments — staging, production — each with its own secrets (Chapter 5's environment-specific secrets, made concrete) and its own protection rules.
| Protection Rule | Effect |
|---|---|
| Required reviewers | A specific person or team must manually approve before a job targeting this environment runs — the human gate that separates Delivery from Deployment |
| Wait timer | A mandatory delay before the job proceeds — time to notice and cancel a bad merge |
| Deployment branch restrictions | Only specific branches (e.g. main) can deploy to this environment — preventing an accidental deploy from a feature branch |
Referencing an environment in a job is a single line — environment: production — and that one line ties the job to both the environment's secrets and its protection rules simultaneously.
Staging vs Production: A Common Real Pattern
Auto-Deploy Staging, Gated Production
Push to main automatically deploys to staging — Continuous Deployment for staging, since the stakes are low and it's easy to revert. Deploying the same build to production requires a manual approval — Continuous Delivery for production, since the stakes are higher and a human makes the final call. This staging-auto/production-gated split is a genuinely common, sensible real-world pattern.
No Environment Concept vs Staging + Production Split
One Undifferentiated Deploy Job
Same secrets, same rules, deploys straight to production on every merge — no distinction between low-stakes and high-stakes targets at all.
Separate GitHub Environments
Staging deploys automatically; production requires a reviewer's approval — the same pipeline, different gates for different stakes.
💻 Coding Challenges
Challenge 1: Add a Wait Timer to a Production Deploy
Given the deploy-production job from this chapter's example, describe (conceptually, since this is configured in repo Settings, not YAML) what adding a 10-minute wait timer protection rule would change about the deployment flow.
Goal: Practice reasoning about a protection rule's practical effect, not just naming it.
Challenge 2: Restrict Production Deploys to main
Explain what deployment branch restrictions on the production environment would prevent, using a concrete scenario involving a feature branch.
Goal: Practice connecting a protection rule to a specific, realistic mistake it prevents.
Challenge 3: Diagnose an Unprotected "Production" Environment
A team names a job's environment production but never configures any protection rules for it in Settings. Explain what actually happens when that job runs, and why the environment's name alone provides no safety.
Goal: Practice recognizing this chapter's core gotcha in a concrete scenario.
Simply naming an environment "production" does not automatically make it safer or gated in any way. Without explicitly configured protection rules — required reviewers, branch restrictions, a wait timer — an environment named "production" behaves exactly like an unprotected job would, running immediately with no approval step at all. The false sense of safety comes purely from the name; the actual protection comes entirely from the rules configured for it in repo Settings, and forgetting to configure them defeats the entire point of using an Environment in the first place.
🎯 What's Next
Every piece is now in place — the final chapter is a capstone: Building a Full Pipeline for a Real App, combining build, test, Docker, and a staging/production deploy with an approval gate into one working pipeline.