Understanding GitLab CI
One YAML file, every commit in your repo runs through it.
What a job is, how stages order them, the cache vs artifact distinction, and the rules: clause that decides what runs when.
The pipeline.
A GitLab pipeline is the sequence of jobs that runs when you push. The pipeline is defined in .gitlab-ci.yml at the repo root. Each job is a Docker container that runs a script. Jobs are grouped into stages; stages run in order; jobs within a stage run in parallel. The default stages are build, test, deploy — most projects start with those three and grow.
Anatomy of a job.
A job needs: image (Docker image to run in), script (shell commands), and a stage assignment. Optional but common:before_script for setup; cache for dependencies that persist across runs; artifacts for files passed to later stages or downloaded by humans; rules for conditional execution; needsfor fine-grained DAG dependencies that bypass strict stage ordering.
Cache vs artifacts.
Cache: files that can be regenerated (npm install output, Maven repo, pip wheels). GitLab caches them by key; later runs restore the cache to skip installation. Artifacts: files produced by the build (compiled binaries, test reports, coverage HTML). Artifacts are uploaded to GitLab and downloadable; they also flow into downstream jobs. Get this wrong and you'll either rebuild dependencies every run or lose your build output.
Rules — the conditional.
The modern way to control when a job runs. rules: - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'→ only on MR pipelines. - if: '$CI_COMMIT_BRANCH == "main"' → only on main. - changes: ["src/**/*"] → only when matching files changed. Rules replace the older only/except syntax; mixing them in one project is a quick way to confusion.
A worked pipeline.
A Node.js app: stage build (npm ci + npm run build, artifacts = dist/), stage test (npm test, depends on build artifacts), stage deploy (rsync dist/ to a server, runs only on main). 30 lines of YAML; first run installs from scratch in 90 s, subsequent runs hit cache and finish in 20 s; test runs in parallel with linting; deploy gated on green tests. The full CI loop in a one-page file.
Node app pipeline
build → test → deploy
3 stages, cache + artifacts, rules for deploy.
npm ci ; npm test ; deploy if branch == main
= Full CI loop in 30 lines
vs GitHub Actions.
Same model, slightly different vocabulary. GitHub uses workflows (multiple files in .github/workflows/), jobs, and steps; GitLab uses one .gitlab-ci.yml, stages, and jobs. Actions has a richer marketplace of pre-built actions; GitLab has tighter integration with the rest of GitLab (releases, registry, security). Pipelines port across in an afternoon once you've translated the syntax.