Get the next live webinar in your inbox

One email a month: the upcoming live event + free recording access for subscribers. No spam, unsubscribe anytime.

Lesson 7 of 10 ~30 min
Course progress
0%

Building a CI Pipeline

Create a complete CI pipeline for testing and building

Building a Production-Ready CI Pipeline

A good CI pipeline catches bugs early and ensures code quality. Let’s build one step by step.

Complete Node.js CI Pipeline

name: Node.js CI

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '18'
          cache: 'npm'
      
      - name: Install dependencies
        run: npm ci
      
      - name: Run ESLint
        run: npm run lint
      
      - name: Check formatting
        run: npm run format:check

  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [16, 18, 20]
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Setup Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
          cache: 'npm'
      
      - name: Install dependencies
        run: npm ci
      
      - name: Run tests
        run: npm test -- --coverage
      
      - name: Upload coverage
        uses: codecov/codecov-action@v3
        if: matrix.node-version == '18'
        with:
          files: ./coverage/coverage-final.json

  build:
    needs: [lint, test]
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '18'
          cache: 'npm'
      
      - name: Install dependencies
        run: npm ci
      
      - name: Build project
        run: npm run build
      
      - name: Upload build artifacts
        uses: actions/upload-artifact@v4
        with:
          name: build-output
          path: dist/
          retention-days: 7

Matrix Strategy

Test across multiple versions:

strategy:
  matrix:
    os: [ubuntu-latest, windows-latest, macos-latest]
    node-version: [16, 18, 20]
  fail-fast: false

steps:
  - name: Test on ${{ matrix.os }} with Node ${{ matrix.node-version }}
    run: npm test

Caching for Speed

- name: Cache node modules
  uses: actions/cache@v3
  with:
    path: ~/.npm
    key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
    restore-keys: |
      ${{ runner.os }}-node-

- name: Install dependencies
  run: npm ci

Conditional Execution

- name: Run integration tests
  if: github.event_name == 'push' && github.ref == 'refs/heads/main'
  run: npm run test:integration

- name: Comment on PR
  if: github.event_name == 'pull_request'
  uses: actions/github-script@v7
  with:
    script: |
      github.rest.issues.createComment({
        issue_number: context.issue.number,
        owner: context.repo.owner,
        repo: context.repo.repo,
        body: '✅ Tests passed!'
      })

Artifacts and Reports

- name: Run tests with coverage
  run: npm test -- --coverage

- name: Upload coverage report
  uses: actions/upload-artifact@v4
  with:
    name: coverage-report
    path: coverage/

- name: Upload test results
  uses: actions/upload-artifact@v4
  if: always()
  with:
    name: test-results
    path: test-results/

Environment Variables

env:
  NODE_ENV: production
  API_URL: ${{ secrets.API_URL }}

jobs:
  test:
    env:
      DATABASE_URL: postgres://localhost:5432/test
    steps:
      - name: Test with env vars
        run: npm test
        env:
          LOG_LEVEL: debug

Best Practices

Run linting first - Fail fast on code quality
Use matrix builds - Test multiple environments
Cache dependencies - Speed up workflows
Upload artifacts - Preserve build outputs
Parallel jobs - Run independent tasks simultaneously
Conditional steps - Skip unnecessary work

Key Takeaways

A well-structured CI pipeline ensures code quality, catches bugs early, and provides fast feedback to developers. Matrix builds and caching make pipelines efficient and comprehensive.