Pipeline Configuration and CI/CD YAML Fundamentals
This domain covers how .gitlab-ci.yml is parsed and composed: which keys are global, which are jobs, how defaults propagate, and how include, extends, and !reference assemble a pipeline. The exam tests whether you can predict the effective configuration of a job after merging, not just recognise keywords.
Structure and reserved keywords
GitLab reads .gitlab-ci.yml from the repository root (overridable with CI_CONFIG_PATH). Top-level keys divide into global keywords (stages, variables, default, include, workflow, image, services, cache, before_script, after_script) and job definitions. Reserved keywords cannot be job names - a job called image or variables makes the file invalid. Job names starting with a dot are hidden templates: parsed, but never added to a pipeline.
stages defaults to build, test, deploy. A job with no stage is placed in test; a job naming an undeclared stage fails pipeline creation. Every job needs script (or trigger). default: centralises image, services, cache, before_script, after_script, tags, retry, timeout, interruptible, and artifacts; a job that declares the key replaces the default rather than merging with it.
Composition
includepulls in local, remote, template, component, or other-project files; the result is one merged document. Keep chains shallow - there is a hard cap on the number of includes.extendsdeep-merges hash keys but replaces arrays, and supports up to eleven levels of inheritance.!reference [job, key]splices one specific value or list item from another job - the way to reuse an array without duplicating it.- YAML anchors work within a single file only; do not rely on an anchor defined in one included file being visible in another. Prefer
extendsor!reference.
Worked example
.defaults:
image: alpine:3.19
before_script:
- echo shared-setup
test:
extends: .defaults
before_script:
- echo job-setup
script: make test
test inherits image: alpine:3.19, but its own before_script replaces the inherited array, so only echo job-setup runs. To keep both, write before_script: [!reference [.defaults, before_script], - echo job-setup].
Traps
- Indenting with tabs - YAML rejects them and the pipeline fails before any job starts.
- Assuming
extendsconcatenates lists such asscriptortags. - Putting job-only keywords (
script,stage,rules) insidedefault:, where they are unsupported. - Shadowing a reserved keyword with a job name.