CI/CD Components, Component Catalog, inputs, Versioned Reuse, and Organization-Wide Pipeline Building Blocks: Diagnostics, Failure Modes, Security, and Performance
Component failures often look like ordinary pipeline failures even when the causal layer is the reusable interface. This lesson diagnoses implicit secret assumptions, moving references, job-name collisions, breaking contract changes, provenance gaps, input validation failures, and permission errors while preserving the original compiled evidence.
Learning objectives
- Diagnose component problems from source/ref and expanded configuration before investigating runners or scripts.
- Recognize implicit-secret dependencies, moving-reference drift, generated-job collisions, breaking changes, and provenance gaps.
- Preserve the original pipeline/configuration evidence before retrying, upgrading, or changing a shared component.
- Repair the smallest causal contract/version/permission edge without broad tokens, unpinned fallbacks, or policy bypass.
- Separate catalog/discovery failures from include resolution, input validation, job execution, artifact, and external-system failures.
1. Evidence-first diagnostic sequence for reusable components
- Preserve pipeline/configuration error, pipeline/job IDs if they exist, consumer source/ref/SHA, and first failure.
- Confirm the exact component project/path and requested/resolved version/ref.
-
Inspect component source plus
spec:inputsand consumer arguments without exposing secret values. -
Inspect expanded configuration: generated job names, stages,
rules, image, scripts, artifacts, variables, tags, and
needs. - If jobs exist, inspect graph/queue/runner/executor/toolchain next.
- Then inspect script/network/identity, reports/artifacts, and any external target.
- Apply the smallest contract/version/permission correction and rerun only the safe scope.
This order prevents runner debugging when the component never compiled and prevents version changes from destroying the original failure evidence.
2. Failure mode: the component silently expects a caller secret
A component contains
curl -H "Authorization: Bearer $DEPLOY_TOKEN" ... but
its README never declares that identity. Some projects happen to
define the variable, so tests pass; another project receives a 401
or, worse, a broad inherited group credential.
Repair: make identity prerequisites explicit,
minimize scope, use a safer job identity or OIDC when appropriate,
add an authorization-negative test, and never print the token while
diagnosing. Do not convert the secret into a normal
spec:input.
3. Failure mode: an unversioned reference drifts
A consumer uses @main. The component maintainer changes
an image, script, or input default. A new consumer pipeline compiles
different jobs although the consumer commit is unchanged.
# Fragile for stable production
include:
- component: $CI_SERVER_FQDN/platform/components/check@main
inputs:
job-prefix: app
# Stronger controlled identity
include:
- component: $CI_SERVER_FQDN/platform/components/check@1.4.2
inputs:
job-prefix: app
Preserve the old pipeline’s resolved configuration and source identity before upgrading. A retry of an existing pipeline and a new pipeline are different evidence.
4. Failure mode: generated job names collide
Two components both create a job named scan, or the
same component is included twice without caller-specific naming.
Depending on merge behavior, configuration can override or conflict
in surprising ways.
Repair: expose a required job-name/prefix input and validate it. After repair, inspect expanded configuration and count the expected jobs before runtime.
5. Failure mode: breaking change released under the same compatibility promise
Version 1.6 changes an input from stage string to a new
required execution_stage with no default. Existing
@1 consumers start failing at configuration time. The
problem is not “GitLab randomly broke”; the producer violated its
major-version compatibility contract.
Repair: restore backward compatibility in the same major or publish a new major with migration guidance. Add contract tests that compile representative old invocations before every release.
6. Failure mode: consumer cannot prove provenance
A pipeline log only says component=security-check. It
does not record source project, requested selector, resolved
release/SHA, or consumer SHA. During an incident, teams cannot
determine which code generated the job.
Repair: retain safe provenance in evidence: component path, exact pin/resolved identity, consumer SHA, pipeline/job IDs, expanded config, and tool/image digest where relevant. Do not log secrets to obtain “more context.”
7. Intentionally broken example: reject an invalid input without hiding the cause
spec:
inputs:
mode:
default: audit
options: [audit, enforce]
---
policy:
script: echo "mode=$[[ inputs.mode ]]"
# Consumer passes:
# inputs:
# mode: bypass
The correct expected result is a configuration/input validation
error. Preserve that exact message. The wrong fix is to add
bypass merely to make the pipeline green. Decide
whether the contract should support that state through review and
policy, not incident pressure.
8. Permission and visibility failures are compilation/access state
A private component may be visible in a browser to one user but unavailable to the pipeline/user context that compiles another project. Diagnose project visibility, role/membership, instance boundary, and the exact reference. Do not weaken the component project to public or inject a broad PAT as the first troubleshooting step.
9. Distinguish component success from downstream side-effect success
A component can compile and its job can succeed while an artifact fails ingestion, a registry push goes to the wrong namespace, or a deployment target is unhealthy. The component contract must say what it owns: configuration, job success, retained evidence, and any external side effect are separate outcomes.
10. Performance: avoid turning components into hidden pipeline bloat
A component that creates ten jobs, downloads large artifacts, and calls external APIs may be easy to include but expensive at scale. Measure generated-job count, queue time, runner usage, artifact/cache transfer, and critical path. Make heavy behavior explicit through inputs or separate components rather than surprising every consumer.
11. Unsafe troubleshooting shortcuts to reject
-
Do not switch to
@mainor~latestjust because an exact release fails. - Do not print tokens/variables to discover why a component cannot authenticate.
- Do not grant privileged runners or broad PATs to “make the component work.”
- Do not disable TLS or component source review for remote dependencies.
- Do not delete/recreate pipelines before preserving expanded configuration and IDs.
- Do not rebuild release artifacts merely because component transfer/promotion failed.
Knowledge check
A component with an invalid input produces no jobs. What should you inspect first?
The exact component version/spec and consumer inputs/expanded configuration, not runner capacity.
Why is changing @1.4.2 to @main a poor incident fix?
It replaces a known immutable failure with new moving code, destroys reproducibility, and can introduce unrelated changes.
Two component instances produce one visible job. What is the likely first causal layer?
Configuration/job-name collision or merge behavior. Inspect expanded configuration and use caller-controlled unique job names.
A shared component needs a deploy token but never documents it. What is the design flaw?
The component has an implicit security/identity dependency outside its declared contract.
What evidence should be preserved before upgrading a failing shared component?
Consumer source/ref/SHA, requested/resolved component identity, expanded configuration, pipeline/job IDs if present, and first failure evidence.
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.