CI/CD Pipeline Design: From GitHub Actions to Production Deploys
See a release team move from change scope to verified handoff.
The sample coordinates build, preview verification, approvals, and release evidence without connecting an account.
A good CI/CD pipeline is the difference between deploying with confidence and deploying with fear. This guide covers the patterns that work for real teams — from single-repo apps to complex microservices.
The Pipeline Stages#
Every CI/CD pipeline has the same core stages:
Push → Build → Test → Security Scan → Deploy Staging → Deploy Production
Each stage is a gate. If any stage fails, the pipeline stops.
Pipeline Patterns#
1. Simple App Pipeline#
# .github/workflows/ci.yml
name: CI/CD
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build-and-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 20 }
- run: npm ci
- run: npm run lint
- run: npm run test
- run: npm run build
deploy:
needs: build-and-test
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci && npm run build
- run: npx vercel --prod --token=${{ secrets.VERCEL_TOKEN }}
2. Microservices Pipeline#
Each service has its own pipeline, triggered by path changes:
on:
push:
paths:
- 'services/api/**'
- '.github/workflows/api.yml'
jobs:
api:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: cd services/api && npm ci && npm test
- uses: docker/build-push-action@v5
with:
context: services/api
push: true
tags: registry/api:${{ github.sha }}
- run: kubectl set image deployment/api api=registry/api:${{ github.sha }}
Key: Only build/deploy what changed. Path filters prevent unnecessary builds.
3. Monorepo Pipeline#
Use a build system that understands the dependency graph:
jobs:
detect-changes:
outputs:
api: ${{ steps.changes.outputs.api }}
web: ${{ steps.changes.outputs.web }}
shared: ${{ steps.changes.outputs.shared }}
steps:
- uses: dorny/paths-filter@v2
id: changes
with:
filters: |
api: ['packages/api/**', 'packages/shared/**']
web: ['packages/web/**', 'packages/shared/**']
shared: ['packages/shared/**']
build-api:
needs: detect-changes
if: needs.detect-changes.outputs.api == 'true'
# ... build api
build-web:
needs: detect-changes
if: needs.detect-changes.outputs.web == 'true'
# ... build web
Tools: Turborepo, Nx, Bazel for intelligent caching and task orchestration.
4. GitOps (ArgoCD)#
Push manifests to Git, ArgoCD syncs to cluster:
Developer → Push code → CI builds image → Push image tag to manifests repo
ArgoCD watches manifests repo → detects change → syncs to Kubernetes
# manifests/api/deployment.yaml (updated by CI)
spec:
containers:
- name: api
image: registry/api:abc123 # CI updates this SHA
Benefits: Git is the source of truth. Rollback = git revert. Audit trail = git log.
Testing Strategy#
| Test Type | When | Speed | Confidence |
|---|---|---|---|
| Lint | Every push | < 30s | Catches style issues |
| Unit tests | Every push | < 2min | Core logic |
| Integration tests | Every push | < 5min | Service interactions |
| E2E tests | PR + main | < 15min | User flows |
| Load tests | Weekly/release | < 30min | Performance |
| Security scan | Every push | < 5min | Vulnerabilities |
Don't run everything on every push. Fast tests on every commit, slow tests on PRs and main.
Deployment Strategies#
Blue-Green#
Two identical environments. Switch traffic instantly:
Blue (current) ← 100% traffic
Green (new) ← 0% traffic
Deploy to Green → test → switch:
Blue ← 0% traffic
Green ← 100% traffic
Rollback? Switch back to Blue instantly.
Canary#
Gradually shift traffic to the new version:
v1 ← 95% traffic
v2 ← 5% traffic (canary)
Monitor errors/latency for 30min...
v1 ← 50% traffic
v2 ← 50% traffic
All good? v2 ← 100% traffic
Rolling Update (Kubernetes default)#
Replace pods one at a time:
spec:
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
Feature Flags#
Deploy code to production but hide behind a flag:
if (featureFlags.isEnabled("new-checkout", user)) {
return <NewCheckout />;
}
return <OldCheckout />;
Tools: LaunchDarkly, Unleash, Flagsmith, PostHog
CI/CD Tools Compared#
| Tool | Type | Best For |
|---|---|---|
| GitHub Actions | Cloud CI | GitHub repos, most teams |
| GitLab CI | Cloud/Self-hosted | GitLab users, self-hosted |
| CircleCI | Cloud CI | Complex workflows, Docker |
| Jenkins | Self-hosted | Enterprise, custom plugins |
| ArgoCD | GitOps | Kubernetes deployments |
| Flux | GitOps | K8s, Helm charts |
| Buildkite | Hybrid | Self-hosted agents, cloud UI |
| Dagger | Programmable CI | CI pipelines as code (Go/Python/TS) |
Security in the Pipeline#
Code Push → SAST (static analysis) → SCA (dependency scan) → Build
→ Container scan (Trivy) → DAST (running app) → Deploy
| Scan Type | What | Tools |
|---|---|---|
| SAST | Code vulnerabilities | Semgrep, CodeQL, SonarQube |
| SCA | Dependency vulnerabilities | Snyk, Dependabot, Socket |
| Container | Image vulnerabilities | Trivy, Grype, Scout |
| Secrets | Leaked credentials | GitLeaks, TruffleHog |
| DAST | Running app vulnerabilities | OWASP ZAP, Burp Suite |
Pipeline Best Practices#
- Fast feedback — lint + unit tests < 2 minutes
- Cache aggressively — node_modules, Docker layers, build artifacts
- Immutable artifacts — build once, deploy same artifact to staging + prod
- Environment parity — staging mirrors production
- Secrets in vault — never in code, use GitHub Secrets or Vault
- Rollback plan — every deploy should be reversible in < 5 minutes
Summary#
| Pattern | When |
|---|---|
| Simple pipeline | Single app, small team |
| Path-filtered | Microservices, monorepo |
| GitOps (ArgoCD) | Kubernetes, audit requirements |
| Blue-green | Zero-downtime, instant rollback |
| Canary | Gradual rollout, risk reduction |
| Feature flags | Decouple deploy from release |
Generate CI/CD architectures at codelit.io — export GitHub Actions workflows, Docker configs, and Kubernetes manifests from any diagram.
See a release team move from change scope to verified handoff.
The sample coordinates build, preview verification, approvals, and release evidence without connecting an account.
Try this template
Continue learning
Go deeper on infrastructure and delivery
As an Amazon Associate I earn from qualifying purchases. Codelit may receive a commission at no extra cost to you.
The DevOps Handbook
Gene Kim, Jez Humble · 2021
Case studies from Etsy, Amazon, and Target on rewiring deployment pipelines and org structure.
Network Programmability and Automation
Christian Adell, Scott Lowe, Matt Oswalt, Jason Edelman · 2023
Treats network config as code: APIs, source control and CI applied to routers and switches.
4.9 (24)Infrastructure as Code
Kief Morris · 2020
Tool-agnostic patterns for structuring stacks and testing infra code, beyond one provider's docs.
4.4 (120)Learning Domain-Driven Design
Vlad Khononov · 2021
Turns bounded contexts and aggregates into decision rules for where service boundaries actually go.
4.6 (400)