This is the pipeline we stand up on every engagement. It is deliberately boring: GitHub Actions for CI, a container registry, and a blue-green release behind a health-checked load balancer.
Stage 1 — every push, under four minutes
- Install with a frozen lockfile, cache by lockfile hash.
- Lint and type-check — a warning fails the build, always.
- Unit tests with coverage thresholds that can only go up.
- Secret scanning and dependency audit — Trivy and
npm auditin the same job.
Stage 2 — every merge to main
- Build the image, tag it with the commit SHA, push it.
- Deploy to a preview environment with a real database seed.
- Run Playwright end-to-end tests against the preview.
- Post the preview URL back into the pull request automatically.
Stage 3 — production releases
- Blue-green: the new colour spins up, a smoke test runs, the load balancer flips.
- If the health check does not turn green in thirty seconds, roll back automatically.
- The deploy log carries the SHA, the author, the migration set and the previous image ID.
Rules we do not break
- No direct push to
main. Ever. - No deploy without a green pipeline, even for a hotfix.
- Every production deploy has a tested rollback path.
Total cost: about two days to stand up, and it has paid for itself every month since.