CI/CD Fundamentals
Continuous Integration (CI) merges and verifies code changes automatically, while Continuous Delivery (CD) releases them safely. Learn the anatomy of a pipeline — lint, build, test, deploy — and why automation is the core of DevOps.
What is this?
CI/CD is the practice of automatically building, testing and releasing software every time code changes. A pipeline is a sequence of stages — usually lint, build, test and deploy — that run without a human in the loop. CI catches integration problems early by merging everyone's changes frequently and verifying them; CD makes every passing commit a candidate for release to staging or production.
Why do you need it?
- Catching a broken build in two minutes beats discovering it on a release day.
- Automated pipelines remove the 'it works on my machine' problem by running every check in a clean, repeatable environment.
- Small, frequent integrations shrink the blast radius of any single change and make debugging trivial.
- Automation turns deployment from a scary, manual ritual into a repeatable, auditable and reversible step.
- A one-click deployable from every commit gives teams the option to ship small and often.
Mental model
An assembly line in a factory
A CI/CD pipeline
Each station does one focused job — parts are inspected (lint), assembled (build), quality-checked (test) and packaged (deploy). If any station rejects the product, the line stops before a defective unit ships. A pipeline is that line, digitized.
How it works
- A developer pushes a commit to the shared repository, which triggers the pipeline automatically.
- The lint stage checks style and obvious errors early, before expensive steps run.
- The build stage compiles source, bundles assets and produces a deployable — the artifact.
- The test stage runs unit, integration and end-to-end suites against the fresh build.
- If every stage passes, the artifact is deployed to an environment; on failure the pipeline stops and reports which stage broke.
Anatomy of a basic CI/CD pipeline: lint, build, test, deploy.
Key commands
git push origin mainThe event that triggers most CI/CD pipelines.
docker build -t myapp:v1 .The build stage: produce a container image from source.
docker run myapp:v1 npm testRun the test suite inside a clean, disposable environment.
grep -ri 'TODO' src && echo 'blocked' || echo 'lint clean'A minimal lint gate that fails the pipeline on leftover markers.
docker push myapp:v1The deploy stage: publish the artifact to a registry.
Examples
A pipeline run, stage by stage
git push origin main# triggered: build-1 run started# [1/4] lint -> grep -ri "TODO" src || echo "clean"# [2/4] build -> docker build -t myapp:v1 .# [3/4] test -> docker run myapp:v1 npm test# [4/4] deploy -> docker push myapp:v1Success — build-1 finished in 3m 42s, deployed to stagingThe push event triggers the pipeline. Each stage is a step that must pass before the next runs. The last stage produces and deploys an artifact. Any failure halts the run and flags the offending stage so the change never reaches production unreviewed.
In production
- Merge checks gate pull requests — a red pipeline blocks merging, protecting main.
- Every main-branch commit is built, tested and deployed to staging automatically.
- Release tags trigger production deployments, so a version in production is always traceable to a commit.
- Nightly pipelines run expensive test suites and security scans that are too slow for every commit.
- Metrics like build time and failure rate feed DORA-style delivery performance tracking.
Best practices
- Fail fast: run the cheapest checks (lint, formatting) first so teams get feedback in seconds.
- Keep pipelines fast enough that developers wait for them — slow pipelines get ignored.
- Treat every stage as a gate: a failing stage must stop the run, never continue.
- Build once, test many: produce a single artifact and reuse it through test and deploy stages.
- Make the environment reproducible from code so builds are identical everywhere.
Common mistakes
- Building the artifact once per environment, so production runs code that never passed tests.
- Skipping tests in the pipeline 'because they pass locally'.
- Letting a flaky check fail the pipeline randomly and training developers to ignore red.
- Manually deploying because the pipeline is too slow or too broken to trust.
Common issues
Pipeline passed locally but failed on the runnerThe CI environment differs from your machine — missing dependencies, different versions, no secrets.
Compare the runner image with your local environment and pin dependency versions in lockfiles.
Build fails with 'command not found'A tool is installed locally but not in the pipeline image.
Install the tool in the runner image or use a pre-built image that already includes it.
Deploy stage never runs after tests passThe deploy stage is gated on a condition or approval that never becomes true.
Check the stage's condition expression and the environment's protection rules and approvals.
Debugging tips
- Read the failing stage's logs first — the pipeline reports exactly where it stopped.
- Reproduce locally with the same commands the stage runs to isolate environment drift.
- Check the diff of the triggering commit; most pipeline failures trace to a single change.
- Look for non-determinism (dates, ordering, network) when the same commit passes and fails.
Interview checkpoint
Hands-on lab
- Create a small project with a source file and Dockerfile
- Run a lint gate manually
- Build a container image as the artifact
- Deploy the container and verify it with curl
Hand-Run Your First Pipeline
25 min · beginner
Quick quiz
What is the correct order of the four classic pipeline stages?
The artifact produced by the build stage should be the exact artifact deployed to production.
What triggers a CI/CD pipeline in most modern setups?
Cheat sheet
lintFast static checks on style and syntaxbuildCompile source into an artifacttestUnit, integration, e2e validationdeployShip the artifact to an environmentpipelineA series of stages triggered by an eventstageA logical phase such as test or deployartifactThe immutable build outputrunnerThe machine that executes a jobgreen/redPipeline passing or failing