Chapter 10Lesson 01~205 minutes

GitLab CI/CD Foundations: .gitlab-ci.yml, Pipelines, Jobs, Stages, and Execution Model: Concepts, Architecture, and Mental Model

Build the GitLab CI/CD execution model from versioned configuration through pipeline creation, jobs, stages, runner selection, checkout, logs, artifacts, predefined variables, and job identity.

CI/CDPipeline model.gitlab-ci.ymlJobs & stagesRunnersTrust boundaries

Learning objectives

  • Explain the separation between GitLab pipeline creation (control plane) and runner job execution (execution plane).
  • Relate .gitlab-ci.yml, pipeline source, pipeline, stage, job, runner, executor, checkout, log, artifact, and status without conflating them.
  • Distinguish pre-pipeline, pipeline, and job-only variables and explain why evaluation timing matters.
  • Explain how CI_JOB_TOKEN represents temporary job identity and why authentication does not imply unlimited authorization.
  • Inspect pipeline, job, commit, runner, and token-related metadata before changing CI configuration.
Availability baseline (verified 2026-08-21). Core GitLab CI/CD, .gitlab-ci.yml, Pipeline Editor/CI Lint, jobs, stages, ordinary branch and merge-request pipelines, predefined variables, artifacts, runner scheduling, and CI_JOB_TOKEN are available on GitLab Free across GitLab.com, Self-Managed, and Dedicated. GitLab-hosted runners are provided for GitLab.com and GitLab Dedicated; Self-Managed installations provide and operate their own runner capacity. Hosted compute quotas, credits, machine types, and billing can change, so this chapter never hard-codes them and provides a validation-only path whenever a runner is unavailable. Current glab uses the glab ci command family; older pipe/pipeline aliases are deprecated.

1. Why a green pipeline can still be misunderstood

Chapters 01–09 built the hosted collaboration path from project boundaries through merge governance and integration. CI/CD adds a second operating system around that work. A commit does not “run itself.” GitLab reads versioned configuration, decides whether a pipeline exists, materializes jobs, schedules eligible jobs, and hands each job to a runner. The runner then prepares an execution environment, checks out source, injects job-scoped context, executes commands, uploads requested evidence, and reports status.

If those phases are blurred together, teams make dangerous assumptions: “the YAML is valid, so the pipeline must exist,” “the pipeline exists, so a runner must execute it,” or “the job has a token, so it can call any API.” This chapter replaces those assumptions with a state model you can inspect.

2. The core resource chain

From repository configuration to executed evidence
flowchart TD
  A[Git commit / ref] --> B[.gitlab-ci.yml]
  B --> C[GitLab pipeline creation]
  C --> D[Pipeline]
  D --> E[Stage ordering]
  E --> F[Job queue]
  F --> G[Eligible runner]
  G --> H[Executor environment]
  H --> I[Checkout + variables]
  I --> J[script]
  J --> K[Job log / status]
  J --> L[Artifacts if configured]

The arrows are causal. GitLab reads configuration in the context of a commit/ref and pipeline source. It decides which jobs belong to the pipeline. Stage constraints make jobs eligible over time. A matching runner claims an eligible job, its executor creates the runtime context, and the resulting log/status/artifacts are reported back to GitLab.

Object Where it lives What it means Do not confuse it with
.gitlab-ci.yml Repository commit Versioned desired CI/CD configuration. A running pipeline; configuration can exist without creating one.
Pipeline GitLab hosted metadata One evaluated execution graph for a source/ref/SHA. A Git branch or runner process.
Stage Pipeline scheduling model A sequencing group; later stages normally wait for earlier stages. A machine or deployment environment.
Job Pipeline + runner lifecycle One executable unit with its own status/log/context. An entire pipeline.
Runner Execution agent registered with GitLab Requests and executes eligible jobs. The server-side pipeline scheduler.
Executor Runner implementation choice How the runner creates the job environment, such as shell, Docker, or Kubernetes. The runner identity itself.
Artifact GitLab-managed job output Files/reports deliberately uploaded after job execution. The runner workspace or cache.

3. Control plane versus execution plane

GitLab is the control plane. It parses/evaluates CI configuration, creates pipelines and jobs, tracks permissions and policy, queues work, and stores status/log/artifact metadata. GitLab Runner is the execution plane. A runner asks GitLab for work, receives a job it is eligible to execute, prepares an executor, obtains sources and variables, runs commands, and reports results.

This boundary matters for troubleshooting. A pipeline that was never created is not a runner problem. A job that is pending after pipeline creation may be a runner eligibility/capacity problem. A command returning exit code 1 after the job reaches running is an execution problem. Start diagnosis at the phase that actually failed.

Trust boundary: repository CI configuration is executable input. A runner that executes untrusted branch or fork configuration can expose whatever that runner/job context is authorized to reach. Runner isolation and credential scope are therefore security controls, not mere performance settings.

4. A pipeline has a source, ref, and commit identity

A pipeline is not simply “the pipeline for branch X.” GitLab records why it was created. The predefined variable CI_PIPELINE_SOURCE can distinguish sources such as push, merge_request_event, web, schedule, api, trigger, parent_pipeline, and pipeline. The source matters because workflow:rules and job rules can produce different graphs for different origins.

Always pair source with CI_COMMIT_SHA and the ref-related variables. A branch name is movable. A SHA names the commit the job is actually evaluating.

# Read-only from an authenticated local clone.
glab ci list --output json --per-page 10   --jq '.[] | {id,status,source,ref,sha,web_url}'

# For the current branch, inspect pipeline and job details.
glab ci get --output json --with-job-details   --jq '{id,status,ref,sha,source,jobs}'

git rev-parse HEAD
git rev-parse origin/main

5. Configuration and variables exist in phases

GitLab predefined variables are not all available at the same time. Pre-pipeline values exist before pipeline creation and can influence which configuration is included. Pipeline values exist while GitLab builds the pipeline graph and can drive job rules. Job-only values appear only after a runner starts a job and therefore cannot decide whether that job or pipeline was created.

Phase Examples Can affect pipeline graph? Operational question
Pre-pipeline CI_PIPELINE_SOURCE, selected project/ref context Yes, including early configuration choices. Should GitLab even load/include this configuration?
Pipeline Job/stage context and variables available while jobs are created Yes, for supported job rules. Which jobs are added to this pipeline?
Job-only CI_JOB_ID, CI_JOB_TOKEN, CI_RUNNER_ID No; the job already exists. What identity/environment did the runner give this running job?

6. Stages are the beginner scheduling model

With a stages-first pipeline, GitLab normally makes jobs in the same stage eligible together and waits for the previous stage to succeed before later stages proceed. If you omit stages, GitLab has default stage names; if a job omits stage, it belongs to test. Chapter 15 later introduces DAG execution with needs; do not optimize away the simple mental model before you can explain it.

stages:
  - inspect
  - verify

show_identity:
  stage: inspect
  script:
    - printf 'source=%s\n' "$CI_PIPELINE_SOURCE"
    - printf 'sha=%s\n' "$CI_COMMIT_SHA"

verify_checkout:
  stage: verify
  script:
    - test "$CI_COMMIT_SHA" = "$(git rev-parse HEAD)"

7. Runner eligibility is a matching problem

Jobs enter a queue; runners request work. GitLab considers runner scope, availability, protected status where applicable, and tags. If a job declares tags, the runner must satisfy all of those tags. A runner that allows untagged work can claim an untagged job. A job that has no eligible runner stays pending; changing the script cannot fix a scheduling mismatch.

GitLab.com projects can use GitLab-hosted runners when enabled and capacity/quota permits. Dedicated can use hosted runners configured for the tenant. Self-Managed operators provide runner infrastructure themselves. Never infer the executor or isolation level solely from a runner display name—inspect the actual runner/job metadata.

8. CI_JOB_TOKEN is temporary identity, not a universal secret

Just before a job runs, GitLab creates a CI_JOB_TOKEN. It is job-only, valid while the job runs, and revoked when the job finishes. Its effective access is related to the user who triggered the pipeline but is deliberately limited to a documented subset of GitLab resources. Cross-project access is additionally governed by job-token allowlists and the triggering user still needs the underlying permission.

Never print, echo, upload, screenshot, or persist CI_JOB_TOKEN. GitLab masks the token in logs, but runner isolation and script discipline remain essential. Presence can be verified without revealing the value.
token_presence:
  stage: inspect
  script:
    - |
      if [ -n "${CI_JOB_TOKEN:-}" ]; then
        echo "CI_JOB_TOKEN is present; value intentionally not printed"
      else
        echo "CI_JOB_TOKEN is unexpectedly absent"
        exit 1
      fi

9. Read-only inspection checklist before the first CI commit

  • Repository: does .gitlab-ci.yml already exist on the target branch, and at what SHA?
  • Build → Pipelines: what sources, refs, SHAs, and statuses have recently existed?
  • Build → Jobs: which jobs are pending/running/failed, and which runner is shown?
  • Settings → CI/CD → Runners: which runners are available, and do they run untagged jobs? Do not expose registration/authentication tokens.
  • Pipeline Editor / CI Lint: does GitLab accept the configuration, and does simulated creation produce the expected jobs?
  • Compute: if hosted execution is unavailable, stop at validation and use the supplied expected-output fixture rather than purchasing capacity.

10. DevOps connection: prove what executed, where, and as whom

A production pipeline is evidence only when you can answer four questions: what configuration was evaluated, which commit/ref/source it represented, which runner/executor executed each job, and which identity/permissions the job received. Those questions connect source governance to later artifact, environment, release, registry, security, and deployment chapters.

Knowledge check

Why is a pipeline that never appears usually not a runner problem?

Why is CI_COMMIT_SHA stronger evidence than a branch name?

Can CI_JOB_TOKEN be used in workflow:rules to decide whether a pipeline exists?

A job declares tags [linux, docker]. Which runner is eligible?

Why is CI_JOB_TOKEN not equivalent to a personal access token?

Summary

GitLab CI/CD is a state machine spanning versioned configuration, server-side pipeline creation, staged job eligibility, runner scheduling, executor preparation, source checkout, job-scoped identity, execution logs, artifacts, and final status. Correct operations begin by locating the failed phase and proving source/SHA/runner/identity rather than treating “the pipeline” as one opaque process.

Official references

Next lesson

Run the smallest observable pipeline

Lesson 2 validates configuration before commit, executes a tiny Free-compatible pipeline when runner capacity is available, captures pipeline/job/runner evidence, and preserves one deliberately harmless artifact.

Keep the academy open

Support free, practical DevOps education.

Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this address.