hooks/tests: release-gate.test.sh still scores a crashed gate as "allow" - and the audit scope is an open question #417
Labels
No labels
breaking
bug
documentation
enhancement
epic
good first issue
help wanted
refactoring
resolution/duplicate
resolution/invalid
resolution/wontfix
security
severity/critical
severity/high
severity/low
severity/medium
status/abandoned
status/blocked
status/needs-decision
status/needs-info
status/needs-verification
testing
upstream
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
sixfold-space/madtea#417
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Follow-up to #366. The harness hardening there covered the eight suites that invoke the guard as
bash "$HOOK".hooks/tests/release-gate.test.shhas the identical defect and was missed, because it names its subject$GATErather than$HOOKand so fell outside the grep that produced the file list.hooks/tests/release-gate.test.sh:112-118:Same three problems #366 describes: stderr discarded, exit status never inspected, and scoring that treats absent output as a permissive result. Demonstrated against a gate stub that exits 9: eight expect-ALLOW cases still report PASS, because a gate that never ran looks exactly like a gate that allowed.
This one guards the release gate specifically, so the blind spot sits on the path that decides whether a release may proceed.
Open question - how wide should the sweep be
Not settled, and worth deciding before the work starts rather than after:
release-gate.test.shalone, mirroring thelib-hook-harness.shtreatment.hooks/tests/for the general shape: any subprocess-under-test invoked with2>/dev/nulland no exit-status check, scored by absence. This does not assume$HOOKand$GATEare the only two spellings. It is the option that answers "what else did the grep miss", which is the actual lesson of this follow-up: the file list came from a pattern that matched a naming convention, not from the defect.My recommendation is (2), because the miss here was caused by scoping on a name rather than on the behaviour, and repeating that method would likely repeat the miss. The cost is a wider diff across suites that are currently green.
Acceptance criteria
alloworblock.Sticking with the body's lean: option (2), the behavioral audit across
hooks/tests/. Any subprocess-under-test run with2>/dev/nulland no exit-status check, scored by absence, is in scope, not just the two known spellings ($HOOKand$GATE). The miss here came from scoping on a name, so repeating that method would repeat the miss. The cost is a wider diff, but it preserves the green suites.Open question before the work starts: whether the wider diff is worth it now, or whether
release-gate.test.shgets the point fix first and the audit follows as its own change. My lean is the full audit in one pass, because splitting it leaves the same "what else did the grep miss" gap open in between.Real-world reproductions of this defect, in CI.
Two occurrences this session: the cold
pull_requestgateruns for the #429 merge (680d199) and the #456 merge (f09a263d) both failed onover-threshold-stalewithexpected deny (score 16 >= 10, no grace), got allow. Both passed the gate on theirpushruns of the identical SHA, and both pass the full gate locally. Neither commit touches scripts/release-gate.sh. So the gate did not wrongly allow - it produced no"deny"output on those cold runs (a transient failure under CI load, the same load class as #410), and the test scored that absence as allow. The run history shows the samegate-job failure recurring across many older SHAs too.This is exactly the defect:
run_gaterunsbash "$GATE" ... 2>/dev/nullwith stderr discarded and the exit status never inspected, andis_denytreats the absence of a"deny"string as a pass. A gate that crashed or produced nothing is indistinguishable from a gate that allowed, so a transient gate failure surfaces as a falseover-threshold-stale/prs-merge-denyfailure and red-lights an unrelated PR.The point fix is ready in shape (capture the gate exit status and stderr; report a non-zero exit or empty output as an error naming the cause; require positive evidence the gate ran for the expect-allow cases - the lib-hook-harness.sh treatment from #366). I am still holding on the open question above - point-fix this file, or the behavioral audit across all of hooks/tests/ in one pass. My lean stays the full audit, but these occurrences argue for landing at least the point fix soon, because it is now causing red CI on unrelated merges.
Decision: the full behavioral audit across all of hooks/tests/ (option 2), not the point fix alone. Building it now.