CI/CD Pipeline Design Guide 2026: From Commit to Production in 10 Minutes
Advertisement
CI/CD 2026: Ship Fast, Break Nothing
A good CI/CD pipeline takes you from code commit to production in 10 minutes with zero downtime. Here's how to build one.
- The Pipeline Stages
- Complete Pipeline
- Blue-Green Deployment
- Canary Release
- Deployment Notifications
- Rollback Strategy
- Deployment Metrics to Track
The Pipeline Stages
Commit → Lint/Format → Tests → Build → Docker → Staging → E2E → Production
10s 30s 2min 2min 3min 1min 3min 1min
Total: ~12 minutes commit to production
Complete Pipeline
# .github/workflows/pipeline.yml
name: Production Pipeline
on:
push:
branches: [main]
pull_request:
branches: [main]
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
# Stage 1: Quality checks (parallel)
quality:
name: Code Quality
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: '20', cache: 'npm' }
- run: npm ci
- run: npm run lint
- run: npm run typecheck
- run: npm run format:check
# Stage 2: Tests (parallel with quality)
test:
name: Tests
runs-on: ubuntu-latest
services:
postgres:
image: postgres:16-alpine
env: { POSTGRES_PASSWORD: test, POSTGRES_DB: testdb }
options: --health-cmd pg_isready --health-interval 5s
ports: ['5432:5432']
redis:
image: redis:7-alpine
ports: ['6379:6379']
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: '20', cache: 'npm' }
- run: npm ci
- run: npm run db:migrate
env:
DATABASE_URL: postgresql://postgres:test@localhost:5432/testdb
- run: npm run test:ci
env:
DATABASE_URL: postgresql://postgres:test@localhost:5432/testdb
REDIS_URL: redis://localhost:6379
- uses: codecov/codecov-action@v4
with: { token: ${{ secrets.CODECOV_TOKEN }} }
# Stage 3: Build Docker image
build:
name: Build Image
runs-on: ubuntu-latest
needs: [quality, test]
outputs:
image: ${{ steps.meta.outputs.tags }}
digest: ${{ steps.build.outputs.digest }}
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=sha,prefix=sha-
type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }}
- id: build
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
cache-from: type=gha
cache-to: type=gha,mode=max
# Stage 4: Deploy to staging
deploy-staging:
name: Deploy to Staging
runs-on: ubuntu-latest
needs: build
environment:
name: staging
url: https://staging.webcoderspeed.com
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- name: Deploy to staging
run: |
# Update staging with new image
kubectl set image deployment/app-staging \
app=${{ needs.build.outputs.image }} \
--namespace=staging
kubectl rollout status deployment/app-staging --namespace=staging
# Stage 5: E2E tests on staging
e2e:
name: E2E on Staging
runs-on: ubuntu-latest
needs: deploy-staging
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: '20', cache: 'npm' }
- run: npm ci
- run: npx playwright install --with-deps
- run: npx playwright test
env:
BASE_URL: https://staging.webcoderspeed.com
- uses: actions/upload-artifact@v4
if: failure()
with:
name: playwright-report
path: playwright-report/
# Stage 6: Production deploy
deploy-production:
name: Deploy to Production
runs-on: ubuntu-latest
needs: e2e
environment:
name: production
url: https://webcoderspeed.com
steps:
- name: Blue-green deploy
run: |
# Switch traffic to green (new version)
kubectl apply -f k8s/production/
kubectl rollout status deployment/app-production
Blue-Green Deployment
# Zero-downtime deployment strategy
# Blue: current production
# Green: new version
# k8s/service.yaml — switch traffic by updating selector
apiVersion: v1
kind: Service
metadata:
name: app-production
spec:
selector:
app: webcoderspeed
version: blue # Switch to 'green' for deploy
# Deploy green, then switch service selector
kubectl apply -f k8s/deployment-green.yaml
kubectl rollout status deployment/app-green
kubectl patch service app-production -p '{"spec":{"selector":{"version":"green"}}}'
# Quick rollback if needed
kubectl patch service app-production -p '{"spec":{"selector":{"version":"blue"}}}'
Canary Release
# Send 10% of traffic to new version
# k8s/canary-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-canary
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "10" # 10% traffic
spec:
rules:
- host: webcoderspeed.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app-canary-service
port: { number: 80 }
Deployment Notifications
notify:
name: Notify
needs: [deploy-production]
runs-on: ubuntu-latest
if: always()
steps:
- name: Slack notification
uses: slackapi/slack-github-action@v1
with:
channel-id: '#deployments'
slack-message: |
*${{ job.status == 'success' && '✅' || '❌' }} Deployment ${{ job.status }}*
Version: `${{ github.sha }}`
By: ${{ github.actor }}
${{ job.status == 'success' && 'Production is live!' || 'Check GitHub Actions for details' }}
env:
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
Rollback Strategy
#!/bin/bash
# rollback.sh — Emergency rollback script
PREVIOUS_VERSION=$(kubectl rollout history deployment/app-production | tail -3 | head -1 | awk '{print $1}')
echo "Rolling back to revision $PREVIOUS_VERSION..."
kubectl rollout undo deployment/app-production
# Or to specific revision
kubectl rollout undo deployment/app-production --to-revision=5
echo "Rollback complete!"
kubectl rollout status deployment/app-production
Deployment Metrics to Track
| Metric | Target | Alert Threshold |
|---|---|---|
| Deployment frequency | Multiple per day | < 1 per week |
| Lead time (commit → prod) | < 15 minutes | > 1 hour |
| Change failure rate | < 5% | > 15% |
| Recovery time | < 30 minutes | > 2 hours |
These are the DORA metrics — the industry standard for measuring engineering team performance. A great CI/CD pipeline is the foundation of high performance.
Advertisement