Building a CI Pipeline
Put the pieces together into a real pipeline that guards your main branch.
You know the pieces β now letβs build a real CI pipeline: the automated gate that every change must pass before it can be merged. This is the workflow that keeps a codebase healthy.
π― Learning Objectives
By the end of this lesson you will:
- Design a complete CI pipeline for an app
- Order steps logically: install β lint β test β build
- Upload build artifacts
- Enforce the pipeline as a required check
What a CI Pipeline Should Do
A good CI pipeline runs on every push and pull request and answers one question: is this change safe to merge? It typically:
- Checks out the code
- Installs dependencies (cached)
- Lints for style and obvious errors
- Tests the code
- Builds the production artifact
- Uploads the artifact for later use
π‘ Fail fast, cheapest first
Order steps so the quickest checks run first. Linting fails in seconds; a full test suite takes minutes. Putting lint before tests means an obvious mistake stops the pipeline early, saving time and runner minutes.
A Complete CI Workflow
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
ci:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v4
- name: Set up Node
uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- name: Install dependencies
run: npm ci
- name: Lint
run: npm run lint
- name: Test
run: npm test
- name: Build
run: npm run build
- name: Upload build output
uses: actions/upload-artifact@v4
with:
name: dist
path: dist/Each step is named so the Actions UI reads clearly. npm ci (not npm install) gives clean, reproducible installs from the lockfile β the right choice for CI.
Artifacts β Keeping the Output
The build step produces a dist/ folder. Uploading it as an artifact means you can download it from the run, or hand it to a deploy job later:
- uses: actions/upload-artifact@v4
with:
name: dist
path: dist/
retention-days: 7β npm ci vs npm install in CI
Always use npm ci in pipelines. It installs exactly whatβs in package-lock.json and fails if the lockfile is out of sync β giving you reproducible builds. npm install can silently update the lockfile, causing βworks locally, fails in CIβ surprises.
Making It a Required Check
A pipeline only protects you if it blocks bad merges. In the repositoryβs branch protection settings, mark the CI workflow as a required status check on main.
Now a pull request cannot be merged until CI passes:
Pull request β CI runs β β green β merge allowed
β β red β merge blockedπ‘ This is the heart of CI
Branch protection + a required CI check is what actually keeps main deployable. Without it, the pipeline is just advisory β people can merge over a red build.
π§ͺ Hands-on Lab
Design a CI Pipeline
- Write a CI workflow that runs on pushes and PRs to
main - Include install (cached), lint, test, and build steps in the right order
- Upload the build output as an artifact
π§ Knowledge Check
Why should linting run before the full test suite in a CI pipeline?
What makes a CI pipeline actually prevent broken code from reaching main?
πΌ Interview Preparation
Walk me through a CI pipeline you would build for a web application.
Summary
Youβve built a complete CI pipeline: checkout, cached install, lint, test, build, and artifact upload β enforced as a required check. Next, youβll safely add deployment using secrets and environments to reach true CD.