Skip to content

fix(auto-merge): match required checks by normalised name, and require all of them - #39

Merged
forkwright merged 1 commit into
mainfrom
fix/normalise-required-check-match
Aug 15, 2026
Merged

fix(auto-merge): match required checks by normalised name, and require all of them#39
forkwright merged 1 commit into
mainfrom
fix/normalise-required-check-match

Conversation

@forkwright

Copy link
Copy Markdown
Owner

Finding

The reusable auto-merge matched required checks with endswith() against literal spellings. Three
fleet repos name their OSV job osv-scanner, which ends with neither accepted leaf — "osv-scanner"
does not end with "osv scanner", and it ends with "scanner", not "osv-scan". Those repos could
not adopt this workflow at all: it would refuse every dependabot PR whose OSV check had reported and
passed.

Evidence

  • dependabot-auto-merge.yml:63require_passed_check "osv scanner" "osv-scan"
  • akroasis, epistole, hammasecurity.yml job named osv-scanner
  • kanonsecurity.yml job named osv scanner (the one that matched)

The file's own header asserted the premise this contradicts: "Required-check names are
fleet-invariant because security.yml + gate-attestation.yml are canonical."
Measured across the four
repos carrying it, they are not — two spellings, split 3–1, hyphen in the majority.

Reported by @t0-thumos as #38 while sweeping the exit 0 auto-merge-guard class.

Why this matters

It fails closed, so nothing merged that should not have. The cost is the migration path: the
repos still carrying a local copy of this workflow are exactly the ones whose local copy has the
exit 0 defect, and this was the blocker stopping them from replacing it with the fixed shared one.

Adding osv-scanner as a third literal would fix the instance and leave the class. An invariance
asserted in a comment and enforced nowhere has already drifted once; the matcher is what should
tolerate it.

Desired correction

Strip every non-alphanumeric from both the reported check name and the token, then test containment.
osv scanner, osv-scanner, and osv scanner / osv-scan all normalise to something containing
osvscan, so the whole spelling class matches without enumerating it.

A second defect fixed alongside, because looser matching would otherwise have made it worse. The
old code took [0] of the matching checks, so when a token selected more than one, the verdict
depended on the order GitHub returned them — a superseded run could answer for a live one. Every
matching check must now pass. For a guard whose failure mode is auto-merging, that is the only
defensible direction.

Verified by running the matcher against a fixture of the real check names from all four repos:

token matches
osvscan osv scanner, osv-scanner, osv scanner / osv-scan — all three
cargodeny cargo deny
cargoaudit cargo audit
gateattestation gate-attestation
gategate gate / gate

Unrelated checks stay clear: PII Scan normalises to piiscan, which contains scan but not
osvscan. Both refusal paths were exercised too — a red OSV check and a wholly absent check each
set failed=1.

Done when: a repo naming its OSV job osv-scanner can adopt this workflow and have its dependabot
PRs auto-merge on green.

Closes #38

…e all of them

Three repos name their OSV job osv-scanner, which endswith() matched against
neither accepted literal, so they could not adopt this workflow at all -- it
would refuse every dependabot PR whose OSV check had reported and passed. The
header asserted required-check names are fleet-invariant; measured across the
four repos carrying it, they are not, two spellings split 3-1.

Adding a third literal would fix the instance and leave the class, so both
sides are now stripped to alphanumerics and tested for containment.

A second defect had to go with it: the old code took [0] of the matching
checks, so a token selecting more than one made the verdict depend on the
order GitHub returned them, and a superseded run could answer for a live one.
Looser matching would have made that worse. Every matching check must now
pass, which for a guard whose failure mode is auto-merging is the only
defensible direction.

Verified against a fixture of the real check names from all four repos: the
osv token matches all three spellings, every other token matches exactly its
own check, PII Scan stays clear, and both refusal paths (a red check, an
absent check) set failed=1.
@forkwright
forkwright merged commit 922899f into main Aug 15, 2026
1 check passed
@forkwright
forkwright deleted the fix/normalise-required-check-match branch August 15, 2026 16:47
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.

ci: the reusable auto-merge cannot match an "osv-scanner" check, so three repos cannot adopt it

1 participant