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.