AtomLearnAtomLearn
DashboardGoalsPathAchievementsReviewSign In
DashboardCI/CDBuilding a CI Pipeline
CI/CDNot Started

Building a CI Pipeline

Run tests, lint, and build artifacts automatically on every push and pull request

0%
Knowledge0%
Learn & Drill
Fluency0%
Drill & Speed
Retention0%
Mastery & Review
Confidence0%
All modes
Practice

Free tier: read the explanation here. Upgrade to Pro for Drills, Speed challenges & Mastery badges.

Upgrade
Knowledge
Fluency
Retention

Knowledge Debt detected

You can study this freely — but your score may plateau if these foundations have gaps. The Mastery badge requires them to be solid.

Explanation

A CI pipeline is the automated sequence that runs on every code change to verify it is safe to merge and deploy.

Standard CI pipeline stages:

1. Checkout code 2. Set up runtime (Python/Node version, cache) 3. Install dependencies 4. Lint (code style and quality) 5. Type check (TypeScript, mypy) 6. Run tests (unit + integration) 7. Build artifact (if tests pass) 8. Publish artifact (Docker push, npm publish, etc.)

A complete Python/FastAPI CI example:

yaml name: CI on: [push, pull_request] jobs: quality: runs-on: ubuntu-latest services: postgres: image: postgres:15 env: POSTGRES_PASSWORD: testpass POSTGRES_DB: testdb ports: ['5432:5432'] options: >- --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: '3.12' cache: 'pip' - run: pip install -r requirements.txt - run: flake8 . --max-line-length=100 name: Lint - run: mypy src/ name: Type check - run: pytest --tb=short -q name: Tests env: DATABASE_URL: postgresql://postgres:testpass@localhost/testdb

Matrix testing — test on multiple versions:

yaml jobs: test: strategy: matrix: python-version: ['3.10', '3.11', '3.12'] runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - run: pip install -r requirements.txt && pytest `` Matrix creates one job per combination — all run in parallel.

Uploading test reports:

yaml - run: pytest --junitxml=test-results.xml - uses: actions/upload-artifact@v4 with: name: test-results path: test-results.xml if: always() # upload even if tests fail

Fail fast — exit early on first failure:

yaml strategy: fail-fast: true # cancel remaining matrix jobs if one fails (default) # fail-fast: false # let all matrix jobs finish

Examples

Full-stack CI pipeline (Next.js)

Build runs last — only reached if typecheck, lint, and tests all pass. Fastest feedback first.

# .github/workflows/ci.yml
name: CI

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

jobs:
  ci:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'

      - run: npm ci

      - name: Type check
        run: npx tsc --noEmit

      - name: Lint
        run: npm run lint

      - name: Run tests
        run: npm test

      - name: Build
        run: npm run build
        env:
          NEXT_PUBLIC_SUPABASE_URL: ${{ secrets.SUPABASE_URL }}
          NEXT_PUBLIC_SUPABASE_ANON_KEY: ${{ secrets.SUPABASE_ANON_KEY }}

Services: running a real database in CI

The health-cmd option makes the job wait until Postgres is actually ready before running tests — prevents flaky "connection refused" failures.

# .github/workflows/ci.yml
jobs:
  test:
    runs-on: ubuntu-latest

    services:
      db:
        image: postgres:15
        env:
          POSTGRES_USER: testuser
          POSTGRES_PASSWORD: testpass
          POSTGRES_DB: apptest
        ports:
          - 5432:5432
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5

    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with: { python-version: '3.12', cache: pip }
      - run: pip install -r requirements.txt

      - name: Run migrations
        run: alembic upgrade head
        env:
          DATABASE_URL: postgresql://testuser:testpass@localhost/apptest

      - name: Run tests
        run: pytest tests/ -v
        env:
          DATABASE_URL: postgresql://testuser:testpass@localhost/apptest

How well did you understand this?

Next in CI/CD

Deployment Pipelines

Continue