Core Concepts
5 min readRapid overview
- CI/CD Core Concepts
- Fundamentals
- Continuous Integration (CI)
- Continuous Delivery (CD)
- Continuous Deployment
- GitHub Actions
- Basic Workflow
- Matrix Strategy
- Docker Build and Push
- Deployment Workflow
- Reusable Workflows
- Azure DevOps Pipelines
- YAML Pipeline
- Templates
- Deployment Strategies
- Blue-Green Deployment
- Canary Deployment
- Rolling Update
- Pipeline Security
- Secrets Management
- OIDC Authentication
- Branch Protection
- Best Practices
- Pipeline Optimization
- Artifacts and Dependencies
- Interview Questions
- 1. What's the difference between CI and CD?
- 2. How do you handle database migrations in CI/CD?
- 3. Explain blue-green vs canary deployment
- 4. How do you secure CI/CD pipelines?
CI/CD Core Concepts
Fundamentals
Continuous Integration (CI)
- Developers integrate code frequently (at least daily)
- Each integration is verified by automated build and tests
- Detect integration errors early
Continuous Delivery (CD)
- Every change can be deployed to production
- Deployment is a manual decision
- Always in a deployable state
Continuous Deployment
- Every change that passes tests is automatically deployed
- No human intervention
- Requires high test confidence
GitHub Actions
Basic Workflow
# .github/workflows/ci.yml
name: CI
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
env:
NODE_VERSION: '20'
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
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 build
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: build
path: dist/
Matrix Strategy
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [18, 20, 22]
exclude:
- os: macos-latest
node-version: 18
fail-fast: false
steps:
- uses: actions/checkout@v4
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- run: npm ci
- run: npm test
Docker Build and Push
jobs:
docker:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ghcr.io/${{ github.repository }}
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=sha
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
Deployment Workflow
name: Deploy
on:
push:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npm test
deploy-staging:
needs: test
runs-on: ubuntu-latest
environment:
name: staging
url: https://staging.example.com
steps:
- uses: actions/checkout@v4
- name: Deploy to staging
run: |
# Deployment commands
echo "Deploying to staging"
deploy-production:
needs: deploy-staging
runs-on: ubuntu-latest
environment:
name: production
url: https://example.com
steps:
- uses: actions/checkout@v4
- name: Deploy to production
run: |
echo "Deploying to production"
Reusable Workflows
# .github/workflows/reusable-build.yml
name: Reusable Build
on:
workflow_call:
inputs:
node-version:
required: true
type: string
secrets:
npm-token:
required: true
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ inputs.node-version }}
registry-url: 'https://registry.npmjs.org'
- run: npm ci
env:
NODE_AUTH_TOKEN: ${{ secrets.npm-token }}
- run: npm run build
# .github/workflows/main.yml
name: Main
on: [push]
jobs:
call-reusable:
uses: ./.github/workflows/reusable-build.yml
with:
node-version: '20'
secrets:
npm-token: ${{ secrets.NPM_TOKEN }}
Azure DevOps Pipelines
YAML Pipeline
# azure-pipelines.yml
trigger:
branches:
include:
- main
- develop
pool:
vmImage: 'ubuntu-latest'
variables:
nodeVersion: '20.x'
stages:
- stage: Build
jobs:
- job: BuildJob
steps:
- task: NodeTool@0
inputs:
versionSpec: $(nodeVersion)
displayName: 'Install Node.js'
- script: npm ci
displayName: 'Install dependencies'
- script: npm run lint
displayName: 'Run linter'
- script: npm test
displayName: 'Run tests'
- script: npm run build
displayName: 'Build'
- task: PublishBuildArtifacts@1
inputs:
pathToPublish: 'dist'
artifactName: 'drop'
- stage: DeployStaging
dependsOn: Build
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
jobs:
- deployment: DeployToStaging
environment: staging
strategy:
runOnce:
deploy:
steps:
- script: echo "Deploying to staging"
Templates
# templates/build-template.yml
parameters:
- name: nodeVersion
default: '20.x'
steps:
- task: NodeTool@0
inputs:
versionSpec: ${{ parameters.nodeVersion }}
- script: npm ci
- script: npm test
- script: npm run build
# azure-pipelines.yml
stages:
- stage: Build
jobs:
- job: Build
steps:
- template: templates/build-template.yml
parameters:
nodeVersion: '20.x'
Deployment Strategies
Blue-Green Deployment
# Kubernetes blue-green
apiVersion: v1
kind: Service
metadata:
name: myapp
spec:
selector:
app: myapp
version: blue # Switch to 'green' for deployment
ports:
- port: 80
Pros: Zero downtime, instant rollback Cons: Requires 2x resources, database migrations complex
Canary Deployment
# Istio canary
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: myapp
spec:
hosts:
- myapp
http:
- route:
- destination:
host: myapp
subset: stable
weight: 90
- destination:
host: myapp
subset: canary
weight: 10
Pros: Gradual rollout, reduced blast radius Cons: Complex monitoring, longer deployment time
Rolling Update
# Kubernetes rolling update
spec:
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
Pros: No extra resources, gradual replacement Cons: Mixed versions during deployment
Pipeline Security
Secrets Management
# GitHub Actions
steps:
- name: Deploy
env:
API_KEY: ${{ secrets.API_KEY }}
run: ./deploy.sh
# Azure DevOps - Variable Groups
variables:
- group: production-secrets
OIDC Authentication
# GitHub Actions with AWS OIDC
permissions:
id-token: write
contents: read
steps:
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789:role/github-actions
aws-region: us-east-1
Branch Protection
# Required status checks
on:
pull_request:
branches: [main]
jobs:
required-check:
runs-on: ubuntu-latest
steps:
- run: npm test
# This job must pass for PR to be mergeable
Best Practices
Pipeline Optimization
# Caching
- uses: actions/cache@v4
with:
path: ~/.npm
key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-npm-
# Parallel jobs
jobs:
lint:
runs-on: ubuntu-latest
steps: [...]
test:
runs-on: ubuntu-latest
steps: [...]
# lint and test run in parallel
Artifacts and Dependencies
jobs:
build:
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- id: version
run: echo "version=$(cat VERSION)" >> $GITHUB_OUTPUT
deploy:
needs: build
steps:
- run: echo "Deploying version ${{ needs.build.outputs.version }}"
Interview Questions
1. What's the difference between CI and CD?
- CI: Automates integration - build, test, merge
- CD (Delivery): Automates release preparation, manual deploy decision
- CD (Deployment): Fully automated deployment to production
2. How do you handle database migrations in CI/CD?
- Run migrations as separate job before deployment
- Ensure backward compatibility (expand/contract pattern)
- Use feature flags for new schema requirements
- Test migrations against production-like data
3. Explain blue-green vs canary deployment
Blue-Green:
- Two identical environments
- Instant switch via load balancer
- Fast rollback
- Higher resource cost
Canary:
- Gradual traffic shift
- Monitor metrics during rollout
- Lower risk, longer deployment
- Requires traffic splitting capability
4. How do you secure CI/CD pipelines?
- Use secrets management (never commit secrets)
- OIDC for cloud authentication
- Least privilege access for service accounts
- Branch protection rules
- Audit logging
- Sign artifacts/images
- Dependency scanning