CI rendering¶
What ocx-catalog ci [--check] emits and the rules it enforces
(src/ci/). This is a reference to the mechanics — for a worked setup, see
Deploy on GitHub Pages or
Deploy on GitLab Pages.
Output file per forge¶
ci.forge |
Output path |
|---|---|
github |
.github/workflows/catalog-ci.yml |
gitlab |
.gitlab-ci/catalog.yml |
The GitLab output is a job file meant to be pulled in with include: from
the repository's own root .gitlab-ci.yml — this renderer never writes a
root .gitlab-ci.yml itself.
Generated-file header contract¶
Every file this renderer writes starts with a literal first line:
The version number is TOOL_HEADER_VERSION, bumped only when the
render/discovery/normalize contract changes in a way an older tool version
could no longer safely parse. That line is the entire "is this file ours"
test: a committed file with no header, or a header that doesn't match the
pattern, is invisible to this tool — never read for pins, never
drift-checked, never overwritten. A discovered file whose header names a
version newer than the running tool supports is a hard error
(TOOL_TOO_OLD) rather than a best-effort parse of a contract the tool
doesn't know yet.
--check: drift detection¶
ocx-catalog ci --check re-renders the job set in memory and compares it
against what's committed, through a normalization pass
(normalizeForDrift) rather than a raw byte comparison: line endings are
unified, and the @ref/trailing comment on a uses: (GitHub) or image:
(GitLab) line is stripped before comparing. A Renovate/Dependabot pin bump
on the committed file is therefore never read as drift — only a structural
change, or a different action/image entirely, trips it. A missing file also
counts as drift. Any drift throws, naming every mismatched file, and the CLI
maps that to exit code 65.
Pin carry-forward¶
GitHub Actions pins (uses: owner/action@<sha>) are scraped out of every
discovered generated file and carried forward into the next render, so a
Renovate-bumped SHA survives a re-render instead of reverting to the
template default. GitLab jobs pin by image: instead and carry no uses:
pins at all.
Defaults, used when there's nothing to carry forward:
| Action | Default pin |
|---|---|
actions/checkout |
34e114876b0b11c390a56381ad16ebd13914f8d5 (v4.3.1) |
actions/setup-node |
820762786026740c76f36085b0efc47a31fe5020 (v7.0.0) |
oven-sh/setup-bun |
0c5077e51419868618aeaa5fe8019c62421857d6 (v2.2.0) |
Two situations fall back to the default and warn on stderr instead of carrying a committed pin forward:
- Conflicting pins — the same action pinned to more than one distinct SHA across the discovered files.
- A mutable ref — the committed
uses:value isn't a full 40-hex commit SHA (a branch, a tag,@main).
The mutable-ref case exists because drift normalization strips @ref
before comparing: a hand-edit from a real SHA to @main would otherwise be
invisible to the generated verify-catalog-ci/catalog:verify job, and the
next render would silently adopt that mutable ref as the new pin. Refusing
to carry it forward means a mutable ref can never survive more than one
render cycle.
ci config block¶
| Field | Values | Default |
|---|---|---|
forge |
"github" | "gitlab" |
required |
packageManager |
"npm" | "bun" |
"npm" |
verifyCi |
boolean |
true |
packageManager is a closed union — any other value fails config loading
rather than rendering CI that fails at its own install step. verifyCi:
false omits the verify job from the rendered output.
ci is the one config object whose unknown keys are tolerated: every other
object in catalog.config.json rejects a key it doesn't recognize, but an
unknown key inside ci is passed through untouched (forward-compat for a
newer tool version's own ci fields).
Running ocx-catalog ci against a config with no ci block at all fails
with MISSING_CI_CONFIG — there's nothing to render.
Templates¶
| Template | Renders |
|---|---|
templates/ci/github-ci.yml |
The whole catalog-ci.yml workflow: triggers, top-level permissions: {}, and the build job. |
templates/ci/github-verify-job.yml |
The verify-catalog-ci job, appended into github-ci.yml when verifyCi is true. |
templates/ci/gitlab-ci.yml |
The whole catalog.yml job file: the catalog:build job. |
templates/ci/gitlab-verify-job.yml |
The catalog:verify job, appended into gitlab-ci.yml when verifyCi is true. |
Substitution is single-pass {{key}} replacement — a value substituted into
one placeholder is never re-scanned for placeholders of its own.