CI/CD Components, Component Catalog, inputs, Versioned Reuse, and Organization-Wide Pipeline Building Blocks: Guided Hands-On Workflow and Core Operations
This guided workflow builds a tiny component contract with typed inputs, exercises valid and invalid consumers, simulates two released versions without paid infrastructure, inspects generated job names and expanded configuration, and shows the exact syntax for consuming a version-pinned GitLab component.
Learning objectives
- Create a small component-like contract with typed, documented, validated inputs and caller-controlled job naming.
- Consume two simulated versions and compare their effective generated jobs without depending on a paid/admin feature.
- Trigger a deliberate input-validation failure and interpret it as a configuration-creation failure rather than a runner failure.
- Inspect expanded configuration, component/ref identity, pipeline/job IDs, and non-secret outputs as evidence.
- Document a safe upgrade path from one component version to another and complete a layer-selection challenge.
1. Disposable workflow and two execution paths
Use a throwaway project/branch such as
glci-ch13-components-lab /
glci/ch13-components. The mandatory path uses local
component-shaped files with spec:inputs so the contract
can be learned without catalog settings. If your disposable GitLab
project supports components, an optional path tests the same
template with include:component pinned to the current
SHA.
2. Create the component-shaped project layout
Create a root README and two simulated version snapshots. In a real
component project the distributable component would normally live at
templates/greeting/template.yml; the two files below
exist only so one consumer pipeline can compare a v1 and v1.1
contract deterministically.
README.md
templates/
greeting-v1.yml
greeting-v1_1.yml
.gitlab-ci.yml
3. Version 1.0 contract: small, typed, explicit
spec:
inputs:
job-prefix:
description: "Unique prefix for generated job"
regex: '^[a-z0-9-]{2,24}$'
stage:
default: test
options: [test, verify]
greeting:
default: hello-v1
---
"$[[ inputs.job-prefix ]]-greet":
stage: $[[ inputs.stage ]]
image: alpine:3.20.3
script:
- printf 'contract=v1.0\n'
- printf 'greeting=%s\n' '$[[ inputs.greeting ]]'
- printf 'source=%s sha=%s pipeline=%s job=%s\n' "$CI_PIPELINE_SOURCE" "$CI_COMMIT_SHA" "$CI_PIPELINE_ID" "$CI_JOB_ID"
The component exposes only three knobs. It does not assume a production stage, secret, runner tag, external API, or project-specific path.
4. Version 1.1 contract: additive compatible behavior
spec:
inputs:
job-prefix:
description: "Unique prefix for generated job"
regex: '^[a-z0-9-]{2,24}$'
stage:
default: test
options: [test, verify]
greeting:
default: hello-v1.1
uppercase:
type: boolean
default: false
---
"$[[ inputs.job-prefix ]]-greet":
stage: $[[ inputs.stage ]]
image: alpine:3.20.3
script:
- value='$[[ inputs.greeting ]]'
- if [ '$[[ inputs.uppercase ]]' = 'true' ]; then value="$(printf '%s' "$value" | tr '[:lower:]' '[:upper:]')"; fi
- printf 'contract=v1.1\n'
- printf 'greeting=%s\n' "$value"
- printf 'source=%s sha=%s pipeline=%s job=%s\n' "$CI_PIPELINE_SOURCE" "$CI_COMMIT_SHA" "$CI_PIPELINE_ID" "$CI_JOB_ID"
The new boolean has a default, so existing callers can remain compatible. That is an example of a reasonable minor-version change if the generated job behavior stays within the documented contract.
5. Consume both simulated versions with different job prefixes
stages: [test, verify]
include:
- local: templates/greeting-v1.yml
inputs:
job-prefix: old
stage: test
greeting: compatible
- local: templates/greeting-v1_1.yml
inputs:
job-prefix: new
stage: verify
greeting: compatible
uppercase: true
consumer-proof:
stage: verify
image: alpine:3.20.3
script:
- printf 'consumer_sha=%s\n' "$CI_COMMIT_SHA"
Validate first. The expanded configuration should contain
old-greet, new-greet, and
consumer-proof. The two component instances do not
collide because the caller controls the prefix.
6. Prove validation failure before runtime
Change one consumer to use job-prefix: BAD PREFIX!.
Because the input regex rejects that value, GitLab should reject the
configuration before any runner starts. Preserve the validation
message as evidence; do not “fix” it by deleting the regex.
include:
- local: templates/greeting-v1_1.yml
inputs:
job-prefix: "BAD PREFIX!"
stage: verify
greeting: test
This is an interface failure. There is no useful runner log because no job should exist yet.
7. Optional real component path pinned to exact source identity
If the same disposable project is structured as a component project, test the component from its current commit SHA. GitLab’s component documentation recommends testing a component against the current SHA before release.
include:
- component: $CI_SERVER_FQDN/$CI_PROJECT_PATH/greeting@$CI_COMMIT_SHA
inputs:
job-prefix: sha-pinned
stage: test
greeting: current-sha
For a separate consumer project, replace
$CI_PROJECT_PATH with the exact component-project path
and pin a reviewed SHA or exact governed release. Both projects must
be on the same GitLab instance and authorization must permit access.
8. Model two released versions without publishing to the catalog
To practice upgrade reasoning without catalog side effects, record
two synthetic release identities:
v1.0.0 → <SHA-A> and
v1.1.0 → <SHA-B>. Compare the two template diffs,
expanded jobs, and README contract. If you own a disposable
component project, you may create those tags, but catalog
publication is optional and not required for the lesson.
| Evidence | v1.0.0 | v1.1.0 |
|---|---|---|
| Source identity | SHA-A | SHA-B |
| Required inputs | job-prefix | job-prefix |
| Optional inputs | stage, greeting | stage, greeting, uppercase |
| Generated job pattern | ||
| Breaking change? | Baseline | No, if default preserves old behavior |
9. Inspect the generated jobs and runtime identity
For a successful run, record the consumer SHA/pipeline source, pipeline ID, generated job names and IDs, runner/executor, and logs showing only synthetic arguments. In the expanded configuration, prove the interpolated job names and stage values before execution.
printf 'source=%s ref=%s sha=%s pipeline=%s job=%s runner=%s version=%s
' "$CI_PIPELINE_SOURCE" "$CI_COMMIT_REF_NAME" "$CI_COMMIT_SHA" "$CI_PIPELINE_ID" "$CI_JOB_ID" "${CI_RUNNER_ID:-not-observed}" "${CI_RUNNER_VERSION:-not-observed}"
10. Write an upgrade note before changing consumers
A useful upgrade note names the old and new component identity, input changes, generated-job changes, permission/secret changes, side effects, compatibility claim, test evidence, rollback reference, and deadline for deprecation if applicable. “Upgrade to latest” is not an upgrade plan.
11. Layer-selection challenge
A consumer succeeds with v1 but configuration fails with v1.1 before any job appears. The component project is reachable and the runner fleet is healthy. Where do you investigate first?
Expected reasoning: compare resolved version,
spec:inputs, supplied arguments, and expanded
configuration. This is a component contract/configuration layer
problem until evidence proves otherwise.
12. Cleanup and retained evidence
Delete only the disposable branch/project/tags created for the lab after exporting the non-secret evidence packet. If you enabled catalog-project settings in an optional experiment, disable or delete only the disposable project you created; do not modify organization-wide catalog settings.
Knowledge check
Why does the lab use different job prefixes for the two versions?
Both component instances merge jobs into one consumer configuration. Distinct prefixes prevent job-name collisions and make version evidence explicit.
What should happen when BAD PREFIX! violates the input regex?
Configuration should fail during pipeline creation/validation before a runner is assigned.
Why is adding an optional input with a default usually compatible?
Existing consumers do not need to supply the new input, so the old invocation can keep compiling if the default preserves prior behavior.
What is the safest real-component test reference before publication?
A specific commit SHA, commonly the current component-project SHA in its own test pipeline.
What belongs in an upgrade note besides version numbers?
Input/API changes, generated jobs, permissions/secrets, side effects, compatibility evidence, rollback identity, and migration/deprecation guidance.
Version and compatibility note
GitLab and GitLab Runner evolve continuously. Treat version-sensitive YAML, runner/executor behavior, APIs, security features, policy controls, tiers, and deprecations as assumptions to verify against the current official GitLab documentation before production use. Preserve the exact project/ref/SHA, compiled configuration, pipeline/job IDs, runner/tool versions, and external target evidence used for any reproducible lab or incident record.
Official references and version notes
Documentation verification date: 2026-09-11. Component, input, catalog, component-context, analytics, and publication behavior is version-sensitive. Re-check the GitLab version deployed on Self-Managed or Dedicated instances before relying on newer syntax.
- CI/CD components and CI/CD Catalog — component projects, version selectors, permissions, testing, publication, security guidance, and current project limits.
-
CI/CD inputs
—
spec:inputs, interpolation, types, defaults, options, regex validation, size limits, and include inputs. -
CI/CD YAML syntax reference
—
include:component,include:inputs, component context, and current parsing semantics. - Pipeline editor — validate and inspect expanded configuration before execution.
- CI Lint — syntax/configuration validation and pipeline simulation where available.
- Component examples — testing components against the current SHA and coupling versioned resources to component releases.
1/1.2 and ~latest. Catalog
releases require SemVer and publication through a GitLab
release job. Components can only be referenced from the
same GitLab instance. Inputs are resolved at pipeline creation;
missing required or invalid typed/options/regex values reject
configuration before runner execution. A string inside one input
must be under 1 KB, and a string containing interpolated input
content must be under 1 MB. Component context fields
(name, sha, version,
reference) are current functionality but should be
version-checked on older instances.
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.