Skip to content

🐛 fix(ci): anchor the dist_* wiring gate to the lint job's steps - #325

Merged
konih merged 3 commits into
mainfrom
lane/gate-harden-01-r2
Aug 23, 2026
Merged

🐛 fix(ci): anchor the dist_* wiring gate to the lint job's steps#325
konih merged 3 commits into
mainfrom
lane/gate-harden-01-r2

Conversation

@konih

@konih konih commented Aug 23, 2026

Copy link
Copy Markdown
Collaborator

Problem

The dist_* wiring gate was structurally unable to detect the failure it exists to
prevent. It located its anchors by grepping the whole ci.yaml for line numbers
and took the first hit with head -1. File-global positions carry no job scope, so
moving the operator-sdk install step out of lint into any other job — anywhere
earlier in the file — still satisfied "install comes before the glob". The gate stayed
green while the lint job ran the dist_* test glob with no operator-sdk binary on
PATH.

Fix

The gate now resolves every anchor via yq over .jobs.lint.steps specifically, so a
step in a sibling job is simply not visible to it. Each anchor must match exactly
once
— zero matches and duplicate matches are both hard failures, closing the
head -1 hole where a second copy masked a moved original. Ordering is asserted on
step indices within the job, not on file lines.

The gate ships a built-in self-test: it mutates the real workflow into each known
broken shape and asserts the gate rejects it. That makes the gate's own detection power
a tested property rather than an assumption.

dist_olm_bundle_test.sh and dist_operatorhub_pr_test.sh get the same anchoring
correction applied to their smaller equivalents.

Verification

An independent reviewer ran a 16-shape mutation sweep and confirmed 11 of 16 shapes
are now caught, versus roughly 0 for the old gate. The fix was proven by
differential: the same mutated ci.yaml leaves the old gate green (rc=0) and makes the
new gate red (rc=1).

Scope

Three shell test scripts. Zero Go files, zero workflow files — no runtime or CI
behaviour changes, only the gate that guards it.

konih added 3 commits August 23, 2026 17:27
The gate compared file-global line numbers and locked onto the first
`head -1` match. Moving the operator-sdk install step out of `lint` into
the earlier `gitleaks` job kept it green -- rc=0, "ok - ci.yaml installs
operator-sdk before the dist_* glob" -- while the job that actually runs
the dist_* glob had no binary. That is exactly the permanent red the gate
exists to prevent.

Every anchor is now resolved with yq over `.jobs.lint.steps`: a matching
step in another job is not a match, and each anchor must resolve to
exactly one step, so a duplicate fails loudly instead of silently
resolving to the first hit. Type guards on `.jobs.lint` and
`.jobs.lint.steps` stop a renamed job from making the whole gate select
over an empty list.

A self-test mutates the real workflow with yq and asserts the checks
reject all three shapes (install moved to gitleaks, installed twice,
installed after the glob), so the gate proves its own non-vacuity on
every CI run rather than only on the happy path.
The diff printed above the failure is symmetric -- "<" is a
config/crd/bases kind absent from spec.customresourcedefinitions.owned,
">" is an owned[] entry whose CRD base is gone -- but the remedy named
only the first direction. On a stale owned[] entry it told the reader to
declare every config/crd/bases kind under owned, which is the opposite of
the fix and sends them looking for a kind that is already there.

State both directions and tie each to the diff marker that produced it.
… not comments

The operator-sdk assertion grepped the raw release.yaml while this same
script already establishes a comment-stripped view for exactly this
reason. release.yaml documents the operator-sdk prerequisite in a comment
directly above the step that installs it, so commenting out the run: line
left the gate green: with the install disabled the check still printed
'All dist OperatorHub PR tests passed.' at rc=0.

The story named ${CODE}; that variable is derived from
hack/operatorhub-pr.sh, so reusing it here would assert about a different
file. Applied the same discipline through a workflow-scoped
${WORKFLOW_CODE} instead.
@codecov

codecov Bot commented Aug 23, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@konih
konih merged commit 62622b4 into main Aug 23, 2026
31 checks passed
@konih
konih deleted the lane/gate-harden-01-r2 branch August 23, 2026 15:35
@sonarqubecloud

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant