Core concepts
pipeline
The full automated sequence of steps — build, test, deploy — that runs every time code changes.
# .github/workflows/ci.yml
jobs:
build: ...
test: ...
deploy: ...
💡 Sometimes called a "workflow" (GitHub Actions) or "job" (GitLab CI) depending on the platform.
trigger
The event that starts a pipeline run — a push, a pull request, a schedule, or a manual click.
on:
push: { branches: [main] }
pull_request: {}
schedule: [{ cron: '0 6 * * *' }]
💡 A pipeline that only triggers on merge to main gives feedback too late — trigger on every PR instead.
runner
The actual machine (virtual or physical) that executes a pipeline's jobs — hosted by the CI provider or self-managed.
runs-on: ubuntu-latest # a hosted GitHub Actions runner
💡 A "self-hosted runner" is your own machine registered with the CI provider — used for special hardware or cost control.
job
A set of steps that run together on the same runner — pipelines are usually composed of several jobs, often in parallel.
jobs:
lint: { runs-on: ubuntu-latest, steps: [...] }
test: { runs-on: ubuntu-latest, steps: [...] }
💡 Independent jobs (lint, test) commonly run in parallel to cut total pipeline time.
Pipeline stages
build stage
Compiles or bundles the source code into a runnable artifact — a binary, a Docker image, a static bundle.
- run: npm run build
💡 A pipeline that fails at the build stage never even reaches your tests — check build errors first.
test stage
Runs the automated test suite against the build output — unit, integration, sometimes e2e tests.
- run: npm test -- --coverage
💡 Split unit and e2e tests into separate jobs so a slow e2e suite doesn't block fast unit-test feedback.
lint stage
Runs static analysis tools to catch style violations and common bugs before the code is even tested.
- run: eslint . --max-warnings=0
💡 Usually the fastest stage — put it first so obvious mistakes fail the pipeline in seconds, not minutes.
quality gate
A required condition — passing tests, minimum coverage, zero lint errors — that a pipeline must satisfy before it's allowed to proceed.
# branch protection rule: "Require status checks to pass before merging"
💡 Distinct from a coverage threshold — a quality gate can bundle multiple checks (tests + coverage + security scan) into one pass/fail signal.
Artifacts & caching
build artifact
A file (or set of files) produced by the build stage and passed on to later stages or stored for later use.
- uses: actions/upload-artifact@v4
with: { name: dist, path: dist/ }
💡 Artifacts let a "build once, deploy many times" pattern — the same binary goes to staging and then production unchanged.
artifact repository
A server that stores and versions build outputs — Docker images, npm packages, compiled binaries — for later deployment.
docker push registry.example.com/team/app:1.4.0
💡 Examples: Docker Hub/GHCR/ECR for images, npm/Artifactory for packages.
caching
Reusing previously downloaded dependencies or build outputs between pipeline runs to save time.
- uses: actions/cache@v4
with: { path: node_modules, key: ${{ hashFiles('package-lock.json') }} }
💡 A stale cache key is a classic source of "works locally, fails in CI" — bust the cache when the lockfile changes.
Deployment
continuous integration (CI)
The practice of merging code changes into a shared branch frequently, with an automated build and test run on every push.
# every push to a PR branch triggers build + test automatically
💡 CI is about catching integration problems early — it doesn't by itself say anything about deployment.
continuous delivery
Every change that passes the pipeline is automatically prepared for release, but a human still clicks the button to actually deploy.
# pipeline builds a deployable artifact on every merge;
# "Deploy to production" requires a manual approval step
💡 The middle ground between manual releases and full continuous deployment.
continuous deployment
Every change that passes the pipeline deploys automatically to production — no manual approval step at all.
# merge to main → pipeline passes → live in production, no human click
💡 Both "continuous delivery" and "continuous deployment" are abbreviated CD — context (or an explicit approval gate) tells you which one a team means.
rollback
Reverting a deployment to the previous known-good version, usually triggered when a new release causes problems.
kubectl rollout undo deployment/api
💡 A fast, reliable rollback path is a prerequisite for safely doing continuous deployment at all.
canary deployment
Rolling out a new version to a small percentage of traffic first, watching for errors, then gradually increasing it.
# 5% of traffic → new version; monitor error rate; ramp to 100% if healthy
💡 Named after "canary in a coal mine" — the small slice of traffic acts as an early warning system.
feature flag
A runtime switch that turns a feature on or off without a new deployment — decouples deploying code from releasing a feature.
if (flags.isEnabled('new-checkout')) { renderNewCheckout(); }
💡 Lets you deploy risky code dark (off by default) and enable it separately once you're confident.
Quality & security
static analysis
Checking code for bugs, style issues, or security problems without actually running it.
# eslint, mypy, sonarqube — all static analysis tools
💡 Distinct from "dynamic analysis", which observes the program while it runs.
dependency scanning
Automatically checking a project's third-party dependencies for known security vulnerabilities.
- run: npm audit --audit-level=high
💡 Tools like Dependabot and Snyk also open automated PRs to bump the vulnerable dependency.
flaky pipeline
A pipeline that fails intermittently for reasons unrelated to the actual code change — usually a flaky test or an infra hiccup.
# "Just re-run it, it's flaky" — a red flag if said too often
💡 Erodes trust in CI over time — teams start ignoring red pipelines, which is exactly when a real failure slips through.
pipeline as code
Defining the CI/CD pipeline itself in a version-controlled file, rather than clicking through a web UI to configure it.
# .github/workflows/ci.yml, .gitlab-ci.yml, Jenkinsfile — all pipeline as code
💡 Same benefits as Infrastructure as Code: reviewable, reproducible, and it travels with the codebase.
Infra & environments
environment (deploy)
A distinct, isolated place code runs — commonly dev, staging, and production, each with its own config and data.
environments:
staging: { url: staging.example.com }
production: { url: example.com, requires_approval: true }
💡 Staging should mirror production as closely as possible — a staging-only bug that surfaces in prod means the environments have drifted.
blue-green deployment
Running two identical production environments; traffic switches from the old ("blue") to the new ("green") all at once, with instant rollback by switching back.
# green is fully deployed and verified → router switches 100% traffic from blue to green
💡 Unlike a canary, there's no gradual ramp — it's an instant, all-or-nothing cutover.
secrets management
Securely storing and injecting sensitive values (API keys, tokens, passwords) into a pipeline without hardcoding them in the repo.
env:
API_KEY: ${{ secrets.API_KEY }}
💡 A secret that ends up printed in build logs is effectively leaked — mask/redact them explicitly.