Case index CI/CD pipeline with gates that block and a recorded rollback / 02 of 04

Claim

The release lane gates on five live smoke assertions: a build that misses one is rolled back to the previous release, and the hosted demo page records the order.

Eight PR gates feed one required ci-ok check; the demo page starts the gate run, ships a bad image, and redeploys the previous release.

(GitHub Actions, Docker Buildx, Trivy, Fastify, PostgreSQL)

Live

Click Run the gates and watch each job turn green.

What to expect on the free instance

  • The free instance sleeps after 15 minutes idle and takes about a minute to wake.
  • The demo page starts one action at a time; the buttons stay disabled while a run is in flight.
  • A full gate run takes several minutes and spends the repository's Actions minutes.

Five-step walkthrough

01 / What it is

What it is

A Fastify invoice API on PostgreSQL 16 with a GitHub Actions workflow, a Dockerfile and a release script. The workflow defines eight gates and a ci-ok aggregator; the hosted demo page dispatches the gate run, the bad-image run and the rollback from a server-side token.

The release lane swaps a current pointer, waits on /health and /ready, runs five smoke assertions and redeploys the previous release when an assertion misses.

Pipeline demo page mid-run: the Run the gates card reads running under run 40948040956, and the job list shows image, lint, test (22), migration-gate, typecheck, bundle-size and git-leaks all in progress.
Demo page mid-run: the gate card reads running under run 40948040956, and image, lint, test (22), migration-gate, typecheck, bundle-size and git-leaks each read in progress.
Pipeline demo page rollback: a six-step timeline reading deploy.start, health.ok, smoke.fail, rollback.start, rollback.health.ok and rollback.smoke.ok, with the two deploy ids dep-dbhpqeeqcfc7384uzc0 and dep-dbhpq88b9cc7c7394bfg in the footer.
Rollback on the demo page: six steps from deploy.start to rollback.smoke.ok, with dep-dbhpqeeqcfc7384uzc0 live and dep-dbhpq88b9cc7c7394bfg previous.
Pipeline demo page after the bad-image run: the build job reports success, the Trivy job reports a HIGH finding, and the banner names bad-image-trivy while the run finishes red.
Bad-image run: the build job reports success, the Trivy job reports a HIGH finding, and the banner names bad-image-trivy while the run finishes red.

02 / The hard part

The hard part

A process can answer /health and /ready while its invoice route returns errors, and a release with no return path leaves that process in front of traffic. The hard part is deciding the deploy on what the service does, not on what its health endpoint reports.

03 / The decision

The decision

Smoke decides the release; health starts the wait

Decision After the health wait, run five smoke assertions and roll back when any assertion misses, then re-smoke the restored release.

Rejected alternative Treat /health and /ready as success; a process can answer both while its invoice route returns errors.

Cost Every release pays for five assertions and a rollback restart, and rollback returns to the previous release.

Evidence deploy.log records deploy.start, health.ok, smoke.fail, rollback.start, rollback.health.ok, rollback.smoke.ok.

04 / The failure it refuses

The failure it refuses

Pathological case

The process answers /health and /ready while the invoice route returns errors, or a release is promoted with no way back to the previous build.

Mechanism The release lane swaps the current pointer, waits on /health and /ready, then runs five smoke assertions; any miss triggers rollback.start, restores the previous release, and re-runs the same smoke gate. deploy.log records every step.

05 / Measured

Measured

Local run: nine integration tests passed, the smoke gate passed 5/5 assertions with /ready p95 7.7 ms, and demo.txt records the rollback order. The workflow structure check found 20 pinned actions and zero unpinned.

Green demo run 40929946794; red run 40930412365 stopped at bad-image-trivy with 10 HIGH. A rollback moved Render from dep-dbhonnk9v7es73bg70f0 to dep-dbhoo3rbc2fs73f1b85g.

Measured results and the method behind each value.
Metric Value Method Artifact
Release, broken release and rollback healthy 5/5 · broken smoke FAIL · rollback 5/5 bash scripts/demo.sh against the local release on 127.0.0.1:8787; summary in docs/evidence/demo.txt docs/evidence/demo.txt
Image scan 0 CRITICAL/HIGH findings with ignore-unfixed · exit 0 trivy image --severity CRITICAL,HIGH --ignore-unfixed --exit-code 1 invoice-api:slim docs/evidence/trivy-local.txt
Workflow structure 9 jobs incl. ci-ok · 20 pinned uses · 0 unpinned node structural check over .github/workflows/pr.yml docs/evidence/workflow-structure.txt

Gate checks (test counts, not metrics)

  • Smoke gate: 5/5 assertions · /ready p95 7.7 ms. bash scripts/smoke.sh against the local release; five named behaviours docs/evidence/smoke.txt
  • Verification gate: 9/9 integration tests · verify: ok · exit 0. bash scripts/verify.sh (eslint, tsc --noEmit, vitest run) docs/evidence/verify-latest.txt

Invariants and their tests

Back to the case index