๐ What is CI/CD?
Continuous Integration (CI)
Automatically build and test code changes
- โข Code commit triggers build
- โข Run automated tests
- โข Catch bugs early
- โข Merge frequently
Continuous Deployment (CD)
Automatically deploy to production
- โข Automated deployment
- โข Zero-downtime releases
- โข Rollback capability
- โข Fast delivery
๐ GitHub Actions
Basic Workflow
# .github/workflows/ci.yml
name: CI Pipeline
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run linter
run: npm run lint
- name: Run tests
run: npm test
- name: Build
run: npm run buildDeploy to Production
# .github/workflows/deploy.yml
name: Deploy to Production
on:
push:
branches: [ main ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '20'
- name: Install and Build
run: |
npm ci
npm run build
- name: Deploy to Vercel
uses: amondnet/vercel-action@v25
with:
vercel-token: ${{ secrets.VERCEL_TOKEN }}
vercel-org-id: ${{ secrets.ORG_ID }}
vercel-project-id: ${{ secrets.PROJECT_ID }}
vercel-args: '--prod'Docker Build & Push
name: Docker Build and Push
on:
push:
branches: [ main ]
tags: [ 'v*' ]
jobs:
docker:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and push
uses: docker/build-push-action@v4
with:
context: .
push: true
tags: |
username/app:latest
username/app:${{ github.sha }}
cache-from: type=registry,ref=username/app:latest
cache-to: type=inline๐ฆ GitLab CI/CD
# .gitlab-ci.yml
stages:
- test
- build
- deploy
variables:
NODE_VERSION: "20"
# Test Stage
test:
stage: test
image: node:${NODE_VERSION}
cache:
paths:
- node_modules/
script:
- npm ci
- npm run lint
- npm test
only:
- merge_requests
- main
# Build Stage
build:
stage: build
image: node:${NODE_VERSION}
script:
- npm ci
- npm run build
artifacts:
paths:
- dist/
expire_in: 1 hour
only:
- main
# Deploy Stage
deploy_production:
stage: deploy
image: alpine:latest
before_script:
- apk add --no-cache curl
script:
- echo "Deploying to production..."
- curl -X POST ${DEPLOY_WEBHOOK_URL}
environment:
name: production
url: https://myapp.com
only:
- main
when: manual # Requires manual approval๐ง Jenkins Pipeline
// Jenkinsfile
pipeline {
agent any
environment {
NODE_VERSION = '20'
DOCKER_IMAGE = 'username/myapp'
}
stages {
stage('Checkout') {
steps {
checkout scm
}
}
stage('Install') {
steps {
sh 'npm ci'
}
}
stage('Test') {
parallel {
stage('Lint') {
steps {
sh 'npm run lint'
}
}
stage('Unit Tests') {
steps {
sh 'npm test'
}
}
}
}
stage('Build') {
steps {
sh 'npm run build'
}
}
stage('Docker Build') {
steps {
script {
docker.build("${DOCKER_IMAGE}:${BUILD_NUMBER}")
}
}
}
stage('Deploy') {
when {
branch 'main'
}
steps {
script {
docker.withRegistry('https://registry.hub.docker.com', 'docker-credentials') {
docker.image("${DOCKER_IMAGE}:${BUILD_NUMBER}").push()
docker.image("${DOCKER_IMAGE}:${BUILD_NUMBER}").push('latest')
}
}
}
}
}
post {
success {
echo 'Pipeline succeeded!'
}
failure {
echo 'Pipeline failed!'
}
}
}๐งช Testing Strategies
Test Pyramid
- Unit Tests (70%): Fast, isolated, test individual functions
- Integration Tests (20%): Test component interactions
- E2E Tests (10%): Test full user workflows
# Example: Node.js Testing
- name: Run Tests
run: |
npm run test:unit
npm run test:integration
npm run test:e2e
- name: Upload Coverage
uses: codecov/codecov-action@v3
with:
files: ./coverage/coverage-final.json
fail_ci_if_error: true๐ข Deployment Strategies
1. Rolling Deployment
Gradually replace old version with new
โ Zero downtime, โ Slow rollback
2. Blue-Green Deployment
Two identical environments, switch traffic
โ Instant rollback, โ Double resources
3. Canary Deployment
Release to small subset first
โ Low risk, โ Complex monitoring
๐ Secrets Management
# GitHub Actions Secrets
steps:
- name: Deploy
env:
API_KEY: ${{ secrets.API_KEY }}
DATABASE_URL: ${{ secrets.DATABASE_URL }}
run: |
echo "Deploying with secrets..."
# GitLab CI Variables
deploy:
script:
- echo "API_KEY=${API_KEY}" >> .env
- echo "DB_URL=${DATABASE_URL}" >> .env
# Best Practices:
โข Never commit secrets to code
โข Use environment-specific secrets
โข Rotate secrets regularly
โข Use secret managers (Vault, AWS Secrets Manager)
โข Encrypt secrets at rest๐ Monitoring & Notifications
# Slack Notification
- name: Slack Notification
uses: 8398a7/action-slack@v3
with:
status: ${{ job.status }}
text: 'Deployment ${{ job.status }}'
webhook_url: ${{ secrets.SLACK_WEBHOOK }}
if: always()
# Email Notification
post:
failure:
mail to: 'team@example.com',
subject: "Pipeline Failed: ${env.JOB_NAME}",
body: "Build failed. Check console output."
# Metrics
โข Build duration
โข Success/failure rate
โข Deployment frequency
โข Mean time to recovery (MTTR)โ CI/CD Best Practices
- Keep pipelines fast: Parallel jobs, caching, optimize tests
- Fail fast: Run quick tests first
- Automate everything: Testing, building, deployment
- Version everything: Code, configs, infrastructure
- Monitor pipelines: Track metrics and failures
- Secure secrets: Never hardcode credentials
- Test in production-like environment: Staging should mirror prod
- Rollback strategy: Always have a way back
๐ Pipeline Checklist
- โ Automated testing (unit, integration, e2e)
- โ Code linting and formatting
- โ Security scanning
- โ Build artifacts
- โ Docker image creation
- โ Automated deployment
- โ Rollback mechanism
- โ Notifications (Slack, email)
- โ Monitoring and logging
- โ Secrets management
- โ Environment-specific configs
- โ Documentation
๐ฏ Conclusion
CI/CD pipelines are essential for modern software development. They automate repetitive tasks, catch bugs early, and enable fast, reliable deployments. Start simple with basic testing and building, then gradually add deployment automation and advanced strategies.
๐ณ Containerize Your Apps
CI/CD works best with containers. Generate optimized Dockerfiles for your applications.
Generate Dockerfile โ