CI/CD
Continuous Integration and Continuous Delivery/Deployment. Development practices that automate code integration and delivery to production.
Pronunciation
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?
| 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@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
| Aspect | Continuous Delivery | Continuous Deployment |
|---|---|---|
| Automation | Up to staging | Up to production |
| Human approval | Yes, for production | No |
| Risk | Lower | Higher (requires more tests) |
| 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@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/
Popular CI/CD Tools
| 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@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
| 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 |
Related terms
- [[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.