CI/CD Components, Component Catalog, inputs, Versioned Reuse, and Organization-Wide Pipeline Building Blocks: Concepts, Architecture, and Mental Model
A CI/CD component is best understood as a versioned pipeline API rather than a convenient YAML snippet. This lesson builds the mental model from a component project and spec:inputs through version resolution, consumer arguments, compiled jobs, permissions, side effects, evidence, and compatibility promises.
Learning objectives
- Explain a CI/CD component as a versioned configuration API with a producer, consumer, inputs, generated jobs, and observable side effects.
- Trace component project/version/ref → input interpolation → compiled configuration → jobs → runtime evidence without collapsing these states.
- Distinguish component inputs from CI/CD variables and secret storage, including validation timing and visibility boundaries.
- Compare commit SHA, full SemVer tag, partial SemVer selectors, branches, and ~latest by reproducibility and upgrade risk.
- Inspect component provenance, permissions, generated job names, and compatibility assumptions before running a consumer pipeline.
1. The practical problem: shared YAML is not yet a stable API
Chapter 12 showed how includes, hidden jobs, extends,
anchors, and !reference reduce duplication. Those
mechanisms still expose implementation details: consumers often need
to know internal job names, variables, stages, and merge behavior.
At organization scale, that creates fragile coupling.
A CI/CD component adds a stronger distribution model. The maintainer publishes a named reusable unit with an explicit input contract and version identity. The consumer references that unit and supplies arguments. GitLab resolves the reference and inputs during pipeline creation, merges the resulting jobs into the consumer configuration, and only then can runners execute them.
2. Separate the states before changing anything
| State | Examples | Evidence |
|---|---|---|
| Source/revision | Consumer SHA; component project; component version/ref | Repository URL/path, commit SHA, release/tag identity |
| Compiled configuration | Resolved component + interpolated inputs + caller jobs | Expanded YAML / CI Lint result |
| Job/runner | Generated job names, stage, tags, image, runner | Pipeline/job IDs, runner metadata, trace |
| Identity/trust | Project visibility, component permissions, tokens/secrets exposed to job | Access decision and non-secret scope metadata |
| Evidence/output | Artifacts/reports/logs generated by component jobs | Producer job/SHA, digest, retention, report state |
| External side effects | Registry publish, deployment, API mutation, notification | Exact target identity + authorization + target verification |
| Governance | Owner, release policy, compatibility window, deprecation path | README, changelog/release notes, tests, exception record |
3. Mental model: producer contract → resolved consumer jobs
The component project owns source code and a
templates/ contract. A released or pinned reference
identifies one revision. The consumer supplies explicit inputs.
GitLab validates and interpolates those inputs while compiling the
consumer pipeline. Only the generated jobs that survive
compilation/rules can later enter the runner queue.
Every arrow changes a different kind of state. A successful component lookup does not prove the inputs are valid; valid compiled jobs do not prove a runner exists; a green component job does not prove an external deployment is healthy.
4. A component project is a versioned product boundary
Current GitLab component projects store components under a top-level
templates/ directory. A component can be a single
templates/name.yml file or a
templates/name/template.yml directory. The project
should document every component in a root README and test component
behavior in its own pipeline.
All components in one project share version releases. Current GitLab allows up to 100 components per component project. If one component needs an independent release cadence or radically different ownership, place it in a separate project rather than forcing unrelated APIs to version together.
5. spec:inputs is the public parameter surface
Inputs are configuration-time parameters. They are not mutable
runtime variables and they are not a secret vault. Define only the
choices a caller legitimately needs to make. GitLab validates
required inputs and can enforce type,
options, and regex before a pipeline
starts.
spec:
inputs:
job-prefix:
description: "Unique prefix for generated job names"
regex: '^[a-z0-9-]{2,24}$'
stage:
description: "Consumer stage for the component job"
default: test
options: [test, verify]
strict:
description: "Fail when the synthetic check is not clean"
type: boolean
default: true
---
"$[[ inputs.job-prefix ]]-policy-check":
stage: $[[ inputs.stage ]]
script:
- echo "component contract executed"
- echo "strict=$[[ inputs.strict ]]"
A required job-prefix prevents silent name collisions.
The stage is caller-controlled instead of hard-coded. The boolean
remains typed. If a consumer supplies an invalid prefix or stage,
configuration fails before runner execution.
6. Inputs, variables, and secrets solve different problems
| Mechanism | Best use | Important boundary |
|---|---|---|
| Component input | Stable caller-controlled configuration | Resolved/validated at pipeline creation; treat safe values as API arguments |
| Predefined variable | Project/pipeline/job context | Provided by GitLab; phase availability matters |
| CI/CD variable | Runtime configuration or values from settings | Precedence and protection/masking rules apply |
| Secret provider / protected secret | Sensitive credentials | Authorize narrow retrieval; do not expose as ordinary component input |
7. Version selectors are upgrade policy encoded in syntax
| Reference | Meaning | Use |
|---|---|---|
| Full commit SHA | Exact repository revision | Strongest immutable evidence; ideal for high-assurance pinning/testing |
| 1.2.3 tag | Exact semantic release | Human-readable governed release identity |
| 1.2 | Latest published 1.2.x catalog release | Automatic patch updates within minor line; still a moving selector |
| 1 | Latest published 1.x catalog release | Automatic minor/patch updates within major line |
| ~latest | Latest published catalog release | Most convenient and highest drift risk; avoid for stable production without explicit policy |
| branch (for example main) | Moving repository ref | Useful during controlled development; weak production reproducibility |
8. Resolution, visibility, and permission are part of the contract
include:component references a component on the same
GitLab instance as the consumer. Private component projects require
the consumer/user context to have sufficient access. Therefore “the
URL exists” is not enough: project visibility, membership, and
authorization are compilation state.
Do not solve access failures by inserting a broad personal access token into every consumer. Prefer the platform-supported authorization model and keep component projects scoped and visible according to organizational policy.
9. Read-only inspection before consumption
Before adding a third-party or organization component, inspect its source project, README, release/version, template source, dependencies, generated job names, images, scripts, token expectations, artifacts, network/API targets, and release history. Then inspect the consumer’s expanded configuration with CI Lint or the pipeline editor.
include:
- component: $CI_SERVER_FQDN/platform/ci-components/policy-check@1.4.2
inputs:
job-prefix: service-a
stage: verify
strict: true
The consumer should be able to answer: Which component revision was compiled? Which arguments were supplied? Which jobs were added? Which permissions and side effects can those jobs exercise?
10. Component context can bind resources to the resolved component identity
Current GitLab supports component context fields such as component
name, SHA, version, and original reference when declared in
spec:component. This can help a component refer to a
tool image released at the same version. Because this functionality
arrived after component GA, verify support on older Self-Managed
instances before making it mandatory.
spec:
component: [name, sha, version, reference]
inputs:
stage:
default: test
---
identity-check:
stage: $[[ inputs.stage ]]
script:
- echo "component=$[[ component.name ]]"
- echo "sha=$[[ component.sha ]]"
- echo "version=$[[ component.version ]]"
- echo "requested=$[[ component.reference ]]"
11. Catalog publication is distribution, not correctness proof
The CI/CD Catalog makes component projects discoverable and supports
released version selection. Publishing currently requires the
project to be marked as a catalog project and a SemVer release
created through a GitLab release job after tests
succeed. Catalog presence is useful distribution metadata, but it
does not prove the component is safe for your trust model.
Consumers still audit source, version, permissions, external dependencies, secret handling, and side effects. Maintainers still test every release and publish migration guidance for breaking changes.
12. Common wrong models
- “A component is just an include with a nicer name.” It is also a versioned interface/distribution contract with explicit inputs and catalog semantics.
- “Inputs are secure because they are validated.” Validation is not secrecy. Do not pass credentials as ordinary component inputs.
- “~latest is safest because it is newest.” It is deliberately moving and can cross major versions.
- “A component can silently assume my job names or stages.” Hard-coded global assumptions make reuse brittle; expose necessary choices as inputs and use collision-resistant names.
- “Catalog publication proves compatibility.” Only tests and a maintained compatibility policy support that claim.
Knowledge check
Why is an invalid component input not a runner problem?
Inputs are validated while GitLab builds the pipeline configuration. If validation fails, the pipeline or job graph is never created and no runner has anything to execute.
Which reference gives the strongest immutable identity: main, ~latest, 1, 1.2.3, or a full commit SHA?
A full commit SHA identifies the exact repository revision. An exact release tag is also a useful governed identity, but a SHA is the strongest immutable source pin.
Why should a component expose a job-prefix input?
Generated job names merge into the consumer configuration. A caller-controlled prefix prevents collisions and lets the same component be included multiple times.
Should a database password be a component input?
No. Inputs are configuration parameters, not secret storage. The component should document what secret/identity it needs and retrieve or consume it through the narrow secret/identity mechanism.
What evidence proves which reusable configuration GitLab compiled?
The component project/path, exact resolved version/ref/SHA, supplied inputs, and the consumer expanded configuration together identify the compiled reusable configuration.
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.