DevOps Basic

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.

Pronunciation

IPA: /siː aɪ siː diː/

Sounds like: “see-eye-see-dee” - each letter separately

Common 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?

PracticeDescription
Frequent commitsIntegrate code multiple times a day
Automated buildCompile code automatically
Automated testsRun tests on every push
Fast feedbackKnow 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@v4

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

      - 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

AspectContinuous DeliveryContinuous Deployment
AutomationUp to stagingUp to production
Human approvalYes, for productionNo
RiskLowerHigher (requires more tests)
SpeedFastVery 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@v4
      - run: npm ci
      - run: npm test

  deploy-staging:
    needs: test
    runs-on: ubuntu-latest
    environment: staging
    steps:
      - uses: actions/checkout@v4
      - 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@v4
      - name: Deploy to Production
        run: |
          npm ci
          npm run build
          # Deploy to production server
          rsync -avz ./dist/ prod-server:/var/www/app/
ToolTypeIdeal for
GitHub ActionsCloudGitHub projects
GitLab CICloud/Self-hostedGitLab projects
JenkinsSelf-hostedFull control
CircleCICloudSpeed
Azure DevOpsCloudMicrosoft ecosystem
AWS CodePipelineCloudAWS 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

MetricWithout CI/CDWith CI/CD
Deploy frequencyWeekly/MonthlyDaily/Multiple per day
Feedback timeHours/DaysMinutes
Bugs in productionFrequentRare
RollbackManual, slowAutomatic, 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@v4

      - name: Setup
        uses: actions/setup-node@v4
        with:
          node-version: '20'
          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@v4

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

Best Practices

PracticeWhy
Fast tests firstEarly feedback
Reproducible buildsSame results always
Secure secretsNever in code
Automatic rollbackQuick recovery
Post-deploy monitoringDetect 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.