On this page
What Are the Stages of a CI/CD Pipeline?
A CI/CD pipeline runs source, build, test, package, deploy, and verify. Here is what each stage outputs and which ones a small project can skip.
Quick answer
- A CI/CD pipeline has five functional stages: source, build, test, package, and deploy, usually followed by a verification step that checks the deployed result.
- The build stage turns source code into a runnable artifact; the deploy stage moves that artifact to an environment. They are different stages because they should run at different times.
- Stages should run cheapest-first so a lint error fails in 30 seconds instead of after a 20-minute test suite.
- A small project needs install, lint or typecheck, test, build, deploy, and a smoke test. Staging environments and security scans can wait.
- Every stage should produce something you can inspect — a log, a report, an artifact digest — otherwise you cannot tell whether it ran.
What are the stages of a CI/CD pipeline?
A pipeline is a sequence of automated stages, each with an input and an output. The source stage checks out a specific commit. The build stage compiles or bundles it. The test stage runs automated checks against that build. The package stage stores the result as an immutable artifact. The deploy stage puts that artifact into an environment, and a verification stage proves the deployed thing actually works.
The split matters because each boundary is a place to fail early and a place to reuse work. If testing runs against the artifact rather than against a fresh build, you know the tested bytes are the deployed bytes. If deployment consumes a stored artifact rather than rebuilding, the deploy is fast and repeatable.
| Stage | Input | Output | Fails when |
|-----------|------------------------|-------------------------------|-----------------------------------|
| Source | A commit SHA | Checked-out tree | Ref does not exist / auth fails |
| Build | Source + lockfile | Binary, bundle, or image | Missing dep, compile error |
| Test | Built artifact | Pass/fail + reports | A check regresses |
| Package | Tested artifact | Immutable artifact + digest | Registry auth or tag collision |
| Deploy | Artifact digest | Running version in an env | Health check never passes |
| Verify | Running version | Smoke test result | App is up but wrong |Which stages does a small project actually need?
Start with six steps: install dependencies from the lockfile, run the linter or typechecker, run the test suite, build the artifact, deploy it, and hit one endpoint to confirm the deploy worked. That covers most of the value of a pipeline and fits in a single configuration file.
Skip a staging environment until you have users whose data you cannot lose, and skip security scanning until the pipeline is already trusted enough that a red build means something. A pipeline with six honest stages beats one with fifteen half-configured stages, because the fifteen-stage version gets ignored.
What order should the stages run in?
Order stages by feedback speed, not by importance. Static checks and unit tests are seconds to minutes; integration tests and image builds are minutes; deployment and end-to-end tests are the slowest. Running the cheap checks first means most broken commits stop in under a minute, which is what keeps developers watching the pipeline instead of walking away.
Build once, then promote the same artifact through every environment. Rebuilding for production is the most common cause of the works-in-staging failure, because the second build can resolve different dependency versions or pick up a different base image.
name: ci
on: [push]
jobs:
verify:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 22, cache: npm }
- run: npm ci
- run: npm run lint
- run: npm test
- run: npm run build
- uses: actions/upload-artifact@v4
with: { name: dist, path: dist/ }How do you know each stage is doing its job?
Each stage must leave evidence: a test report with counts, an artifact with a digest, a deploy log naming the version, a smoke test that asserted a status code and a body. Without that evidence, a green check only means the command exited zero, which is not the same as the stage having an effect.
The most common silent failure is a test stage that runs zero tests. Frameworks exit zero when no tests are discovered, so pin the expected count or fail on an empty run. The second is a deploy stage that succeeds because it never deployed — a skipped condition, a wrong environment name, or a cache hit that reused the previous build.
Where this bites vibecoders
An AI assistant will happily write a pipeline that installs dependencies, builds, and deploys in one job, with no artifact in between and no smoke test at the end. It looks complete because every step has a name. The review question is what each stage outputs and whether the deployed bytes are the tested bytes — if the answer is a rebuild in the deploy step, the pipeline cannot catch the class of bug it exists to catch.
Where AI coding assistants get this wrong
- Running tests after the deploy step, so a failing test no longer blocks the release.
- Rebuilding the app in the deploy job instead of promoting the tested artifact.
- Using npm install instead of npm ci, so the lockfile is not enforced.
- Leaving a test stage that can pass with zero tests discovered.
- Putting lint, tests, build, and deploy in one job so a lint error costs a full rebuild.
- Treating a green pipeline as proof the app works, with no post-deploy smoke test.
Checklist
- Write down each stage and its output before editing the YAML.
- Run static checks before tests, and tests before build.
- Build the artifact once and pass it between jobs by digest.
- Install dependencies from the lockfile in every job that needs them.
- Fail the test stage when zero tests run.
- Add one post-deploy request that asserts a real response.
FAQ
How many stages should a CI/CD pipeline have?
As many as you can name an output for. A practical starting point is six: install, static check, test, build, deploy, verify. Adding stages that produce nothing inspectable increases maintenance without increasing confidence, which is why large pipelines often feel less trustworthy than small ones.
Is build part of CI or CD?
Build sits at the boundary. Continuous integration covers source, build, and test — proving the commit integrates. Continuous delivery covers packaging and deployment readiness. Most tools run all of it in one pipeline, but the distinction matters when you decide what must pass before a merge versus before a release.
Do I need separate staging and production pipelines?
Not separate pipelines, separate deployments of the same artifact. One pipeline should build and verify, then deploy to staging, run smoke tests, and promote the identical artifact to production. Duplicating the build for production defeats the purpose of having a pipeline at all.
Why is my pipeline slower than my local build?
Usually because it starts from a cold environment: no dependency cache, no build cache, and a fresh checkout every time. Local builds reuse node_modules, compiler output, and layer caches. Add dependency and build caching keyed on the lockfile, and compare queue time separately from run time.
Related topics
- What Is CI/CD?
- Continuous Integration vs Continuous Delivery: What’s the Difference?
- What Is a Build Artifact (and Why Does Yours Keep Breaking)?
- How to Speed Up CI Builds (Without Skipping Tests)
- How to Set Up a CI/CD Pipeline With GitHub Actions
- Do You Need CI/CD for a Solo Project?