Repository navigation
Description
🤖 Generated by the Agentic Engineer
Evidence
validateProductionRoutes checks that each merge-queue production job invokes the checked deploy
action, but it never checks the publication-contract validator step itself on that route.
On the merge-queue path (.github/workflows/ci.yaml):
deploy-proddeclaresneeds: [changes, validate-eks-authorization]- the DR-signing validator (
go run ./scripts/validate-dr-signing …) runs as a step inside the
changesjob, not in a dedicated gate job validateProductionRoutescontains no reference tovalidatorCommand,requireEnforcedStepon
that step, orrunBlockIsSimpleSequence
So the changes job can succeed with the validator neutered, and deploy-prod proceeds.
The direct-push route in cd.yaml is protected against exactly this by validateDRWorkflow: the
validator step there must execute the command, must be neither skipped nor failure-suppressed, must be
a straight-line sequence, and (as of #2939) must carry no shell override at any scope. None of that
applies to the ci.yaml occurrence.
Why it matters
The contract's own premise is that the guarantee is only as strong as its weakest route, and the
merge-queue route is the normal path to production — direct-push is the exception. Every bypass
already pinned for cd.yaml is reachable here: echo-ing the command, set +e, continue-on-error,
if: false, a here-doc, or defaults.run.shell: bash {0} plus a trailing true.
Not exploitable by an outside contributor — it needs a workflow edit — so this is defence-in-depth of a
gate that already exists, not a live exposure.
Expected behaviour
The ci.yaml validator step is held to the same enforcement rules as the cd.yaml one, and
deploy-prod is proven to depend on the job that carries it.
Acceptance criteria
validateProductionRoutes(or a peer) locates the validator step on the merge-queue route by the
samevalidatorCommandequality used forcd.yaml, and fails when it is absent.- That step is required to be enforced — not skipped, not
continue-on-error, straight-line, and no
shell override at workflow / job / step scope. deploy-prodis required toneedsthe job that actually carries the validator, so moving the step
to an unrequired job fails the check.- One ablation per rule, each failing a disjoint test, each build-checked.
- The shipped
ci.yamlpasses unchanged.
Size
Small–medium. The rules exist; this reuses requireEnforcedStep / refuseShellOverride /
runBlockIsSimpleSequence against a second route rather than writing new logic.
Found while fixing a CodeRabbit P1 on #2939; deliberately kept out of that PR to keep it one concern.
Metadata
Metadata
Assignees
Labels
Type
Fields
Projects
- StatusShow more project fields✅ Done
Activity
coderabbitai commentedon Aug 4, 2026
🔗 Related PRs
#2330 - ci: heal prod when a merge-group deploy fails (restore main) [merged]
#2622 - fix(ci): heal cancelled merge-group deploys [merged]
#2753 - fix(aws): allow EKS version discovery [merged]
#2825 - fix(ci): queue prod deploys instead of dropping the pending one [merged]
#2930 - feat(ci): verify published evidence before promoting the prod digest [merged]
📝 Issue Planner
Check the box below or use the
@coderabbitai plancommand to generate an implementation plan and prompts that you can use with your favorite coding assistant.🧪 Issue enrichment is currently in open beta.
You can configure auto-planning by selecting labels in the issue_enrichment configuration.
To disable automatic issue enrichment, add the following to your
.coderabbit.yaml:💬 Have feedback or questions? Drop into our discord!
fix(ci): enforce the publication-contract gate on the merge-queue route