CI/CD Pipeline Design: From Zero to Production Deployment


Disclosure: This article may contain affiliate links. We only recommend products we believe in.

What CI/CD Actually Means

Continuous Integration (CI)

Every code change triggers automated tests. If tests fail, the change is rejected. The goal is to catch bugs immediately, not days later.

Continuous Delivery (CD)

Every change that passes CI is automatically deployed to a staging environment and can be deployed to production with one click.

Continuous Deployment

Every change that passes CI is automatically deployed to production. No manual approval step.

The Pipeline Stages

1. Lint and Format

Catch style issues and potential errors before running expensive tests.

- name: Lint
  run: npm run lint
- name: Type Check
  run: npm run type-check

2. Unit Tests

Fast, isolated tests that verify individual functions and components.

- name: Unit Tests
  run: npm run test -- --coverage

3. Integration Tests

Test interactions between components, database queries, and API endpoints.

4. Build

Compile, bundle, and optimize the application for production.

- name: Build
  run: npm run build

5. Deploy to Staging

Deploy to a staging environment that mirrors production.

6. E2E Tests (on Staging)

Run Playwright or Cypress tests against the staging deployment to verify the full user flow.

7. Deploy to Production

If all checks pass, deploy to production.

GitHub Actions Example

name: CI/CD Pipeline
on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: npm
      - run: npm ci
      - run: npm run lint
      - run: npm run test -- --coverage
      - run: npm run build

  deploy:
    needs: test
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci && npm run build
      - name: Deploy
        run: npx wrangler pages deploy dist/
        env:
          CLOUDFLARE_API_TOKEN: ${{ secrets.CF_TOKEN }}

Key Principles

  1. Fast feedback: The pipeline should complete in under 10 minutes. Slow pipelines get ignored.
  2. Fail fast: Run the cheapest checks first (lint, then unit tests, then integration).
  3. Reproducible: Use locked dependency versions and consistent environments.
  4. Secure: Never hardcode secrets. Use environment variables and secret managers.