2025-11-18

CI/CD Pipelines That Scale

Green on main is table stakes. We spell out what runs on every pull request, what we gate before merge, and how we keep deploys boring on purpose.

6 min read

CI/CD Pipelines That Scale

Most teams agree CI is important; fewer agree on what actually has to run before code touches production. This article is about the gates we use so main stays shippable, feedback stays fast, and nobody is guessing what “green” means on a Friday night.

What we want from a pipeline

A useful pipeline does three things: it tells a developer quickly when they broke something obvious, it stops bad merges before they become everyone’s problem, and it makes production deploys repeatable enough that releasing is not a ceremony. Fancy tooling is optional; clear rules are not.

Testing gates

  • Lint and typecheck on every PR. Fail fast. If style and types drift, everything else gets harder to read and refactors get scary.
  • Unit tests on every push. Keep them fast: mock I/O, avoid hitting real databases in the default path, so people get signal in a few minutes and actually run them locally.
  • Integration tests on PR or before merge, with a real database or containers where it matters. Slower is fine here; you are catching contract and wiring bugs.
  • End-to-end tests on a schedule or before release, against staging, focused on money paths and sign-up flows. Not every click needs E2E coverage.

We usually require lint, typecheck, and unit tests before merge. We add integration and E2E as the product and risk grow, not because a blog checklist said so.

Deployment strategies

  • Branch-based: main (or a release branch) goes to production; preview deploys per PR for QA. Short-lived URLs beat “works on my machine” screenshots.
  • Tag or release-based: production only moves when someone pushes a version tag. Good when legal or compliance wants explicit release notes.
  • Environments: dev, staging, and production stay separate. Promote staging from main, then promote to production with a human click or a second automated step when you are ready.

GitHub Actions in practice

Reuse workflows and composite actions so you are not copying YAML into fifteen repos. Use a matrix when you really need multiple Node or Python versions. Cache npm, pnpm, or pip so CI minutes go to tests, not downloads. Secrets live in GitHub Secrets or a vault, never in logs. Use concurrency groups so a newer push on the same branch cancels an old run instead of burning minutes twice.

Closing thought

Good CI is opinionated. Pick the gates that match your risk, document them in one place, and change them when the product changes. We set up and maintain pipelines for product teams; if yours is slow, flaky, or unclear, that is usually fixable without rewriting the whole app.


Cogent Softwares, DevOps and engineering practices.