Pipeline Anatomy — Stages, Gates, Environments & Promotion
Stages, soft/hard gates, environments, and build-once promotion anatomy with GitHub Actions sketch + promotion helpers.
- 1Gist
- 2Maps
- 3Q&A
- 4Sandbox
Voice readout needs Web Speech Synthesis in this browser.
A new critical finding shows up on a pull request
Prefer
Hard-fail, with an expiring exception
New critical findings block the branch that can ship. An accepted risk has an owner and an expiry.
- main stays a place you can promote from.
- The exception is a record, so the next audit can see it.
- Flakes go to quarantine with an owner. They do not mute the job forever.
Alternative
Permanent soft-fail
The check posts a warning and the pipeline stays green. After a month nobody reads the warning.
- The team learns that red annotations are decoration.
- A real critical finding looks like last week's noise.
- Promotion policy becomes a hope.
Order the graph so failure is cheap and promotion is explicit
Serial stages are simple. A DAG is faster when artifact handoff is explicit. Either way, production consumes the digest staging already ran.
- 1
Fail fast
Lint, types, unit tests, and secret scan run before the expensive build. - 2
Produce the artifact
Build, push the digest, then attach the SBOM and the signature. - 3
Test the thing you ship
Integration, contracts, and the image scan use that digest. - 4
Promote the same digest
Staging deploys it. Smoke runs there. Production reuses it after the gate.
Overview
A pipeline is a directed graph of stages (groups of jobs), gates (policy checks that block promotion), and environments (where artifacts run). Good anatomy makes the happy path obvious, the failure mode diagnosable, and promotion of the same digest explicit.
Bad anatomy is copy-pasted jobs, a mutable latest tag, and a deploy step that rebuilds from scratch. Interviewers ask you to draw this graph and defend each gate. Incidents often trace to a missing gate, or to the wrong order: deploy, then migrate, then notice.
The map is the hub. This page is the graph.
Stages, jobs, steps, gates
| Concept | Meaning | Example |
|---|---|---|
| Stage | Logical phase, often with an entry rule | verify, build, deploy-staging |
| Job | Unit of scheduling, often one runner | unit-tests, docker-build |
| Step | Command inside a job | npm ci, pytest |
| Gate | Condition that must pass before promotion | coverage, reviewers, vuln policy, smoke |
Verify is cheap signal on the change: lint, unit, secret scan. Build produces the shippable artifact and the attestations. Mixing them makes cache invalidation and failure attribution harder. That split is the first interview answer on this page.
Reference anatomy
The source sketch boxed verify, build, test, and promote into side-by-side groups. Those groups are the same four phases. This page numbers them in one column so the labels stay readable.
Flow
- 1
1. Verify lint, unit, secrets
- next2. Build and push digest
- 2
2. Build and push digest
- next3. Attach SBOM and sign
- 3
3. Attach SBOM and sign
- next4. Integrate, contract, scan
- 4
4. Integrate, contract, scan
- next5. Promote staging by digest
- 5
5. Promote staging by digest
- next6. Smoke, then prod gate
- 6
6. Smoke, then prod gate
Lesson map
Pipeline Anatomy — Stages, Gates, Environments & Promotion
Stages, soft/hard gates, environments, and build-once promotion anatomy with GitHub Actions sketch + promotion helpers.
Architecture. Architecture
Select a node to see why it exists, or an edge to see the protocol, direction, effect, and consequence.
Mermaid export
flowchart TB a["1. Verify lint, unit, secrets"] b["2. Build and push digest"] c["3. Attach SBOM and sign"] d["4. Integrate, contract, scan"] a -->|1. Verify lint, unit, secrets| b b -->|2. Build and push digest| c c -->|3. Attach SBOM and sign| d
Ordering rules:
- Fail fast on lint, types, and unit tests before the expensive build.
- Produce the artifact before integration that needs the real image, or share one local build cache so every job sees the same bits.
- Scan the thing you ship (the image and the SBOM), not only the source tree.
- Run schema changes as an explicit job, ordered with expand/contract. Mechanics live in Zero-Downtime Database Migrations. A silent "migrate on boot" in production is an incident generator.
- Production promotion consumes the staging-proven digest. It does not rebuild.
Soft gates and hard gates
| Gate | Soft (warn) | Hard (block) | Notes |
|---|---|---|---|
| Lint / format | Early branches | main and release | Autofix bots reduce the pain |
| Unit tests | Never soft on main | Always hard | Quarantine flakes. Do not mute the job |
| Coverage delta | Warn on the pull request | Hard on release | An absolute percentage is a vanity trap |
| SCA / CVE | Warn on low severity | Block on critical or high policy | Needs a grace period and an exception process |
| Approval | — | Production and prod data | Environment protection rules |
| Smoke | — | After deploy | Failed smoke blocks the next promotion or rolls back |
A required manual production approval is an environment protection rule with required reviewers. Record who approved and which digest they approved. A job that sleeps until someone clicks a button in the log is not an audit trail.
A merge queue changes the timing, not the gates. It retests the would-be merge commit so main stays green, and it shifts some load from "after merge" to "before land."
Environments and promotion models
Named environments with protection rules. dev, then staging, then production. Each environment can require reviewers, a wait timer, or a branch restriction. GitHub Environments and GitLab environments are this model.
Ephemeral pull-request previews. Every pull request gets a short-lived stack, destroyed on merge or close. Review fidelity goes up. Cost, seed data, and secrets need a budget. The branching lesson owns the design.
Artifact channel promotion. Channels such as candidate and stable move a digest without a second build. Desktop, mobile, and container release trains use this. It is build-once only if the registry refuses to overwrite the digest.
| Model | Pros | Cons |
|---|---|---|
| Environment protection | Clear audit, human gates | Can become rubber-stamp theater |
| Ephemeral previews | High review fidelity | Cost, data seeding, secrets |
| Channel promotion | True build-once | Needs a registry and a policy tool |
Monorepos add path filters and an affected-project graph so only touched services run the full build and deploy. A shared library triggers its downstream consumers. Path-filter cost is the CI performance lesson.
A minimal GitHub Actions sketch
This is anatomy, not a production pipeline. id-token: write is the OIDC permission the supply-chain page explains. The digest output is the handoff the artifacts page formalizes.
# .github/workflows/ci.yml — anatomy sketch
name: ci
on:
pull_request:
push:
branches: [main]
jobs:
verify:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "20"
cache: npm
- run: npm ci
- run: npm run lint && npm test -- --coverage
build:
needs: verify
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
packages: write
outputs:
digest: ${{ steps.push.outputs.digest }}
steps:
- uses: actions/checkout@v4
- name: Build and push
id: push
run: echo "digest=sha256:REPLACE_ME" >> "$GITHUB_OUTPUT"
staging:
if: github.ref == 'refs/heads/main'
needs: build
environment: staging
runs-on: ubuntu-latest
steps:
- run: echo "Deploy digest ${{ needs.build.outputs.digest }} to staging"Pipeline as code is reviewable and reproducible. A click-ops UI is faster for an experiment. Anything that touches production stays as code, with a reusable template so the YAML does not sprawl.
Helpers you can run
Press Run. Snippets must be self-contained — no network, files, or native modules.
Press Run. Snippets must be self-contained — no network, files, or native modules.
Interview Q&A
What belongs in verify versus build?
Answer
Verify is cheap signal on the change: lint, unit tests, secret scan. Build produces the shippable artifact and the attestations. Mixing them makes cache invalidation and failure attribution harder.
How do you model a required manual production approval?
Answer
Use environment protection rules with required reviewers. Record the approver and the digest. A job that sleeps until a human notices the log is not an approval record.
Should database migrations be a pipeline stage?
Answer
Yes, as an explicit job with expand/contract discipline, ordered relative to the app deploy. The migration pattern itself is Zero-Downtime Database Migrations. Silent migrate-on-boot in production is an incident generator.
What is a merge queue, and how does it change anatomy?
Answer
A merge queue serializes landings so main is retested at the would-be merge commit. Some load moves from "after merge" to "before land." The gates stay the same.
Soft-fail versus hard-fail for SAST?
Answer
New critical findings hard-fail. A known accepted risk is documented and it expires. A permanent soft-fail trains the team to ignore the check.
How do multi-service monorepos structure stages?
Answer
Path filters plus an affected-project graph. Touched services run the full build and deploy. A shared library triggers downstream consumers. Naive path ignores can miss a generated client. That tradeoff is the performance lesson.
Where do smoke tests live?
Answer
After deploy, in the target environment, against the promoted digest. Failure blocks the next promotion or triggers rollback. Smoke is a gate on the digest you shipped, not a second unit suite.
Pipeline as code versus a click-ops UI?
Answer
Pipeline as code is reviewable and reproducible. A UI is faster for an experiment. Production paths stay as code, with templates so every service does not invent a new YAML dialect.
Pitfalls
- A deploy job that rebuilds because copying the digest output felt like extra work.
- Coverage as a single absolute percentage with no delta and no release gate.
- Approvals that rubber-stamp whatever digest happens to be
latest. - Secret scan after the image push, so a leaked key already left the runner.
- Four copies of the same job graph, one per environment, drifting apart.
Sketch verify, build, attest, test, staging, and the production gate for a service you know. Say which gate is hard on a pull request, which gate is hard only for production, and which output string the staging job is allowed to deploy.