CI/CD Concepts & Pipelines
CI/CD Concepts & Pipelines Core Concepts Continuous Integration (CI) — developers merge to main frequently (daily+); each push triggers automated build + test. …
CI/CD Concepts & Pipelines
Core Concepts
Continuous Integration (CI) — developers merge to main frequently (daily+); each push triggers automated build + test. Finds bugs early, prevents merge hell
Continuous Delivery (CD) — every passing build is deployable to production; deployment triggered manually. Artifact is always release-ready
Continuous Deployment — every passing build automatically deploys to production. Requires high test confidence and good monitoring/rollback
Pipeline stages — typically: Source → Build → Test → Security Scan → Staging Deploy → Smoke Tests → Production Deploy
Artifact — build output stored and versioned (Docker image, JAR, zip). Same artifact deployed across all envs (no rebuilds per env)
Deployment Strategies
Blue/Green Deployment:
Two identical environments (blue = live, green = new)
Deploy to green → run smoke tests → switch traffic to green
Blue stays up for instant rollback
Cost: double infrastructure
Canary Deployment:
Route small % (1-5%) of traffic to new version
Monitor error rates, latency → gradually increase %
Abort if metrics degrade (automatic or manual)
Tools: Argo Rollouts, AWS CodeDeploy, Nginx/Istio
Rolling Update:
Replace instances one by one
Always some of old and new running simultaneously
Default K8s strategy (maxUnavailable, maxSurge params)
Cheaper than blue/green; risk of version mismatch
Feature Flags (Feature Toggles):
Deploy code but enable features selectively
Decouple deployment from release
Tools: LaunchDarkly, Unleash, Flagsmith, Vercel Edge Config
Allows: A/B tests, gradual rollouts, kill switches
Shadow Deployment:
Mirror production traffic to new service
Compare responses — new version doesn't serve real users yet
Good for testing with real data without riskPipeline as Code
# GitLab CI — .gitlab-ci.yml
stages: [test, build, deploy]
variables:
IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
test:
stage: test
image: node:20
cache:
key: $CI_COMMIT_REF_SLUG
paths: [node_modules/]
script:
- npm ci
- npm run lint
- npm run test -- --coverage
coverage: '/Lines\s*:\s*(\d+\.?\d*)%/'
build:
stage: build
image: docker:24
services: [docker:24-dind]
script:
- docker build -t $IMAGE .
- docker push $IMAGE
only: [main]
deploy-staging:
stage: deploy
image: bitnami/kubectl
environment:
name: staging
url: https://staging.myapp.com
script:
- kubectl set image deployment/app app=$IMAGE -n staging
- kubectl rollout status deployment/app -n staging
only: [main]
deploy-production:
stage: deploy
environment:
name: production
url: https://myapp.com
script:
- kubectl set image deployment/app app=$IMAGE -n production
- kubectl rollout status deployment/app -n production
when: manual # require approval
only: [main]CI/CD Best Practices
Fast feedback — keep CI under 10 minutes. Parallelize test suites, cache dependencies, run unit tests first (fail fast)
Immutable artifacts — build once, deploy the same image across staging and production. Never rebuild per environment
Secrets management — never hardcode secrets. Use CI secret variables, Vault, AWS Secrets Manager, or OIDC (keyless auth)
Rollback strategy — always define how to roll back. K8s: kubectl rollout undo. Keep previous image available. Feature flags for quick disable
Branch strategy — trunk-based dev (short-lived branches, merge daily) preferred over GitFlow for CD. Feature flags replace long-lived branches