Pipeline stages

What it is

A pipeline is a sequence of stages, each of which either passes or fails the change it is running against. The usual shape is a fast check that the code compiles and its style passes, then the test suite, then a build producing an artifact, then one or more deployments. Each stage answers a question, and the order is chosen so that the cheapest stage rejects the most bad changes.

Why it matters

The order of a pipeline is a deliberate economic decision. A ten-second compile check that fails half of the obviously broken builds saves the twenty minutes a full suite would have spent on them. Fast feedback also changes behaviour: when a failure arrives in a minute the author fixes it immediately, and when it arrives in an hour they have moved on and the failure becomes somebody’s afternoon. A pipeline that is slow is a pipeline whose results are ignored.

Core ideas

Every stage answers one question

Compilation asks “is this syntactically and structurally valid”; tests ask “does it behave”; the build asks “can this be packaged”; the deployment asks “does it run here”. Mixing questions in one stage makes the failure message ambiguous and forces everything to rerun when one thing changes.

check -> test -> build artifact -> deploy to staging -> deploy to production
seconds   minutes     minutes         minutes            gated by approval

Build once and promote the artifact

The artifact that reaches production should be the one that passed the tests, identified by a version or digest. Rebuilding for each environment reintroduces every difference the pipeline was meant to remove, and it means the thing tested is not quite the thing shipped.

Feedback time sets the pace of the whole team

A pipeline that takes forty minutes for a small change is a queue everyone waits in. Parallelising independent test groups, caching dependencies, and not running the slow end-to-end suite on every commit all reduce it. The slow suite belongs on a schedule or before deployment, not on the fast path.

The main branch must stay green

A red main branch blocks everyone and destroys the trust that makes the practice work. When a failure appears, fixing or reverting it takes priority over any new work. This is a cultural rule enforced by the tooling: a pipeline that permits merging onto a red main branch is teaching people to ignore it.

Deployment is a separate decision from testing

Building and testing can run automatically on every change; releasing to production usually should not, or at least should be an explicit approval. Keeping them as separate stages lets the same pipeline serve both without coupling the decision to the mechanics.

Secrets belong to the pipeline, not to the log

Credentials are supplied by the pipeline’s secret store, masked where the platform supports it, and scoped to the stages that need them. A token that a test prints in a log is a leaked token, and it will be found.

Practice

Order a pipeline by feedback speed

Take a project with a slow test suite and a fast compile check. Arrange the stages so the fastest check runs first, then split the suite so the quick portion runs on every change and the slow portion runs before deployment.

Done when: a change that fails to compile reports failure in under a minute, and the slow suite no longer blocks the fast path.

Promote one artifact across two environments

Build an artifact once, record its version, and deploy that exact version to staging and then production.

Done when: the version identifier is identical in both environments and neither deployment rebuilt anything.

Common mistakes

  • Running a slow suite on every commit — feedback arrives too late to change behaviour; fix: split fast and slow tests and schedule the slow ones.
  • Rebuilding per environment — the tested artifact is not the shipped one; fix: build once and promote by version.
  • Allowing merges onto a failing main branch — everyone’s work is blocked and trust in the pipeline dies; fix: make fixing the main branch the first priority.
  • Printing secrets into build logs — the credential is exposed to everyone who can read the log; fix: use masked secrets and restrict their scope.
  • Coupling the release decision to the test run — a passing build is treated as a licence to ship; fix: keep deployment a separate, deliberate stage.

Go deeper