Chapter 12Lesson 05~285 minutes

Checkpoint Lab — rules, workflow, Pipeline Sources, Changes, Conditions, and Dynamic Pipeline Creation

Design and prove a push/MR/tag/web pipeline matrix, predict every inclusion decision, reproduce one missing or duplicate-pipeline defect, reduce the rule set to a deterministic model, and clean up safely.

CheckpointPipeline matrixPrediction ledgerFailure repairVerificationChapter 13 bridge

Learning objectives

  • Write a complete expected inclusion matrix before running push, MR, tag, and web scenarios.
  • Prove pipeline source/ref/SHA and job existence with independent evidence.
  • Diagnose one intentionally missing or duplicate pipeline from creation-time evidence.
  • Reduce the final workflow/job rules to the smallest deterministic set that satisfies the policy.
  • Clean up synthetic refs/configuration and hand off a production-ready rule contract to Chapter 13.
Availability baseline (verified 2026-08-21). workflow:rules, job rules, rules:if, rules:changes, rules:exists, parent-child pipelines, and dynamic child pipelines are core GitLab CI/CD capabilities on Free, Premium, and Ultimate across GitLab.com, Self-Managed, and Dedicated. Live execution still requires eligible runner capacity; every mandatory exercise therefore has a CI Lint/merged-configuration and prediction path that does not require buying compute. Version-sensitive additions are labeled: directory matching for rules:exists arrived in GitLab 18.2, and rules:changes:regexp is new in GitLab 19.2 and is not required for this chapter.

1. Checkpoint mission

You are defining the first production-style pipeline creation contract for a small service. Requirements:

  • Branch pushes get a lightweight branch pipeline while no MR is open.
  • Once an MR is open, the same branch uses an MR pipeline instead of a duplicate branch pipeline.
  • Tags may create a pipeline for release checks.
  • Manual/web runs are allowed only for explicit operator diagnostics.
  • Docs tests exist only when docs changed; an app marker job exists whenever a committed marker file exists.
  • No deployment, registry push, secret creation, external-system mutation, or privileged runner is part of this checkpoint.

2. Preflight and assumptions

Dimension Assumption / safe fallback
Tier/offering GitLab Free, Premium, or Ultimate on GitLab.com, Self-Managed, or Dedicated.
Role Developer or equivalent ability to push a disposable branch/open MR; tag/manual permissions may vary by protection policy.
Runner Optional for creation/inclusion proof; if no runner exists, jobs may remain pending but pipeline/job objects still demonstrate rules.
Validation Pipeline Editor/CI Lint before every changed rule set.
Secrets None. Print only source/ref/SHA and synthetic markers.
Dynamic child Optional fixture only; not required for passing checkpoint.

3. Minimal candidate policy

workflow:
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
    - if: '$CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS && $CI_PIPELINE_SOURCE == "push"'
      when: never
    - if: '$CI_PIPELINE_SOURCE == "web"'
    - if: '$CI_COMMIT_TAG'
    - if: '$CI_COMMIT_BRANCH'

stages: [inspect, test]

context_probe:
  stage: inspect
  script:
    - printf 'source=%s
' "$CI_PIPELINE_SOURCE"
    - printf 'ref=%s
' "$CI_COMMIT_REF_NAME"
    - printf 'sha=%s
' "$CI_COMMIT_SHA"
  rules:
    - when: on_success

docs_check:
  stage: test
  script: echo "docs check"
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
      changes:
        - docs/**/*
    - if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH'
      changes:
        - docs/**/*

feature_present:
  stage: test
  script: echo "marker present"
  rules:
    - exists:
        - app/feature.flag

4. Prediction ledger — complete before any run

Scenario Expected source Pipeline? docs_check feature_present
Push to lab branch, no MR, docs changed push Yes Included Included
Push to same branch after MR opens merge_request_event is the intended pipeline; duplicate push suppressed One intended MR pipeline Depends on MR diff Included
Tag push push + CI_COMMIT_TAG present Yes Absent with current docs rules Included
Manual UI run on lab branch web Yes Absent with current docs rules Included
App-only MR update merge_request_event Yes Absent Included

5. Build synthetic state and validate

mkdir -p app docs ch12-evidence
printf 'print("checkpoint")
' > app/main.py
printf 'enabled=true
' > app/feature.flag
printf '# Checkpoint docs
' > docs/guide.md
# Save the candidate .gitlab-ci.yml, then validate in Pipeline Editor / CI Lint.
git status --short

If CI Lint reports an error, fix syntax/schema before creating any branch. Save the validation result with the commit SHA once committed.

6. Scenario A — branch push with no MR

git switch -c ch12/checkpoint
git add -- .gitlab-ci.yml app/main.py app/feature.flag docs/guide.md
git diff --cached --check
git commit -m "ch12: checkpoint pipeline matrix"
PUSH_SHA="$(git rev-parse HEAD)"
printf 'push_sha=%s
' "$PUSH_SHA" | tee ch12-evidence/push-sha.txt
git push -u origin ch12/checkpoint

Verify one pipeline object with source push, ref ch12/checkpoint, and SHA equal to PUSH_SHA. Verify both docs_check and feature_present are present. A pending job because of no runner is acceptable; job existence is the creation-time evidence.

7. Scenario B — open MR, then push docs change

Open a disposable MR to the default branch. Change docs and push:

printf '
Second checkpoint line
' >> docs/guide.md
git add -- docs/guide.md
git commit -m "ch12: checkpoint MR docs update"
MR_SHA="$(git rev-parse HEAD)"
printf 'mr_sha=%s
' "$MR_SHA" | tee ch12-evidence/mr-sha.txt
git push

Verify the intended pipeline source is merge_request_event. Confirm there is no second branch-push pipeline for MR_SHA. docs_check should exist because the MR diff contains docs changes.

8. Scenario C — app-only MR change

printf '# app-only checkpoint change
' >> app/main.py
git add -- app/main.py
git commit -m "ch12: checkpoint app-only update"
APP_SHA="$(git rev-parse HEAD)"
printf 'app_sha=%s
' "$APP_SHA" | tee ch12-evidence/app-sha.txt
git push

Verify an MR pipeline exists; docs_check should now be absent while feature_present remains present. This is the clearest proof that change detection and existence detection are separate controls.

9. Scenarios D/E — tag and web without destructive side effects

If project policy permits a disposable tag, create one such as ch12-checkpoint-v0 at the current commit and verify a tag pipeline. Delete the tag after evidence capture. If tag protection prevents this, use CI Lint/prediction only—do not weaken protected-tag policy.

For a web run, use the GitLab UI on the disposable branch if your role permits. Verify source=web. Do not add ad-hoc secret variables to make the run “interesting.”

10. Inject one duplicate-pipeline defect

Temporarily replace the workflow with an overly broad policy:

workflow:
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
    - when: always
Prediction: with an open MR, a push can now create both an MR pipeline and another pipeline allowed by the catch-all. Preserve both pipeline IDs, sources, and the shared commit SHA before repairing the policy.

11. Repair without adding more exceptions

Restore the explicit MR-preference workflow from Section 3. Do not fix the symptom by adding when: never to every job. Push a new harmless commit and verify exactly one intended pipeline for that SHA.

printf '# repair marker
' >> app/main.py
git add -- .gitlab-ci.yml app/main.py
git diff --cached --check
git commit -m "ch12: restore deterministic workflow"
REPAIR_SHA="$(git rev-parse HEAD)"
printf 'repair_sha=%s
' "$REPAIR_SHA" | tee ch12-evidence/repair-sha.txt
git push

12. Optional dynamic child proof

If you choose the optional child fixture, generate only reviewed fixed YAML, store it as an artifact, trigger it, and verify the child’s source is parent_pipeline. Record the generator job ID, artifact, trigger job, and child pipeline ID. Then remove the fixture. Do not pass secrets or unreviewed MR text into generated YAML.

13. Final verification checklist

  • ☐ Every tested pipeline is bound to a recorded commit SHA and source.
  • ☐ Branch-without-MR and MR-with-open-MR behavior matches the prediction matrix.
  • ☐ Duplicate-pipeline failure evidence was preserved before repair.
  • ☐ docs_check reflects the expected change comparison; feature_present reflects repository existence.
  • ☐ No runner privilege, token, protected-resource policy, registry, package, deployment, or external system was changed.
  • ☐ The repaired rule set has no unnecessary final catch-all.
  • ☐ Optional dynamic child configuration, if used, was generated from reviewed fixed input and removed afterward.

14. Cleanup / rollback

Close the synthetic MR. Delete the disposable tag only if you created it and are authorized. Delete the lab branch after confirming evidence SHAs/notes you need are retained locally, or delete the entire disposable project. If this was a shared project, revert only your checkpoint CI and synthetic-file commits; do not rewrite shared history.

15. Production operating model and Chapter 13 bridge

Chapter 12 adds a creation-time policy layer to the GitLab operating model: every pipeline and job now has an explainable reason to exist based on source, ref state, change comparison, repository state, and ordered rules. Duplicate suppression is centralized, dynamic configuration is treated as executable policy, and non-creation is recognized as a security/cost control.

Chapter 13 moves from whether a job exists to what data and secrets the job receives: CI/CD variables, inputs, file variables, masking, protection, and scope. The trust-boundary discipline from this chapter becomes essential there.

Knowledge check

Why must the prediction matrix be written before running the checkpoint?

What proves duplicate pipeline creation?

Why is feature_present still included on an app-only commit?

Why not fix duplicate pipelines by adding exclusions to every job?

What source should an optional child pipeline report?

What is the Chapter 13 trust question that follows this chapter?

Summary

The checkpoint completed the creation-time control loop: define a source matrix → validate → predict → execute/inspect → preserve a deliberate duplicate defect → repair the workflow at the correct layer → verify job inclusion semantics → clean up. The resulting pipeline topology is now deterministic enough to safely introduce variable and secret scoping in Chapter 13.

Official references

Chapter 13

CI/CD Variables, Inputs, Secrets, File Variables, Masking, Protection, and Scope

Next you will reason about data entering jobs: variable types, precedence, masking versus protection, file variables, scoped secrets, and why correct pipeline creation does not by itself make secret delivery safe.

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.