Continuous Deployment & Environments

CI/CD Pipelines — Continuous Deployment & Environments
CI/CD Pipelines
Chapter 8 · Continuous Deployment & Environments

🚪 Continuous Deployment & Environments

Chapter 7 covered how deployment happens. This chapter covers when it happens and who approves it — formalizing Chapter 1's CI/Delivery/Deployment spectrum into concrete GitHub Actions mechanics.

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 RuleEffect
Required reviewersA specific person or team must manually approve before a job targeting this environment runs — the human gate that separates Delivery from Deployment
Wait timerA mandatory delay before the job proceeds — time to notice and cancel a bad merge
Deployment branch restrictionsOnly 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

jobs: deploy-staging: needs: build-and-push runs-on: ubuntu-latest environment: staging # no reviewers configured — deploys automatically steps: - run: ./deploy.sh staging deploy-production: needs: deploy-staging runs-on: ubuntu-latest environment: production # required reviewer configured in Settings steps: - run: ./deploy.sh 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.

→ Solution

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.

→ Solution

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.

→ Solution

⚠️ Gotcha: A "Production" Environment With No Protection Rules

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.