DevOpsBasic

CI/CD

Continuous Integration and Continuous Delivery/Deployment. Development practices that automate code integration and delivery to production.

Pronunciation

/siː aɪ siː diː/
"see-eye-see-dee"
Listen on:Forvo

What is it

CI/CD are two complementary practices:

  • CI (Continuous Integration): Integrating code frequently to the main repository, with automated tests
  • CD (Continuous Delivery/Deployment): Automatically delivering code to production or staging

Together, they enable delivering software quickly, reliably, and frequently.

Common pronunciation mistakes

  • ❌ “cicd” (it’s not a word, it’s an acronym)
  • ❌ “ki-kd” (pronounce each letter clearly)

CI vs CD: The difference

┌─────────────────────────────────────────────────────────┐
│                    CI/CD FLOW                            │
├─────────────────────────────────────────────────────────┤
│                                                          │
│   ┌─────────┐    ┌─────────┐    ┌─────────┐            │
│   │  Code   │ →  │  Build  │ →  │  Tests  │            │
│   │  Push   │    │         │    │         │            │
│   └─────────┘    └─────────┘    └─────────┘            │
│        │                              │                 │
│        └──────── CI ──────────────────┘                 │
│                                       │                 │
│                                       ▼                 │
│                              ┌─────────────────┐        │
│                              │ Tests passed?   │        │
│                              └────────┬────────┘        │
│                                       │                 │
│                          Yes ─────────┴────────── No    │
│                          │                        │     │
│                          ▼                        ▼     │
│                    ┌───────────┐            ┌────────┐  │
│                    │  Deploy   │            │ Fail   │  │
│                    │  Staging  │            │        │  │
│                    └─────┬─────┘            └────────┘  │
│                          │                              │
│                          ▼                              │
│                    ┌───────────┐                        │
│                    │  Deploy   │                        │
│                    │Production │ ← Continuous Delivery  │
│                    └───────────┘                        │
│                          │                              │
│        └──────── CD ─────┘                              │
│                                                          │
└─────────────────────────────────────────────────────────┘

Continuous Integration (CI)

What does it include?

Practice Description
Frequent commits Integrate code multiple times a day
Automated build Compile code automatically
Automated tests Run tests on every push
Fast feedback Know within minutes if something failed

CI Pipeline Example

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

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

jobs:
  build-and-test:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v6

      - name: Setup Node.js
        uses: actions/setup-node@v6
        with:
          node-version: '24'

      - name: Install dependencies
        run: npm ci

      - name: Lint
        run: npm run lint

      - name: Unit tests
        run: npm test

      - name: Build
        run: npm run build

Continuous Delivery vs Deployment

Aspect Continuous Delivery Continuous Deployment
Automation Everything ready for production; the final step is triggered manually All the way to production, no intervention
Human approval Yes, for production No
Key requirement Reliable pipeline and always-deployable software Very robust automated tests and monitoring
Speed Fast Very fast

Continuous Delivery

Code → CI → Tests → Build → Staging → [Manual Approval] → Production

Continuous Deployment

Code → CI → Tests → Build → Staging → More Tests → Production (automatic)

Complete Example: CD Pipeline

# .github/workflows/cd.yml
name: CD Pipeline

on:
  push:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - run: npm ci
      - run: npm test

  deploy-staging:
    needs: test
    runs-on: ubuntu-latest
    environment: staging
    steps:
      - uses: actions/checkout@v6
      - name: Deploy to Staging
        run: |
          npm ci
          npm run build
          # Deploy to staging server
          rsync -avz ./dist/ staging-server:/var/www/app/

  deploy-production:
    needs: deploy-staging
    runs-on: ubuntu-latest
    environment: production
    steps:
      - uses: actions/checkout@v6
      - name: Deploy to Production
        run: |
          npm ci
          npm run build
          # Deploy to production server
          rsync -avz ./dist/ prod-server:/var/www/app/
Tool Type Ideal for
GitHub Actions Cloud GitHub projects
GitLab CI Cloud/Self-hosted GitLab projects
Jenkins Self-hosted Full control
CircleCI Cloud Speed
Azure DevOps Cloud Microsoft ecosystem
AWS CodePipeline Cloud AWS ecosystem

Benefits of CI/CD

For developers

Without CI/CD:
"Works on my machine?" → Merge → 😱 Production broken

With CI/CD:
Push → Automated tests → ✅ or ❌ → Immediate feedback

For the business

Metric Without CI/CD With CI/CD
Deploy frequency Weekly/Monthly Daily/Multiple per day
Feedback time Hours/Days Minutes
Bugs in production Frequent Rare
Rollback Manual, slow Automatic, fast

Practical Case: Setting up CI/CD from Scratch

Step 1: Project structure

my-project/
├── src/
├── tests/
├── package.json
└── .github/
    └── workflows/
        └── ci-cd.yml

Step 2: Basic pipeline

name: CI/CD

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

jobs:
  # CI - Runs on every push/PR
  ci:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6

      - name: Setup
        uses: actions/setup-node@v6
        with:
          node-version: '24'
          cache: 'npm'

      - name: Install
        run: npm ci

      - name: Lint
        run: npm run lint

      - name: Test
        run: npm test -- --coverage

      - name: Build
        run: npm run build

  # CD - Only on push to main
  cd:
    needs: ci
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6

      - name: Deploy
        env:
          DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}
        run: |
          npm ci
          npm run build
          npm run deploy

Best Practices

Practice Why
Fast tests first Early feedback
Reproducible builds Same results always
Secure secrets Never in code
Automatic rollback Quick recovery
Post-deploy monitoring Detect issues
  • Deploy - Process of putting code in production
  • Testing - Automated code testing
  • Docker - Containers for consistent builds
  • Git - Version control

Remember: CI/CD is not just tools, it’s a culture. Start with basic CI and evolve towards CD as your team gains confidence in tests and the process.