Checkpoint Lab — Includes, Templates, CI/CD Components, Component Catalog, and Reusable Pipeline Architecture
Extract a repeated pipeline fragment into a reusable versioned unit, predict and inspect the merged configuration, introduce one incompatible input change, record provenance, and clean up safely.
Learning objectives
- Predict the final merged jobs before linting.
- Build a three-file same-commit reusable pipeline with typed inputs.
- Record provenance and runtime SHA evidence.
- Introduce and repair one incompatible input value without hiding the failure.
- Document production dependency trust and cleanup/rollback.
include, CI/CD inputs, CI/CD components, the CI/CD
Catalog, and CI Lint are available on Free/Premium/Ultimate across
GitLab.com, Self-Managed, and Dedicated. Component references must
resolve on the same GitLab instance as the consuming project. The
mandatory labs require only a disposable Free project and local
configuration. Catalog publication is optional because publishing
requires a catalog-enabled component project, appropriate project
roles, a semantic-version release, and repository metadata. The
current glab repo publish catalog command is experimental
and therefore is not a mandatory production path.
1. Checkpoint scenario and preflight
You will build a three-file reusable CI arrangement in one disposable Free project. It demonstrates same-commit local reuse, typed inputs, merged-configuration inspection, provenance recording, one deliberate contract failure, and cleanup. No real secret, external component, Catalog publication, deployment, registry deletion, or privileged runner is required.
| Assumption | Required |
|---|---|
| GitLab tier/offering | Free-compatible on GitLab.com, Self-Managed, or Dedicated. |
| Project role | Enough permission to push a disposable branch and run CI. |
| Runner | Any ordinary eligible runner; if compute is unavailable, CI Lint/merged-YAML evidence still completes the configuration exercise. |
| Secrets | None. Do not add tokens to source or print environment dumps. |
| Catalog | Not required. Publication remains an optional governance extension. |
2. Predict two state changes before touching the repository
Write these predictions first:
| Prediction | Expected |
|---|---|
| Configuration graph | Main file will include one reusable job template and one typed-input file; GitLab will compile them into one merged configuration. |
| Runtime graph | Three harmless jobs will exist; they will execute the same consumer commit SHA and receive no new credential scope. |
| Provenance |
Both included files resolve to the exact same Git commit as
.gitlab-ci.yml because they are local includes.
|
| Failure drill | An invalid typed input will prevent configuration/pipeline creation rather than execute an unintended mode. |
3. Create the reusable files
Create .gitlab/ci/ch20-template.yml:
.text_check:
stage: test
script:
- test -n "$TARGET"
- test -f "$TARGET"
- wc -c "$TARGET"
Create .gitlab/ci/ch20-contract.yml:
spec:
inputs:
profile:
options: [quick, full]
default: quick
emit_summary:
type: boolean
default: true
---
contract_check:
stage: test
script:
- printf 'profile=%s summary=%s\n' '$[[ inputs.profile ]]' '$[[ inputs.emit_summary ]]'
Create two harmless fixtures:
mkdir -p labdata
printf 'api fixture\n' > labdata/api.txt
printf 'worker fixture\n' > labdata/worker.txt
4. Compose the main pipeline
stages: [test]
include:
- local: .gitlab/ci/ch20-template.yml
- local: .gitlab/ci/ch20-contract.yml
inputs:
profile: full
emit_summary: true
api_check:
extends: .text_check
variables:
TARGET: labdata/api.txt
worker_check:
extends: .text_check
variables:
TARGET: labdata/worker.txt
Before linting, predict the final stage,
script, and TARGET for
api_check and worker_check, plus the
interpolated input values for contract_check.
5. Validate and capture expanded configuration
PROJECT_ID="12345678"
mkdir -p evidence
jq --null-input --arg yaml "$(cat .gitlab-ci.yml)" '{content:$yaml}' \
| glab api --method POST "projects/$PROJECT_ID/ci/lint?include_merged_yaml=true" \
--header "Content-Type: application/json" --input - \
> evidence/ch20-lint.json
jq '{valid,errors,warnings}' evidence/ch20-lint.json
jq -r '.merged_yaml' evidence/ch20-lint.json > evidence/ch20-merged.yml
Verify: the lint response is valid and your
predicted effective jobs match
evidence/ch20-merged.yml.
6. Record dependency provenance before execution
git rev-parse HEAD > evidence/consumer-before.txt
git hash-object .gitlab-ci.yml .gitlab/ci/ch20-template.yml .gitlab/ci/ch20-contract.yml \
> evidence/source-blob-ids.txt
sha256sum .gitlab-ci.yml .gitlab/ci/ch20-template.yml .gitlab/ci/ch20-contract.yml \
> evidence/source-sha256.txt
The Git blob IDs identify repository content; SHA-256 provides an additional portable evidence digest. Neither proves trust by itself, but both make later comparisons precise.
7. Commit, push, and verify runtime identity
git switch -c ch20/checkpoint
git add .gitlab-ci.yml .gitlab/ci/ch20-template.yml .gitlab/ci/ch20-contract.yml labdata/ evidence/
git commit -m "lab: checkpoint reusable pipeline architecture"
git push -u origin ch20/checkpoint
git rev-parse HEAD
Inspect the resulting pipeline. Verify that all jobs belong to this SHA and that no external endpoint, registry, environment, or secret-bearing variable was introduced.
8. Deliberately break the typed contract
Change only the input value:
include:
- local: .gitlab/ci/ch20-contract.yml
inputs:
profile: turbo
emit_summary: true
turbo is outside the declared options. Run CI Lint
again and preserve the validation error. This is the desired failure
mode: configuration is rejected before a job can execute with an
undefined policy.
9. Repair the smallest cause and re-verify
Restore profile: full (or add a deliberately reviewed
new option in the contract with an appropriate compatibility
decision). Lint again and compare the before/after errors and merged
YAML. Do not add allow_failure; this is a configuration
contract problem, not a runtime failure to suppress.
10. Convert the provenance record into a production dependency statement
Write a short dependency record such as:
dependency: platform/ci-components/verify
mechanism: include:component
consumer-policy: full semantic release
requested-version: 2.3.1
resolved-commit: <record exact reviewed SHA>
source-reviewed-by: <team/person>
runner-requirement: unprivileged
credentials-required: none
rollback: pin previous known-good release/SHA
This record is more operationally useful than “we use the shared template.”
11. Optional Catalog design review
Without enabling anything, verify whether a future component project
would satisfy current publication prerequisites: project
description, root README, templates/, tests, semantic
tag, release job, Catalog-project setting, Owner to enable the
setting, and Maintainer/Owner for publication. Treat the
experimental glab repo publish catalog command as
optional until your instance explicitly supports it.
12. Cleanup and rollback
Keep the evidence files if they are useful learning records. Remove synthetic branch/project resources only after verification.
git switch main
# Inspect before destructive remote deletion.
git ls-remote --heads origin ch20/checkpoint
# If and only if this is your disposable lab branch:
# git push origin --delete ch20/checkpoint
git branch -D ch20/checkpoint 2>/dev/null || true
If you created an optional disposable component project, record its final SHA and consumers first, then delete the project through the UI/API only if no other project depends on it.
13. What Chapter 20 adds to the production GitLab operating model
Your pipeline model now has an explicit software-supply layer: reusable CI code has owners, typed interfaces, immutable provenance, tests, release compatibility, least-privilege execution, consumer migration, and rollback. Chapter 21 will use that model to optimize execution safely—interrupting obsolete work, retrying intentionally, debugging failures, and controlling pipeline cost without destroying evidence.
Knowledge check
What evidence proves what GitLab actually compiled from multiple reusable files?
The CI Lint merged/expanded configuration for the exact consumer configuration and ref.
Why is the deliberately invalid
profile: turbo failure useful?
It proves the input contract rejects unsupported configuration before runtime, preventing an undefined mode from executing.
What two identities should a consumer record for an external component dependency?
A human compatibility reference such as the semantic version and the exact resolved/reviewed commit SHA when available.
What is the least-privilege rule for a reusable component?
Its jobs should receive only the runner capability, network reach, variables, and tokens required for its documented responsibility.
A Catalog release breaks consumers. What is the safest immediate migration control?
Pin consumers to the previous known-good release/SHA, preserve evidence, then fix or release a compatible version rather than following a moving reference.
Why is Catalog publication not mandatory for this checkpoint?
The learning objective is reusable architecture and trust. Publication changes project governance and release state, while local includes/typed inputs demonstrate the same core configuration principles on Free.
Summary
You built, inspected, broke, repaired, and documented a reusable pipeline dependency without paid features or live external infrastructure. The durable production pattern is: small contract, explicit owner, merged-config inspection, immutable provenance, representative tests, least privilege, compatible releases, and a known rollback.
Official references
Primary sources used for the current GitLab 19.3 behavior taught in this lesson:
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.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this
address.