// From code to production, on autopilot.
MANUAL DEPLOYMENTS ARE A RELIC.
In today's fast-paced development environment, waiting for manual testing and deployment is unacceptable. CI/CD transforms your workflow from error-prone manual processes into reliable, repeatable automated pipelines.
WHY CI/CD MATTERS
Every commit should be tested. Every change should be deployed. With automated pipelines, you get faster feedback, fewer bugs in production, and the confidence to ship multiple times per day.
SHIP FAST. SHIP OFTEN. SHIP CONFIDENT.
12 lessons. Complete CI/CD mastery.
What is CI/CD, why it matters, and the modern DevOps workflow
BeginnerGit branching strategies, PR workflows, and commit conventions
BeginnerInstalling Jenkins, creating jobs, and building your first pipeline
BeginnerWorkflows, runners, and native GitHub CI/CD
IntermediateBlue-green, canary, rolling deployments, and feature flags
IntermediateContainerizing applications and using Docker in pipelines
IntermediateAutomated builds, unit tests, integration tests, and test reporting
IntermediateStoring build artifacts, versioning, and artifact repositories
IntermediateTerraform, Ansible, and programmable infrastructure
AdvancedSAST, DAST, secrets management, and secure pipelines
AdvancedPipeline metrics, alerting, and continuous feedback loops
AdvancedGitOps, microservices, and enterprise CI/CD
AdvancedCI/CD is the backbone of modern software development. It transforms chaotic release processes into predictable, automated workflows that scale with your team.
The numbers don't lie: Teams with mature CI/CD practices deploy multiple times per day, have 60% fewer bugs in production, and recover from issues 200x faster.
What you'll master: Jenkins, GitHub Actions, Docker, Kubernetes deployments, and enterprise-grade patterns. By the end, you'll design pipelines that rival those at top tech companies.
Automate everything. Sleep better at night.
CI/CD stands for Continuous Integration and Continuous Delivery (or Deployment). It's a methodology that automates the process of integrating code changes, testing them, and delivering them to production.
# Without CI/CD:
Write code → Manually test → Hope it works → Deploy manually →
Fix production bugs → Repeat
# With CI/CD:
Write code → Auto-test → Auto-deploy → Monitor → Fix if needed → Repeat
┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐
│ CODE │──▶│ BUILD │──▶│ TEST │──▶│ STAGING │──▶│PRODUCtn │
│ COMMIT │ │ COMPILE │ │ UNIT │ │ DEPLOY │ │ DEPLOY │
└─────────┘ └─────────┘ └─────────┘ └─────────┘ └─────────┘
What does CD stand for in CI/CD?
Hint: It means automatic deployment to production
What is the first step in any CI/CD pipeline?
Hint: It starts with pushing code
Every CI/CD pipeline starts with version control. Your Git workflow directly impacts how effective your automation can be. Let's build on solid foundations.
main ──────┬─────────────────────────────
▲ ▲
│ merge │ merge
develop ──┴──────┬──────┬──────┬────┴────
feature feature feature
main ────▶───▶───▶───▶───▶───▶───▶
▲ ▲ ▲ ▲ ▲ ▲ ▲
│ │ │ │ │ │ │
PR PR PR PR PR PR PR
# Bad commits:
- fixed it
- updates
# Good commits (Conventional):
- feat: add user authentication
- fix: resolve memory leak in cache
- docs: update API documentation
- test: add unit tests for auth module
What type of branch is used to propose changes in GitHub Flow?
Hint: PR
What is a short-lived branch strategy called?
Hint: Based on main/trunk
Jenkins is the most popular open-source automation server. It automates the building, testing, and deployment of software. With over 1,800 plugins, it integrates with virtually every tool in your stack.
# On Ubuntu/Debian:
sudo apt update
sudo apt install openjdk-11-jdk -y
wget -q -O - https://pkg.jenkins.io/debian/jenkins.io.key | sudo apt-key add -
sudo sh -c 'echo deb http://pkg.jenkins.io/debian-stable binary/ > /etc/apt/sources.list.d/jenkins.list'
sudo apt update
sudo apt install jenkins -y
sudo systemctl start jenkins
# Access at: http://your-server:8080
pipeline {
agent any
stages {
stage('Checkout') {
steps {
git 'https://github.com/your-org/your-app.git'
}
}
stage('Build') {
steps {
sh 'npm install'
sh 'npm run build'
}
}
stage('Test') {
steps {
sh 'npm test'
}
}
stage('Deploy') {
when {
branch 'main'
}
steps {
sh './deploy.sh production'
}
}
}
}
What file contains a Jenkins pipeline definition?
Hint: Named after Jenkins
What keyword defines a stage in Jenkins pipeline?
Hint: Logical unit of work
GitHub Actions lets you automate, customize, and execute your software development workflows right in your repository. No external servers needed.
# .github/workflows/ci.yml
name: CI Pipeline
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
- name: Build
run: npm run build
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [16, 18, 20]
steps:
- uses: actions/checkout@v4
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
name: Deploy to Production
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Deploy to server
uses: appleboy/ssh-action@v1.0.0
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.SSH_KEY }}
script: |
cd /var/www/app
git pull origin main
docker-compose up -d --build
Where are GitHub Actions workflows stored?
Hint: Hidden folder in repository
What syntax references secrets in GitHub Actions?
Hint: ${{ secrets.??? }}
How you deploy affects your availability, risk, and rollback capability. Let's explore the main strategies and when to use each.
# Traffic switches instantly between two identical environments
[Load Balancer]──▶ [Blue: Production v1] [Green: Idle v2]
After testing green:
[Load Balancer]──────────▶ [Blue: Idle] [Green: Production v2]
# Gradually shift traffic
10% ──────────▶ [New Version]
90% ──────────▶ [Old Version]
If metrics look good:
50% ──────────▶ [New Version]
50% ──────────▶ [Old Version]
Finally:
100% ─────────▶ [New Version]
# Update instances one at a time
[v1] [v1] [v1] [v1] → [v2] [v1] [v1] [v1]
→ [v2] [v2] [v1] [v1]
→ [v2] [v2] [v2] [v1]
→ [v2] [v2] [v2] [v2]
# Toggle features without deploying new code
if (featureFlags.isEnabled('new-checkout')) {
return renderNewCheckout();
} else {
return renderOldCheckout();
}
What deployment uses two identical environments?
Hint: Two colors
What lets you toggle features without deploying?
Hint: Flags to toggle features
Docker provides consistent environments across development, testing, and production. Learn to leverage containers throughout your CI/CD pipeline.
# BAD: Large base image, multiple RUN commands
FROM ubuntu:20.04
RUN apt-get update
RUN apt-get install -y nodejs npm git
RUN git clone /repo
RUN npm install
RUN npm build
# GOOD: Minimal, layered, cached
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
CMD ["node", "index.js"]
# Build stage - heavy tools
FROM golang:1.21 AS builder
WORKDIR /src
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o app .
# Runtime stage - minimal
FROM alpine:3.18
RUN apk --no-cache add ca-certificates
COPY --from=builder /src/app /app
CMD ["/app"]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build image
run: docker build -t myapp:${{ github.sha }} .
- name: Run tests in container
run: docker run myapp:${{ github.sha }} npm test
# Trivy container scanning
- name: Run Trivy
uses: aquasecurity/trivy-action@master
with:
image-ref: 'myapp:${{ github.sha }}'
format: 'sarif'
output: 'trivy-results.sarif'
What is the benefit of multi-stage Docker builds?
Hint: Final image is ???
What tool scans Docker images for vulnerabilities?
Hint: T for Tiny
The build phase transforms your source code into a deployable artifact. This includes compiling, bundling, and preparing your application for testing and deployment.
# Dockerfile for a Node.js app
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:20-alpine AS runner
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
EXPOSE 3000
CMD ["node", "dist/index.js"]
- name: Run tests
run: npm test -- --coverage
- name: Upload test results
uses: actions/upload-artifact@v4
if: always()
with:
name: test-results
path: coverage/
# JUnit XML format is widely supported
npm test -- --junit-xml results.xml
# Coverage reports
npm test -- --coverage --json coverage-final.json
What tests verify individual functions in isolation?
Hint: Single component tests
What builds separate the build environment from runtime?
Hint: Multiple ??? builds
Build artifacts are the output of your build process—compiled binaries, Docker images, npm packages, or any file you need to deploy. Artifact management ensures you can reproduce any build.
MAJOR.MINOR.PATCH
1.2.3
- 1.2.3 → 1.2.4 (patch: bug fixes)
- 1.2.3 → 1.3.0 (minor: new features)
- 1.2.3 → 2.0.0 (major: breaking changes)
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v5
with:
push: true
tags: myuser/myapp:latest
# GitHub Actions artifact retention
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: build
path: dist/
retention-days: 30
What versioning scheme uses MAJOR.MINOR.PATCH?
Hint: ??? versioning
Where do you store built Docker images?
Hint: Docker ???
IaC treats your infrastructure the same way you treat your application code: version control, code review, and automation. No more snowflake servers.
# main.tf
terraform {
required_version = ">= 1.0"
}
provider "aws" {
region = "us-east-1"
}
resource "aws_instance" "web" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t3.micro"
tags = {
Name = "web-server"
}
}
- name: Setup Terraform
uses: hashicorp/setup-terraform@v2
- name: Terraform Init
run: terraform init
- name: Terraform Plan
run: terraform plan -out=tfplan
- name: Terraform Apply
if: github.ref == 'refs/heads/main'
run: terraform apply tfplan
# playbook.yml
---
- name: Configure web servers
hosts: webservers
become: yes
tasks:
- name: Ensure nginx is installed
apt:
name: nginx
state: present
- name: Start nginx
service:
name: nginx
state: started
# Infrastructure repository structure
infrastructure/
├── terraform/
│ ├── prod/
│ └── staging/
└── ansible/
└── playbooks/
What tool defines infrastructure as code?
Hint: HashiCorp
What tool configures servers after provisioning?
Hint: Agentless config management
Security should be integrated throughout your pipeline, not added at the end. Let's build secure pipelines that catch vulnerabilities early.
# SonarCloud in GitHub Actions
- name: SonarCloud Scan
uses: SonarSource/sonarcloud-github-action@master
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
# Gitleaks - Scan for secrets in code
- name: Run Gitleaks
uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# npm audit in CI
- name: Security Audit
run: |
npm audit --audit-level=high
# Trivy container scanning
- name: Run Trivy
uses: aquasecurity/trivy-action@master
with:
image-ref: 'myapp:${{ github.sha }}'
format: 'sarif'
output: 'trivy-results.sarif'
# Using HashiCorp Vault in CI
- name: Fetch secrets from Vault
uses: hashicorp/vault-action@v2
with:
url: ${{ secrets.VAULT_ADDR }}
token: ${{ secrets.VAULT_TOKEN }}
What does "Shift Left" mean in security?
Hint: Move testing ??? in pipeline
What tool scans Docker images for vulnerabilities?
Hint: T for Tiny
A pipeline isn't complete without observability. Track metrics, set up alerts, and create feedback loops that help your team improve.
# Slack notification on failure
- name: Notify on failure
if: failure()
uses: 8398a7/action-slack@v3
with:
status: failure
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}
# Annotations in Datadog/Grafana
- name: Annotate deployment
run: |
curl -X POST "https://api.datadoghq.com/api/v1/monitor" \
-H "DD-API-KEY: ${{ secrets.DD_API_KEY }}" \
-d '{"title": "Deployed to production"}'
1. Automated tests run in staging
2. Canary deployment to 10% traffic
3. Monitor error rates and latency
4. If metrics look good → expand to 100%
5. If issues → automatic rollback
6. Alert team of all events
What metric measures time from commit to production?
Hint: ??? time
What measures how fast you recover from failures?
Hint: Mean Time To ???
Now let's explore advanced patterns used by high-performing engineering organizations. Take your pipeline to the next level.
# Only run affected parts of pipeline
- name: Detect changes
id: changes
uses: dorny/paths-filter@v2
with:
filters: |
api:
- 'api/**'
ui:
- 'ui/**'
jobs:
test-api:
if: steps.changes.outputs.api == 'true'
steps:
- run: npm test --workspace=api
# ArgoCD continuously monitors your Git repo
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: production-app
spec:
source:
repoURL: https://github.com/org/manifests
targetRevision: main
path: production
destination:
server: https://kubernetes.default.svc
namespace: production
syncPolicy:
automated:
prune: true
selfHeal: true
# Internal Developer Platform (IDP)
# Developers can provision resources via PR
# Backstage catalog example
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: my-service
spec:
type: service
lifecycle: production
owner: platform-team
Level 1: Manual - No automation
Level 2: Basic - Automated builds
Level 3: Intermediate - Automated tests
Level 4: Advanced - Automated deployments
Level 5: Elite - Self-healing, data-driven
What tool uses Git as single source of truth for deployments?
Hint: Argo???
What is the highest level of CI/CD maturity?
Hint: Self-healing, data-driven