CI/CD Cheat Sheet¶
Name origin: CI/CD stands for Continuous Integration / Continuous Delivery (or Deployment). CI was popularized by Martin Fowler and Kent Beck in the early 2000s as part of Extreme Programming. The "continuous" part means every code change triggers an automated build-and-test cycle — not nightly builds. CD extends this: Continuous Delivery means every change is deployable; Continuous Deployment means every change is automatically deployed.
GitHub Actions¶
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: '1.22'
- run: go test ./...
- run: go build -o app .
deploy:
needs: build
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: ./deploy.sh
GitLab CI¶
stages: [test, build, deploy]
test:
stage: test
image: golang:1.22
script:
- go test ./...
build:
stage: build
image: docker:24
services: [docker:24-dind]
script:
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
deploy:
stage: deploy
only: [main]
script:
- helm upgrade app ./chart --set image.tag=$CI_COMMIT_SHA
Pipeline Best Practices¶
DO:
✓ Pin action/image versions (SHA or tag)
✓ Cache dependencies (node_modules, go mod)
✓ Run tests before build, build before deploy
✓ Use branch protection + required checks
✓ Scan for vulnerabilities in CI (Trivy, Snyk)
✓ Use OIDC for cloud auth (no long-lived secrets)
✓ Fail fast — lint first, slow tests last
DON'T:
✗ Store secrets in pipeline files
✗ Use :latest tags in CI images
✗ Skip tests for "quick" deploys
✗ Grant admin permissions to CI service accounts
✗ Use self-hosted runners without hardening
Docker Build in CI¶
# Multi-stage build (keeps CI image small)
# Dockerfile
FROM golang:1.22 AS builder
WORKDIR /app
COPY go.* ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o app .
FROM gcr.io/distroless/static
COPY --from=builder /app/app /app
CMD ["/app"]
# Build and push in CI
docker build -t registry.example.com/app:$SHA .
docker push registry.example.com/app:$SHA
# Or with buildx for multi-arch:
docker buildx build --platform linux/amd64,linux/arm64 \
-t registry.example.com/app:$SHA --push .
Gotcha:
actions/checkout@v4only checks out a shallow clone by default (fetch-depth: 1). This breaksgit describe,git log, and tools that need commit history. If your pipeline needs full history (e.g., semantic versioning, changelogs), addfetch-depth: 0.
Security Scanning in CI¶
# Container image scan
trivy image --severity HIGH,CRITICAL --exit-code 1 myapp:latest
# Filesystem scan (IaC misconfigs)
trivy fs --security-checks config .
# Secret detection
gitleaks detect --source . --verbose
# SAST
semgrep --config=auto .
Artifact Management¶
# GitHub Actions — upload/download
- uses: actions/upload-artifact@v4
with:
name: app-binary
path: ./app
# Cache dependencies
- uses: actions/cache@v4
with:
path: ~/.cache/go-build
key: go-${{ hashFiles('**/go.sum') }}
Deployment Strategies¶
| Strategy | Risk | Downtime | Rollback |
|---|---|---|---|
| Rolling update | Low | None | kubectl rollout undo |
| Blue/Green | Low | None | Switch LB target |
| Canary | Lowest | None | Route 0% to canary |
| Recreate | High | Yes | Redeploy previous |
Remember: The deployment strategy risk ladder: Recreate (most risk, has downtime) > Rolling (safe default) > Blue/Green (instant rollback via LB switch) > Canary (lowest risk, gradual traffic shift). For most production services, start with rolling update and graduate to canary as your observability matures.
Common CI/CD Failures¶
| Failure | Cause | Fix |
|---|---|---|
| Image pull failed | Wrong registry/tag, auth | Check image name, registry credentials |
| Tests pass locally, fail in CI | Different env, missing deps | Pin versions, match CI env locally |
| Deploy timeout | Health check failing | Check probes, resource limits |
| Permission denied | Missing RBAC, wrong SA | Check service account permissions |
| Cache miss | Changed lockfile hash | Verify cache key includes lockfile |