Chapter 01Lesson 05~140 minutes

Checkpoint Lab — Continuous Integration and Delivery Foundations, GitLab Pipeline Architecture, and Delivery Flow

Integrate Chapter 01 into one reproducible checkpoint. You will author a minimal two-stage pipeline, predict its state transitions before execution, validate the compiled graph, trigger the same commit from push and the GitLab web interface, verify explicit artifact transfer across jobs, preserve an evidence packet, and explain what every successful state proves—and what remains outside its scope.

CheckpointTwo-stage pipelineArtifactsVerificationCleanup

Learning objectives

Checkpoint objectives

  • Predict pipeline/configuration/job/runner/artifact state changes before executing the lab.
  • Validate a two-stage configuration that intentionally accepts only push and web-created pipelines.
  • Capture source/ref/SHA, pipeline/job IDs, runner identity, and artifact evidence for two controlled pipeline sources.
  • Prove that the second job receives an explicitly persisted artifact rather than relying on a shared runner filesystem.
  • Produce a concise evidence packet, perform guarded cleanup, and bridge the mental model to Chapter 02 configuration compilation.
Checkpoint boundary. The lab is intentionally free/disposable and has no real secrets, package publication, release creation, cloud account, Kubernetes cluster, infrastructure apply, or production deployment. Use a throwaway project or a clearly disposable branch. If no safe runner is available, perform the validation/simulation track and label runtime fields as unobserved.

1. Scenario and acceptance criteria

Build a two-stage pipeline in a disposable project. Stage one captures non-secret identity evidence and uploads it as an artifact. Stage two verifies that the artifact arrived, compares its recorded SHA with the current pipeline SHA, and records the second job's runner identity. You will trigger this pipeline once with a Git push and once through New pipeline for the same branch.

The checkpoint is complete only when you can answer all of these questions with evidence:

  1. Which two pipeline sources were observed?
  2. Which immutable SHA did each pipeline evaluate?
  3. Which pipeline and job IDs identify each execution?
  4. Which runner executed each job, if a runner was available?
  5. How did the evidence file move from stage one to stage two?
  6. What did a green pipeline prove?
  7. Which deployment/external-system claims are explicitly not part of this lab?

2. Preflight and exact disposable identity

Choose a project you are authorized to modify and record its namespace/path. Use a dedicated branch so cleanup can target one exact ref. Verify local state before creating it.

LAB_BRANCH="glci/ch01-checkpoint"

git status --short --branch
git remote -v
git rev-parse HEAD
git log -1 --oneline --decorate

# Confirm the lab branch does not already exist remotely.
git ls-remote --heads origin "$LAB_BRANCH"

If the final command already returns a ref, choose a different disposable branch name rather than deleting an existing branch you did not create. In GitLab, inspect available runners read-only. If the only runners are privileged, production-connected, or outside your authority, choose the simulation track.

3. Predict the state changes before writing the file

Action Prediction Evidence after action
Validate configuration GitLab accepts two jobs in two stages for push context. CI Lint/simulation result.
Push lab branch A pipeline with source push is created for LAB_SHA. Pipeline ID/source/ref/SHA.
Run capture job Runner executes job and uploads evidence/identity.txt. Job ID/runner/log/artifact.
Run verify job Later-stage job receives the prior artifact and verifies its SHA. Second job trace and runner metadata.
Create New pipeline A second pipeline with source web targets the same SHA if branch is unchanged. New pipeline/job IDs and source.

Record your predictions before execution. A checkpoint is more valuable when you can compare expected and observed state rather than merely documenting what happened after the fact.

4. Author the two-stage checkpoint pipeline

Save this configuration as .gitlab-ci.yml. The workflow:rules deliberately bounds pipeline creation to the two sources used by this checkpoint. Later chapters will teach rule design in depth.

workflow:
  rules:
    - if: '$CI_PIPELINE_SOURCE == "push"'
    - if: '$CI_PIPELINE_SOURCE == "web"'
    - when: never

stages:
  - observe
  - verify

capture_identity:
  stage: observe
  script:
    - mkdir -p evidence
    - printf 'source=%s\n' "$CI_PIPELINE_SOURCE" > evidence/identity.txt
    - printf 'ref=%s\n' "$CI_COMMIT_REF_NAME" >> evidence/identity.txt
    - printf 'sha=%s\n' "$CI_COMMIT_SHA" >> evidence/identity.txt
    - printf 'pipeline_id=%s\n' "$CI_PIPELINE_ID" >> evidence/identity.txt
    - printf 'producer_job_id=%s\n' "$CI_JOB_ID" >> evidence/identity.txt
    - printf 'producer_runner_id=%s\n' "${CI_RUNNER_ID:-unknown}" >> evidence/identity.txt
    - test "$CI_COMMIT_SHA" = "$(git rev-parse HEAD)"
    - cat evidence/identity.txt
  artifacts:
    name: "glci-ch01-$CI_PIPELINE_ID-$CI_JOB_ID"
    paths:
      - evidence/identity.txt
    expire_in: 1 day

verify_identity:
  stage: verify
  script:
    - test -s evidence/identity.txt
    - expected="sha=$CI_COMMIT_SHA"
    - found=0
    - |
      while IFS= read -r line; do
        if [ "$line" = "$expected" ]; then
          found=1
        fi
      done < evidence/identity.txt
      test "$found" = "1"
    - printf 'consumer_job_id=%s\n' "$CI_JOB_ID"
    - printf 'consumer_runner_id=%s\n' "${CI_RUNNER_ID:-unknown}"
    - printf 'verified_sha=%s\n' "$CI_COMMIT_SHA"

Current GitLab artifact behavior downloads artifacts from jobs in earlier stages into later-stage jobs by default when dependencies or needs has not changed that behavior. Therefore verify_identity can read the uploaded file even if it executes on a different runner. The file is transferred through an explicit GitLab artifact mechanism, not through an assumption that two jobs share a workspace.

5. Validate and inspect the graph before commit

Use Build → Pipeline editor → Validate. Confirm the configuration is valid and the simulated push pipeline contains capture_identity followed by verify_identity. Preserve the final configuration text or commit diff as part of your evidence packet.

If you already use an authenticated GitLab CLI, the optional equivalent is:

glab ci lint
# Once the branch exists remotely:
glab ci lint --dry-run --include-jobs --ref "$LAB_BRANCH"
A successful simulation proves graph construction for its simulated context. It does not prove runner availability, artifact upload, or shell execution. Keep those acceptance checks separate.

6. Create and observe the push pipeline

git switch -c "$LAB_BRANCH"
git add -- .gitlab-ci.yml
git diff --cached --check
git diff --cached
git commit -m "glci ch01: add checkpoint pipeline"

LAB_SHA="$(git rev-parse HEAD)"
printf 'lab_sha=%s\n' "$LAB_SHA"

git push -u origin "$LAB_BRANCH"

Open the resulting pipeline by its branch/SHA. Record:

  • pipeline ID and source push;
  • ref and exact SHA;
  • capture_identity and verify_identity job IDs/statuses;
  • runner ID/description/version or other non-secret runtime metadata exposed by the jobs;
  • the producer artifact name and contents;
  • the consumer verification log.

If the jobs run on different runners, that strengthens the demonstration: the consumer still sees the explicit artifact because GitLab/Runner transferred it. If the same runner happens to execute both, the artifact declaration remains the contract; do not infer shared workspace semantics from scheduler coincidence.

7. Prove the producer/consumer boundary

Download or browse the producer artifact. It should identify the producer pipeline/job/SHA and contain no secret values. Then compare the consumer job's verified_sha line to the pipeline SHA. The consumer's job ID and runner ID should be treated as independent identities.

Explicit cross-job data flow
            flowchart TD
              A[capture_identity job] --> B[evidence/identity.txt]
              B --> C[GitLab job artifact storage]
              C --> D[verify_identity job downloads prior-stage artifact]
              D --> E[Consumer verifies sha = CI_COMMIT_SHA]
          

This is the first concrete example of durable pipeline evidence. Chapter 10 will explore artifacts, reports, retention, and dependency controls in depth.

8. Trigger the second source without changing the branch

After the push pipeline finishes, do not add another commit. Open Build → Pipelines → New pipeline, choose the exact lab branch, and create a pipeline without adding arbitrary variables. Record its pipeline ID and source. The expected source is web.

Compare it with the push pipeline. If the branch has not moved, the two pipelines should have the same commit SHA and different pipeline/job IDs. Runner assignment may be the same or different. Artifact names also differ because they include pipeline/job IDs.

Field Push pipeline Manual web pipeline Interpretation
Source push web Why each pipeline exists differs.
Ref Lab branch Same lab branch Human-friendly Git reference can be the same.
SHA LAB_SHA LAB_SHA if unchanged Immutable source can be identical.
Pipeline ID Unique Different unique ID They are distinct executions.
Job IDs Unique per job New IDs Job evidence belongs to one pipeline execution.
Runner ID Observed assignment May differ Scheduling is independent of source identity.

9. Assemble the Chapter 01 evidence packet

Create a local note or folder outside the repository containing only non-secret evidence. Do not export tokens or complete environment dumps. A useful packet contains:

Evidence item Required content Why preserve it
Assumptions Date, GitLab offering/tier if known, runner availability, shell/runtime limitations. Makes compatibility claims reviewable.
Source identity Project path, lab branch, LAB_SHA. Anchors all execution evidence.
Configuration Final .gitlab-ci.yml and successful lint/simulation result. Shows desired and compiled graph inputs.
Push execution Pipeline/job IDs, source/ref/SHA, statuses, runner metadata. Proves live execution for source push.
Web execution Same fields for source web. Separates trigger source from revision.
Artifact Producer job identity and identity.txt contents. Proves explicit durable cross-job data.
Consumer proof Consumer job ID and verified_sha log line. Shows the later job verified the transferred identity.
External state None by design. Prevents accidental claims about deployment/cloud health.

10. Explain every green status precisely

Green state What this checkpoint proves What it does not prove
CI Lint/simulation valid GitLab can accept/build the simulated graph. Runner or shell success.
capture_identity green A runner executed the producer script and GitLab received successful job result. That the consumer ran.
Artifact present GitLab stored the declared producer file. That arbitrary workspace state is shared.
verify_identity green The later job received the artifact and found the expected SHA line. Any deployment occurred.
Pipeline green All required jobs in this pipeline completed successfully. That omitted jobs existed, that production changed, or that an external service is healthy.

11. Optional controlled diagnosis drill

Without committing a broken file, copy the configuration into CI Lint and temporarily change verify_identity to use stage: verification while the declared stages remain observe and verify. Observe the validation failure, preserve the error text, then discard the broken copy and validate the original configuration again.

This drill proves that configuration failure can be diagnosed before runner execution. It has no repository side effect and does not contaminate the clean live evidence packet.

12. Simulation-only completion path

If no eligible disposable runner exists, complete the checkpoint through CI Lint/pipeline simulation for the push context and document the expected web-source comparison from the configuration. Your evidence packet must mark job IDs, runner IDs, artifact upload, and consumer verification as not observed. Do not fabricate values.

{
  "completion_mode": "validation-and-simulation",
  "source_sha": "captured-lab-sha",
  "compiled_jobs": ["capture_identity", "verify_identity"],
  "live_job_ids": "not observed",
  "runner_identity": "not observed",
  "artifact_transfer": "not observed",
  "external_side_effects": "none"
}

A transparent limitation is stronger engineering evidence than pretending simulation equals live execution.

13. Guarded cleanup and final verification

Before deletion, verify the branch name and remote ref one last time. Preserve the pipeline IDs and evidence packet locally. Then delete only the lab branch you created.

git fetch origin --prune
git ls-remote --heads origin "$LAB_BRANCH"

# Proceed only after confirming the exact disposable branch.
git push origin --delete "$LAB_BRANCH"

git switch -
git branch -D "$LAB_BRANCH"
git fetch origin --prune
git status --short --branch

Do not delete runners, change runner settings, remove unrelated artifacts, or delete the entire project unless the whole project was intentionally created for this checkpoint and you have verified its exact namespace/path and contents.

14. Operational review and Chapter 02 handoff

Chapter 01 established the causal model: source/ref/SHA, configuration compilation, pipeline creation, job graph, runner assignment, executor execution, durable evidence, and external state are different objects. You have now observed two sources for the same revision and moved evidence explicitly between jobs.

Chapter 02 focuses on the configuration layer itself: .gitlab-ci.yml Structure, Pipeline Compilation, Keywords, Defaults, and Configuration Validation. You will expand the brief CI Lint experience from this checkpoint into a precise model of how GitLab reads, validates, inherits, and compiles pipeline configuration before any job runs.

Next lesson

Next: .gitlab-ci.yml Structure, Pipeline Compilation, Keywords, Defaults, and Configuration Validation: Concepts, Architecture, and Mental Model

Continue with the next lesson in the course sequence and carry forward the evidence-first GitLab CI/CD operating model.

Knowledge check

Why does the checkpoint use both push and web pipelines for the same branch?

If verify_identity runs on a different runner, why can it still read evidence/identity.txt?

What must you write in the evidence packet if no safe runner is available?

A green checkpoint pipeline proves production is healthy. True or false?

Why does the cleanup procedure query the exact remote branch before deletion?

Official references and version notes

Version and compatibility note

The checkpoint configuration and current GitLab behavior described here were rechecked against primary documentation on 2026-09-11. GitLab's UI, Runner versions, hosted compute offerings, and CI/CD semantics can evolve; preserve the evidence model and revalidate concrete platform behavior when running this lab in a later 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.

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