Chapter 20Lesson 01~290 minutes

Includes, Templates, CI/CD Components, Component Catalog, and Reusable Pipeline Architecture: Concepts, Architecture, and Mental Model

Build a mental model for GitLab reusable CI/CD configuration: include sources, merge order, typed component inputs, catalog lifecycle, immutable identity, and supply-chain trust.

Mental modelincludeComponentsCatalogTyped inputsSupply chain

Learning objectives

  • Distinguish local/project/remote/template/component include sources and their provenance boundaries.
  • Explain recursive include merging and why the final merged YAML is authoritative.
  • Separate typed inputs from runtime variables/secrets.
  • Explain component version identity, Catalog lifecycle, and supply-chain trust.
  • Inspect reusable configuration read-only before changing it.
Availability baseline (verified 2026-08-22 against current GitLab 19.3 documentation). 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. The practical problem: copy-pasted YAML becomes an ungoverned dependency graph

Chapters 10–19 built increasingly capable pipelines. The next scaling problem is not syntax; it is reuse. Teams copy the same test, scan, build, or deployment fragments into many repositories. Those copies drift, fixes propagate slowly, and a one-line change in a shared source can unexpectedly alter hundreds of consumers.

GitLab provides several reuse layers. The key is to choose the smallest layer that matches the ownership boundary, then treat any remote reusable configuration as supply-chain code.

2. Mental model: source → fetch → validate → merge → instantiate → execute

Reusable configuration evaluation and trust flow
flowchart TD
  R[Repository / \n.gitlab-ci.yml] --> I[include resolver]
  L[local include
same commit] --> I
  P[project include
project + ref + file] --> I
  X[remote include
HTTPS + optional integrity] --> I
  T[GitLab template] --> I
  C[CI/CD component
version + typed inputs] --> I
  I --> M[Merged CI configuration]
  M --> V[CI Lint / pipeline creation]
  V --> J[Jobs]
  J --> Q[Runners + runtime credentials]

GitLab resolves included configuration before pipeline jobs exist. Inputs are interpolated during configuration creation, then the resulting YAML is merged. The final merged configuration—not any one source file—is what defines jobs. Once jobs run, the runner and runtime credentials form a separate trust boundary.

3. Five include sources, five different provenance stories

Source Identity Trust/availability characteristic
include:local Path in the same repository and same commit Strongest coupling to the consumer commit; excellent for repository-local decomposition.
include:project GitLab project + file + optional ref Cross-project reuse on the same instance. Pin a full commit SHA when reproducibility matters.
include:remote HTTPS URL External network and content owner become dependencies. Prefer immutable URL/content plus integrity.
include:template GitLab-provided template name GitLab-maintained template surface; inspect expanded configuration and version-specific behavior.
include:component FQDN/project/component@version Versioned reusable unit with spec:inputs; component must be on the same GitLab instance.

4. Merge order is executable behavior, not formatting

GitLab recursively resolves nested includes first. Included files are merged in the order listed; when included configuration overlaps, later included configuration takes precedence. After the include set is assembled, the main .gitlab-ci.yml is merged and can override overlapping values. This means reading only the shared template is insufficient when diagnosing a job.

include:
  - local: .gitlab/ci/base.yml
  - local: .gitlab/ci/team.yml

# The main file is merged after both includes.
test:
  variables:
    OWNER: application-team

Use CI Lint with merged YAML when the effective result matters. Do not infer inheritance from file layout.

5. Inputs are compile-time contracts; variables are runtime state

A reusable file can declare spec:inputs with types, defaults, options, regex validation, and descriptions. Input interpolation occurs when GitLab fetches configuration, before the configuration is merged. A component or include consumer must pass required values explicitly.

spec:
  inputs:
    stage:
      default: test
    mode:
      options: [quick, full]
      default: quick
    retries:
      type: number
      default: 1
---
shared-test:
  stage: $[[ inputs.stage ]]
  script:
    - printf 'mode=%s retries=%s\n' '$[[ inputs.mode ]]' '$[[ inputs.retries ]]'

Inputs are appropriate for configuration contracts. Secrets remain runtime secret material and should not be embedded in reusable YAML or passed casually as inputs.

6. A CI/CD component is a versioned configuration product

A component packages one reusable CI/CD unit under a component project. Component templates live under templates/; consumers reference a component as host/project/component@version. Components can use typed inputs and can be published to the CI/CD Catalog for discovery.

include:
  - component: $CI_SERVER_FQDN/platform/ci-components/quality@1.4.2
    inputs:
      stage: test
      strict: true

Components should be narrow, composable, documented, tested, and conservative about credentials. GitLab explicitly recommends auditing third-party component source and using minimum-privilege credentials.

7. Version identity: SHA, release tag, branch, partial SemVer, or ~latest

Reference Reproducibility Use
Full commit SHA Highest Strong pin for reviewed exact content; especially useful for ordinary project includes/components.
Full semantic release such as 1.4.2 High Human-readable immutable release contract; recommended catalog consumption pattern.
Partial version such as 1.4 Floating within compatible line Catalog components only; accepts newer matching published patch releases.
~latest Low Follows latest published catalog release; unsuitable where unexpected changes are unacceptable.
Branch such as main Low Useful for development/testing, not deterministic production consumption.

A release tag is only as trustworthy as the repository’s tag/release governance. For maximum immutability, a reviewed full commit SHA is strongest; for managed component products, a semantic release tag gives a clear compatibility contract.

8. Remote includes need content integrity, not just HTTPS

include:remote crosses outside the GitLab project trust boundary. Current GitLab supports integrity, a base64-encoded SHA-256 digest. If the fetched content no longer matches, GitLab rejects it instead of silently compiling changed configuration.

include:
  - remote: 'https://example.invalid/ci/verified.yml'
    integrity: 'sha256-BASE64_SHA256_OF_REVIEWED_CONTENT'

The lab uses example.invalid only as documentation. Do not turn a live third-party URL into a mandatory dependency.

9. Catalog publication is a lifecycle, not an upload button

The Catalog is Free across offerings. A project must first be marked as a Catalog project, then a semantic-version release publishes the component version. Current prerequisites include a project description, root README.md, component configuration under templates/, and creation of the release from a CI job using the release keyword. GitLab requires Owner to enable Catalog-project status and Maintainer or Owner for publication/release work.

Publication should therefore follow tests, review, release notes, compatibility classification, and consumer migration planning.

10. Read-only inspection before editing reuse boundaries

PROJECT_ID="12345678"

# Inspect repository configuration at the current ref.
git show HEAD:.gitlab-ci.yml

# Ask GitLab for expanded/merged configuration using CI Lint.
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 - \
    --jq '{valid,errors,warnings,merged_yaml}'

The exact authentication mechanics of glab api stay outside logs. Never print tokens to prove that linting works.

11. DevOps connection: reusable YAML is executable supply-chain code

A component can select images, invoke scripts, access job tokens, receive project variables, and run on privileged infrastructure. Therefore component review belongs in the same threat model as application dependencies: identify publisher, immutable revision, transitive dependencies, expected permissions, release process, and rollback path.

Knowledge check

Why is include:local usually easier to reproduce than include:project on a branch?

Which configuration wins when an included job and the main .gitlab-ci.yml define overlapping values?

Are typed inputs a good place to pass secrets?

What does a full component commit SHA protect you from?

Can a GitLab.com component be referenced directly by include:component from an unrelated Self-Managed instance?

Summary

Includes assemble reusable configuration; components add a versioned typed contract and Catalog lifecycle. Effective behavior comes from the final merged YAML. Prefer same-commit local reuse when scope is local, immutable project/component references when crossing ownership boundaries, and content integrity for remote includes. Treat every reusable CI dependency as executable supply-chain code.

Official references

Primary sources used for the current GitLab 19.3 behavior taught in this lesson:

Next lesson

Refactor and inspect a reusable pipeline safely

Lesson 2 turns duplicated jobs into a local include, validates the merged result, exercises a component-style typed-input fixture, and records immutable provenance without requiring Catalog publication.

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.