Continuous Integration and Delivery Foundations, GitLab Pipeline Architecture, and Delivery Flow: Concepts, Architecture, and Mental Model
GitLab CI/CD becomes predictable when you model it as a chain of distinct states rather than as “a YAML file that runs commands.” A source event identifies a ref and immutable commit, GitLab resolves and compiles CI configuration, creates a pipeline and eligible jobs, matching runners execute those jobs through an executor, and only then do artifacts, reports, deployments, and external systems record outcomes. This lesson builds that causal model before adding more syntax.
Learning objectives
- Explain the source → compiled configuration → pipeline → job graph → runner/executor → evidence → deployment chain without collapsing distinct states into “the pipeline ran.”
- Distinguish a pipeline source, ref, SHA, compiled configuration, pipeline, job, stage, runner, executor, artifact, report, environment, deployment, and external target.
-
Use safe predefined metadata such as
CI_PIPELINE_SOURCE,CI_COMMIT_SHA,CI_PIPELINE_ID,CI_JOB_ID, and runner variables to identify what actually executed. - Explain why configuration decisions happen before runner execution and why job-only state cannot retroactively decide whether a pipeline or job existed.
- Relate GitLab CI/CD to continuous integration, continuous delivery, deployment, least privilege, reproducibility, and auditable DevOps evidence.
1. The problem: a green pipeline can still be misunderstood
Teams often begin CI/CD by copying a working
.gitlab-ci.yml file. That can produce a green icon
quickly, but it does not automatically produce an operational mental
model. When something later fails, the team may not know whether
GitLab rejected the configuration, declined to create a pipeline,
omitted a job because of rules, queued a job with no eligible
runner, assigned a runner whose executor could not prepare the
environment, ran a command that exited non-zero, failed to upload an
artifact, or successfully called a deployment API while the target
application remained unhealthy. Those are different states owned by
different layers.
The first skill in this course is therefore evidence tracing, not YAML memorization. A reproducible pipeline should let another engineer answer: what caused this pipeline, which exact commit was evaluated, which configuration was compiled, which jobs existed, which runner and executor handled a job, what the job actually produced, what GitLab stored, and whether anything outside GitLab changed. A pipeline that cannot answer those questions is difficult to debug, audit, secure, or recover.
2. Automation, CI, continuous delivery, and continuous deployment
CI/CD is a family of practices, not one switch. GitLab can automate all of them, but the purpose and evidence differ. Continuous integration asks whether an exact change integrates safely with the shared codebase. Continuous delivery asks whether a verified result is maintained in a deployable state. Continuous deployment goes further and automatically changes a target when policy allows it. Repository automation may do useful work that is neither CI nor deployment.
| Practice | Main question | Useful GitLab evidence | What it does not prove |
|---|---|---|---|
| Repository automation | Can repetitive project work happen consistently? | Pipeline/job identity, logs, API result. | That software was built or releasable. |
| Continuous integration | Does this exact revision build, test, lint, or otherwise integrate? | Source SHA, compiled graph, job results, reports. | That production changed. |
| Continuous delivery | Is a verified artifact or image kept ready for controlled promotion? | Immutable artifact/version/digest, verification evidence, gate state. | That deployment was approved or healthy. |
| Continuous deployment | Should a verified change automatically reach a target? | Deployment identity, authorization, target-side health evidence. | Long-term service health after rollout. |
Mature delivery systems promote evidence and immutable outputs rather than merely chaining shell commands. Later chapters will add artifacts, registries, environments, approvals, OIDC, security reports, and policies. Chapter 01 only needs the conceptual separation so those later controls have a place in the model.
3. The causal GitLab CI/CD execution model
Start with intent. The intent may be a Git push, a merge request, a schedule, a user clicking New pipeline, an API request, a trigger token, or a parent/downstream pipeline. GitLab records the pipeline source and associates the run with a ref and commit. Before any runner executes a job, GitLab resolves the CI configuration, evaluates pipeline-level logic, constructs the job graph, and determines which jobs are eligible to exist. Only then can jobs enter the queue and be matched to runners.
flowchart TD
A[Commit or user / API intent] --> B[Pipeline source + ref + immutable SHA]
B --> C[Resolve .gitlab-ci.yml + includes]
C --> D[Validate and compile configuration]
D --> E[workflow / rule decisions]
E --> F[Pipeline ID + job graph]
F --> G[Eligible job enters queue]
G --> H[Matching runner selection]
H --> I[Executor prepares workspace / container / pod]
I --> J[Checkout + variables + job script]
J --> K[Logs + status + reports + artifacts]
K --> L[Environment / deployment record]
L --> M[External target health + policy / audit evidence]
The arrows are operational boundaries. Valid YAML can still compile to no desired job. A pipeline can exist while a job remains pending because no runner matches its tags or protection state. A runner can start successfully while the job's toolchain is missing. A deployment API can return success while the application later fails a health check. When diagnosing, ask: which state definitely exists, and which next state is missing or wrong?
4. Core nouns: name the objects before debugging them
| Object | Mental model | Evidence to inspect |
|---|---|---|
| Pipeline source | Why GitLab is considering pipeline creation. | CI_PIPELINE_SOURCE, UI/API source field. |
| Ref and SHA | Human-friendly Git reference plus immutable commit identity. |
Ref name, CI_COMMIT_SHA, repository history.
|
| CI configuration | Versioned desired automation plus any resolved includes/components. | Repository file, merged/compiled configuration, CI Lint result. |
| Pipeline | One server-side evaluated execution graph for a source/ref/SHA. | Pipeline ID/IID, source, SHA, status, creation time. |
| Stage | A sequencing group in the default scheduling model. | Stage names and job grouping. |
| Job | An executable unit with its own state, log, variables, and runner assignment. | Job ID, status, stage, timestamps, trace. |
| DAG / needs | Explicit job dependencies that can relax simple stage ordering. | Compiled job graph and dependency edges. |
| Runner | The registered execution agent that accepts eligible jobs. | Runner ID, description, version, tags, protection/scope. |
| Executor | How a runner creates the environment in which a job executes. | Runner configuration/job log; shell, Docker, Kubernetes, and other models. |
| Artifact / report | Explicitly uploaded job output; reports have GitLab-defined semantics. | Producer job/SHA, paths, retention, parsed UI result. |
| Cache | A performance aid for reusable data, not trusted build evidence. | Cache key, hit/miss, backend/runner behavior. |
| Environment / deployment | GitLab records for deployment intent/history and target naming. | Environment, deployment ID/status, actor, target metadata. |
| External target | The cloud, registry, cluster, server, or service changed outside GitLab. | Provider resource/deployment ID, digest, health, external logs. |
Precise language makes incident reports useful. “GitLab failed” is
vague. “Pipeline 812 exists for source push and SHA
…a41f; job 2941 is pending because no protected runner
matches tag release” points directly to the scheduling
layer.
5. Control plane versus execution plane
GitLab performs control-plane work: it stores project configuration, resolves CI configuration, creates pipelines and jobs, evaluates eligibility, queues work, tracks permissions, receives traces, and stores configured artifacts/reports. GitLab Runner performs execution-plane work: a registered runner requests eligible work, an executor prepares an environment, source is obtained, variables are exposed according to job context, scripts run, and results are sent back.
This distinction prevents expensive misdiagnosis. If CI Lint rejects the configuration, changing runner settings cannot help. If a pipeline exists but a job remains pending, the runner/scheduling layer is a better first suspect than shell syntax. If a job is running and a command exits 1, begin with the job trace and tool state. If the job is green but a deployment is unhealthy, move outward to the target.
6. Identity: a branch name is not enough
Branches and tags move; commit SHAs do not. Record the immutable
revision that the pipeline is evaluating. Also record why the
pipeline exists. A push pipeline and a manually started pipeline can
target the same branch and commit while having different
CI_PIPELINE_SOURCE values and therefore different rule
outcomes in later chapters.
Inside a running job, print only the non-secret fields that are
needed for evidence. The following observation block does not print
CI_JOB_TOKEN, environment dumps, or arbitrary
variables:
printf 'pipeline_source=%s\n' "$CI_PIPELINE_SOURCE"
printf 'ref=%s\n' "$CI_COMMIT_REF_NAME"
printf 'sha=%s\n' "$CI_COMMIT_SHA"
printf 'pipeline_id=%s\n' "$CI_PIPELINE_ID"
printf 'job_id=%s\n' "$CI_JOB_ID"
printf 'runner_id=%s\n' "${CI_RUNNER_ID:-unknown}"
printf 'runner_version=%s\n' "${CI_RUNNER_VERSION:-unknown}"
test "$CI_COMMIT_SHA" = "$(git rev-parse HEAD)"
env, printenv, or a complete
variable/context dump as a routine debugging technique.
CI/CD variables can contain credentials and other sensitive values.
Print a narrow allowlist of safe evidence fields.
7. Compilation happens before runner execution
GitLab does not hand the raw YAML file to a runner and ask the
runner to invent a pipeline. GitLab first parses and resolves the
CI/CD configuration, including configuration brought in by supported
reuse mechanisms, then evaluates pipeline/job creation logic. Later
chapters will explore
workflow:rules, job rules,
include, components, child pipelines, and generated
configuration. For now, remember one invariant: the graph must exist
before a runner can execute its jobs.
CI Lint is therefore a control-plane diagnostic. Current GitLab documentation states that it can validate syntax and logic and can simulate pipeline creation to expose more complicated configuration problems. A successful simulation still does not prove that a compatible runner exists or that a shell command will succeed; it proves a different, earlier layer.
Can the document be parsed as YAML?
Does GitLab accept the CI configuration and its resolved syntax/logic?
Can GitLab construct the expected graph in the simulated source/ref context?
Did an eligible runner actually execute commands for a concrete pipeline/job/SHA?
8. Variable availability has phases
GitLab documents predefined variables by availability phase. Pre-pipeline variables are available before a pipeline exists and can participate in decisions such as configuration inclusion. Pipeline variables become available while GitLab creates the pipeline and can influence job rules. Job-only variables appear only when a runner starts a job. This timing is an architectural fact, not trivia.
For example, CI_PIPELINE_SOURCE and
CI_COMMIT_SHA are available early enough to describe
pipeline creation context. Runner-specific values such as
CI_RUNNER_ID are job-only because no runner has been
selected while GitLab is deciding whether the job should exist.
Therefore a rule cannot sensibly depend on a value that exists only
after the rule decision.
9. Runner and executor state: execution is not durable storage
Jobs execute on runners, but the runner is not the pipeline database. Depending on executor and fleet design, workspaces may be ephemeral, reused, or destroyed. Even on a reused host, relying on accidental files from a prior job creates hidden coupling and security risk. Explicit artifacts, registries, or external stores are the durable mechanisms taught later.
GitLab's current runner security guidance warns that the Shell executor has high security risk for untrusted builds because jobs run with the runner user's permissions and can expose host or neighboring project state. The Shell executor is currently in maintenance mode. You do not need to operate a runner in Chapter 01, but you should already know that “it ran on a runner” is not enough; runner scope, executor, protection, network reachability, version, and privilege are part of the evidence.
10. What green proves—and what it does not
| Green / accepted state | What it proves | What still needs evidence |
|---|---|---|
| CI Lint valid | GitLab accepts the checked configuration for the validation context. | Runner availability and command success. |
| Pipeline created | Pipeline-level creation logic allowed a pipeline. | That every expected job is present. |
| Job included | Job-level logic produced the job in this graph. | That a runner can execute it. |
| Job succeeded | The runner reported successful execution for that job attempt. | That every expected artifact/report exists or an external target is healthy. |
| Artifact uploaded | GitLab stored the configured files for that producer job. | That they are the intended files unless content/digest is checked. |
| Deployment record successful | GitLab recorded the deployment outcome reported by the job/integration. | Independent target health and user-facing correctness. |
This state separation is the backbone of the course. It scales from a two-line tutorial job to a multi-project enterprise delivery platform because every layer still needs its own identity and proof.
11. Read-only inspection before mutation
Before adding credentials, changing runner settings, or introducing deployments, inspect what the system already knows. In the GitLab UI, Build → Pipelines identifies pipelines and sources; open a pipeline to inspect its jobs and graph, then open a job to inspect its trace and runner metadata. Settings → CI/CD → Runners shows runner availability when your role permits it. Build → Pipeline editor → Validate provides validation and simulation without requiring a successful runner execution.
Ask these questions in order:
- What source caused or attempted pipeline creation?
- Which exact ref and SHA are involved?
- Which configuration was compiled and validated?
- Does the pipeline exist, and which jobs actually exist in it?
- Which jobs are queued, running, skipped, failed, or successful?
- Which runner/executor handled a running job?
- What durable evidence—artifact, report, registry digest, deployment record—was produced?
- If an external system changed, what independent target-side evidence confirms the change?
12. Foundation mistakes to eliminate now
- “The YAML parses, so CI works.” Parsing is only one early control-plane state.
- “The branch tells me exactly what ran.” Preserve source, ref, and immutable SHA.
- “A job in the YAML must exist in every pipeline.” Compilation and rules can omit jobs.
- “A pending job is a script bug.” The script has not run; inspect runner eligibility/capacity.
- “The workspace is durable.” Persist required results explicitly; do not depend on incidental runner state.
- “A green deploy job means users are healthy.” Verify the external target independently.
- “Printing all variables is the fastest debugging method.” It can leak credentials and expand incident scope.
13. Micro-lab: predict the states before running anything
Imagine a disposable project with one
.gitlab-ci.yml job in an observe stage. A
push to a lab branch creates a pipeline. Before Lesson 2 makes this
real, write down these predictions:
-
The source should be
pushfor the branch push pipeline. -
The pipeline and job should identify the same immutable
CI_COMMIT_SHA. - The job cannot have a runner ID until GitLab assigns an eligible runner.
- If no runner is eligible, the job may remain pending even though configuration and pipeline creation succeeded.
-
If the job runs, its checked-out
HEADshould match the recorded job SHA for this simple branch scenario. - A file remains useful across jobs only if it is persisted through an explicit mechanism such as an artifact; incidental workspace state is not a contract.
- A successful observation job changes no cloud, cluster, registry, or production environment.
Lesson 2 converts these predictions into a safe experiment. The goal is not a green badge; it is a defensible evidence chain.
Knowledge check
A pipeline exists and a job is pending with no
runner assigned. Which layer should you inspect first?
Inspect job scheduling and runner eligibility/capacity first. Pipeline creation already succeeded, and the script has not yet begun.
Why should a pipeline record an immutable SHA instead of relying only on a branch name?
A branch is a movable reference. The SHA identifies the exact commit associated with the pipeline and makes later evidence reproducible.
Can CI_RUNNER_ID be used to decide whether a job
should be created before a runner is assigned?
No. Runner identity is job-only state. Pipeline and job inclusion decisions happen before runner execution.
A deployment job exits 0 after an API accepts a request. What is actually proved?
The job command completed successfully for that request. Deployment completion and application health still require deployment/target-side evidence.
Why is dumping every CI/CD variable to the job log a bad diagnostic pattern?
The environment can contain credentials and sensitive context. Print a narrow allowlist of non-secret evidence fields instead.
Official references and version notes
- Get started with GitLab CI/CD — current first-principles overview of pipeline configuration, jobs, stages, and runners.
- CI/CD pipelines — pipeline sources, basic/stage/DAG pipeline forms, and current pipeline behavior.
- CI/CD YAML syntax reference — authoritative keyword semantics and compatibility notes.
- Predefined CI/CD variables — availability phases and runtime identity variables such as source, SHA, pipeline, job, and runner metadata.
- Runners — current runner scheduling and execution model.
- Validate GitLab CI/CD configuration — current CI Lint behavior, including syntax/logic validation and pipeline simulation.
- Security for self-managed runners — executor trust boundaries and current runner-security guidance.
- Shell executor — current maintenance-mode status and security limitations for untrusted builds.
Version-sensitive statements were rechecked against primary GitLab documentation on 2026-09-11. GitLab and GitLab Runner evolve continuously. The mandatory Chapter 01 path does not depend on a fixed GitLab Runner version, paid tier, external action/template, cloud account, or privileged executor. Re-check current documentation when executing the lesson in a later GitLab release.
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.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0
Send only Ethereum/ERC-20 compatible assets to this
address.