CI/CD is one of those acronyms that gets thrown around constantly. “We have CI/CD.” “The CI is failing.” “We need to set up a pipeline.”
But what does it actually do? And why should you care?
CI and CD are two separate things
CI — Continuous Integration
Every time code gets pushed or a PR is opened, an automated system:
- Pulls the latest code
- Installs dependencies
- Runs type checks, linting, and tests
- Builds the app
If any step fails, the PR is blocked from merging. This ensures the codebase always stays in a working state.
CD — Continuous Delivery / Deployment
After CI passes (and optionally after a merge to main), the system automatically deploys the new version to staging or production.
Together, they mean: merge to main, and it ships automatically.
What belongs in a pipeline?
Use the builder below to understand which steps matter and why:
* Critical steps. Disabling them drops confidence regardless of score. 6/8 steps enabled.
Here’s what each step does and why it earns its place:
1. Install dependencies
- run: npm ci
npm ci (clean install) is stricter than npm install. It:
- Installs exact versions from
package-lock.json - Fails if the lockfile is out of sync with
package.json - Never modifies
package-lock.json
Always use npm ci in CI, never npm install.
2. Type check
- run: npx tsc --noEmit
Catch TypeScript errors that might not have been caught locally. This is cheap and fast — there’s no excuse to skip it.
3. Lint
- run: npx eslint .
Enforces code style, catches potential bugs (unused variables, missing await, etc.). Keeps the codebase consistent.
4. Unit tests
- run: npm test
Your business logic should be tested. CI is what makes tests actually matter — without it, tests are optional suggestions.
5. Build
- run: npm run build
Make sure the production build compiles without errors. Something might pass type checking but still fail to build.
6. Deploy
On a successful merge to main, trigger the deployment to production.
A basic GitHub Actions pipeline
GitHub Actions is the most common CI/CD tool for projects hosted on GitHub. Configuration lives in .github/workflows/.
# .github/workflows/ci.yml
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
ci:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
cache: "npm"
- name: Install dependencies
run: npm ci
- name: Type check
run: npx tsc --noEmit
- name: Lint
run: npx eslint .
- name: Run tests
run: npm test
- name: Build
run: npm run build
Commit this file, push it, and open a PR. GitHub automatically runs the workflow and shows a green/red check on the PR.
Branch protection: making CI mandatory
CI is useless if people can bypass it. In GitHub:
- Go to Settings → Branches → Add rule
- Set Branch name pattern:
main - Check Require status checks to pass before merging
- Select your CI job (
ci) as required - Check Require branches to be up to date
Now no one can merge a PR that fails CI. Your main branch is protected.
Adding auto-deploy
For a static site on Vercel, deployment is already automatic — Vercel watches your repo. But for more control, you can add a deploy step to your workflow:
- name: Deploy to production
if: github.ref == 'refs/heads/main'
run: npx vercel --prod --token ${{ secrets.VERCEL_TOKEN }}
env:
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
The if: github.ref == 'refs/heads/main' condition ensures this only runs on merges to main, not on every PR.
Why CI/CD matters beyond automation
CI/CD isn’t just about speed. It’s about confidence.
Without it:
- Deployments are manual, scary events
- “We can’t deploy on Fridays” becomes a rule
- One bad commit can take down production for hours
- Nobody wants to merge code late in the day
With it:
- Merging is routine and low-risk
- Bad code is caught before it reaches production
- Deployment is boring and fast
- The feedback loop from “write code” to “it’s in production” is minutes, not days
That shift — from deployment as a scary event to deployment as a normal, automatic thing — is what CI/CD is really about.