Tags: ci-cd, continuous-integration, continuous-delivery, devops, github-actions, docker, automation
Level: intermediate
TL;DR: Pipeline automation practices covering build, automated testing, container packaging, and reliable deployment workflows across environments.
Continuous Integration automates building and testing code on every push or pull request.
Continuous Delivery ensures every validated build can be deployed to production with manual approval.
Continuous Deployment automatically deploys every build that passes all pipeline stages to production.
Fast feedback loops detect regressions and integration conflicts early in development.
Build artifacts must be immutable and built once, then promoted across stages.
Trunk-based development with short-lived feature branches prevents painful merge conflicts.
Pipeline stages execute sequentially or in parallel: lint, test, build, security scan, deploy.
Secrets and environment variables must be injected at runtime via secret managers.
Health checks and rollback strategies ensure rapid recovery if deployments fail.
Canary releases and blue-green deployments minimize downtime and production risk.
Q: What is the core difference between Continuous Delivery and Continuous Deployment?R: Both automate build, test, and staging deployment, but Continuous Delivery requires an explicit manual trigger for production, whereas Continuous Deployment pushes every passing build directly to production.
Q: How do you guarantee zero downtime during a deployment?R: I use blue-green or rolling deployments with readiness health checks, routing traffic only after new instances are healthy and keeping old instances ready for instant rollback.
Q: How should secret management be handled in CI/CD pipelines?R: I never commit secrets into repositories; I store them in dedicated secret vaults or masked pipeline environment variables and inject them ephemerally during execution.
Q: Why is artifact immutability important across environments?R: Building once and promoting the identical Docker image or binary through dev, staging, and prod guarantees that what was tested is exactly what runs in production.
Rebuilding artifacts per environment instead of injecting configuration at runtime.
Long-running pipelines taking over 15 minutes, which discourages frequent commits.
Flaky tests that pass intermittently, eroding team trust in pipeline results.
Storing unencrypted credentials, tokens, or private keys inside build scripts or repository code.
Missing rollback automation when post-deployment smoke tests fail.
Running heavy end-to-end test suites sequentially without caching dependencies or parallelizing jobs.
# Sample GitHub Actions CI workflow
name: CI Pipeline
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build-and-test:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run lint and typecheck
run: |
npm run lint
npm run typecheck
- name: Run test suite
run: npm test -- --coverage
Bash
# Docker build and multi-stage container tagging
docker build -t app:git-${GITHUB_SHA::7} -t app:latest .
docker push app:git-${GITHUB_SHA::7}
[ ] Canary deployment traffic shifting strategies using reverse proxies or service meshes
[ ] Pipeline caching strategies for dependency managers (npm, pip, maven)
[ ] Implementation of automated rollback on HTTP 5xx spikes or failed health probes
[x] Setting up linting, automated testing, and build gates on pull requests
[x] Decoupling build-time assets from runtime configuration variables