A beginner's guide to CI/CD pipelines in YAML
What CI/CD actually does, how to read and write pipeline YAML - jobs, steps, dependencies, artifacts, secrets - and the habits that keep pipelines fast and trustworthy.
Mar 4, 2026 · 4 min read · Kash Gohil
A CI/CD pipeline is a script your platform runs automatically on every push: build the code, run the tests, and - if everything passes - ship it. Nearly every platform (GitHub Actions, GitLab CI, Rezee) describes pipelines in YAML files that live in the repo. This guide explains the concepts and the YAML, for developers setting up their first pipeline.
What do CI and CD actually mean?
Continuous Integration (CI): every change is automatically built and tested when pushed, so breakage is caught in minutes on a branch - not weeks later during a release scramble. The pipeline is an objective referee: if checks fail, the change doesn't merge.
Continuous Delivery/Deployment (CD): the same automation carries a passing build onward - packaging it, and deploying it to staging or production. Delivery means a deploy is always possible at the push of a button; deployment means it happens automatically.
The point of both is the same: replace "works on my machine" and manual release rituals with a repeatable process that runs identically every time.
What are the building blocks of pipeline YAML?
Every platform's dialect differs slightly; the concepts don't. Here's a complete Rezee pipeline (.rezee/actions.yml in the repo) that builds and tests a web app:
name: build-and-test
on:
push:
branches: [main]
jobs:
test:
image: oven/bun:1
steps:
- name: install
run: bun install
- name: test
run: bun test
build:
image: oven/bun:1
steps:
- name: install
run: bun install
- name: build
run: bun run build
artifacts:
- dist/**Reading it top to bottom:
on:(trigger) - when the pipeline runs.push(with branch filters) is the workhorse; many platforms also trigger on PRs, tags, and schedules.jobs- units of work, each running in an isolated container.image- the container the job runs in. Pick an image with your toolchain preinstalled instead of installing it in steps.steps- shell commands, in order. A failing step fails the job; a failing job fails the pipeline.artifacts- files a job preserves after its container is destroyed: the built bundle, coverage reports, logs.- Dependencies - on platforms with a
needs:field (GitHub Actions, GitLab), jobs form a graph: parallel where independent, ordered where required. Rezee's dialect is deliberately minimal today - jobs run in sequence, and a dependency graph is on the roadmap - so structure your jobs accordingly.
That's 80% of pipeline YAML on any platform. The remaining 20% - caching, matrices, environments - are refinements of these ideas.
How do secrets work in pipelines?
Deploy steps need credentials - API tokens, registry passwords - and the cardinal rule is: never in the YAML. The file lives in git; history is forever.
Every platform provides a secret store: values are set once (in Rezee, per repo, encrypted at rest with AES-256-GCM), injected into jobs as environment variables, and masked if they ever appear in logs. In Rezee there's nothing to declare in the YAML - a secret named DEPLOY_TOKEN in the repo's settings simply exists as $DEPLOY_TOKEN in your steps:
deploy:
steps:
- name: deploy
run: ./deploy.sh # reads $DEPLOY_TOKEN from the environmentTwo habits worth adopting from day one: scope secrets to the narrowest repo that needs them, and rotate anything that ever leaks into a log or a script, immediately.
What makes a pipeline good rather than merely present?
Fast. A pipeline is a feedback loop; feedback slower than ~10 minutes changes behavior - people batch changes, context-switch away, and stop trusting it. Parallelize independent jobs, cache dependencies, run the quick checks first.
Deterministic. A flaky test that fails 5% of the time teaches the team to click "retry" - at which point the pipeline referees nothing. Quarantine or fix flakes ruthlessly; a smaller trustworthy suite beats a larger untrusted one.
Required. Passing checks gate the merge, with no bypass culture - for anyone. This matters double once AI agents write code: the pipeline is the one reviewer that never rubber-stamps, and agents iterate honestly against a strict pipeline and destructively against a bypassable one.
Observable. When a job fails, the answer should be one click away: live logs, the failing step highlighted, artifacts downloadable. (Rezee streams pipeline logs live; whatever your platform, dig for the equivalent rather than re-running blind.)
FAQ
What's the difference between a pipeline, a workflow, and an action?
Vocabulary, mostly. GitHub calls the whole file a workflow and reusable steps actions; GitLab and Rezee call the whole thing a pipeline. In every dialect the structure is the same: triggers → jobs → steps.
Do I need Docker to use CI/CD?
You need to choose container images, not build them - image: oven/bun:1 is a menu selection, and the platform runs your steps inside it. Building your own images only becomes relevant when your toolchain outgrows public ones.
How many pipelines should a project have?
Start with one on push that tests everything. Split when you have a reason: a deploy pipeline triggered by tags, a nightly for slow suites. Premature pipeline architecture is a classic way to make CI unmaintainable.
How do CI minutes and pricing work?
Hosted platforms meter the compute your jobs consume, in minutes, with a monthly pool included per plan (Rezee includes 3,000-10,000 minutes depending on tier). Parallel jobs consume minutes concurrently - the speed isn't free, which is one more reason to keep pipelines lean.