Repository navigation
brain-ci: Merge Gate can never fail, and a failed detect-build passes as 'not applicable' #883
Description
Part of #851 (W15: gates that fail or pass for a reason other than their claim).
Two holes in brain-ci.yml, both next to the one #881 fixes. 🔒 Merge Gate can never fail, and the report prints a false "not applicable" when detect-build fails.
1. 🔒 Merge Gate cannot fail
merge-gate:
needs: [brain-health-report]
if: github.event_name == 'pull_request'
steps:
- run: |
if [ "${{ needs.brain-health-report.result }}" != "success" ]; then
... exit 1The job's if: has no status function, so GitHub adds success(). That is false as soon as any job upstream of it failed or was cancelled, including jobs it reaches only through the report's needs; the control run below shows this. So the gate runs only when the report and every brain job succeeded. Its one test, "the report did not succeed", is never true when it runs. When anything fails, the gate is skipped, which GitHub shows in grey, not red.
Measured on 3 pull_request runs where the report failed. In all 3 the Merge Gate is skipped:
| run | report | merge gate |
|---|---|---|
| 37020038238 | failure | skipped |
| 36842740058 | failure | skipped |
| 35513831395 | failure | skipped |
main has no branch protection (GET branches/main/protection returns 404), so no check is required for merge. The gate's only effect is what a reviewer sees on the PR, and on a damaged PR that is a grey "skipped".
2. A failed detect-build makes the report say "no root build.zig"
detect-build writes present=true|false from a shell test. Every brain job runs only if present == 'true'. The report then does:
if [ "${{ needs.detect-build.outputs.present }}" != "true" ]; then
echo "### ⏭️ Brain CI skipped — no root build.zig ... Non-blocking."
exit 0
fiIf detect-build itself fails (checkout error, its 2-minute timeout, a broken step), the step that writes present never runs. The output is empty, and [ "" != "true" ] sends the report down the "not applicable" branch. The report check goes green and says there is no root build.zig. main does have one (57de4a1).
Correction. I first wrote that this turns the whole brain CI green, Merge Gate included. The control run shows otherwise. detect-build's own check is red, so the run is red, and the Merge Gate is skipped for the reason in section 1. What is false is the report: a green check whose summary gives a wrong reason. This is smaller than I first claimed.
Not measured: whether detect-build has ever failed on a real run.
Fix
- In the report, before the
presenttest, requireneeds.detect-build.result == 'success'. Otherwise print the result it had and exit 1. - Give
merge-gatean explicitif: ${{ !cancelled() && github.event_name == 'pull_request' }}. It then runs after a failed report, and its existing test fails it. After a cancel it does not run (see brain-ci: a cancelled run posts a false "CRITICAL: Brain Health Below Threshold" #881).
Done when
- Control: dispatch run 37240659458 on
exp/gate-defect-ab, which ismainplus a forcedexit 1indetect-build, with merge-gate'spull_requestfilter removed and its implicitsuccess()kept. The report succeeded:if [ "" != "true" ]→ "Brain CI skipped — no root build.zig … Non-blocking" →exit 0. Merge Gate wasskipped(0 steps), and the run concludedfailure. - Fix plus the same forced failure: dispatch run 37240661475 on
exp/gate-fix-ab, with the filter dropped so the dispatch can exercise the gate. The report failed:[ "failure" == "success" ]→ "cannot tell whether it applies: detect-build was failure" →exit 1. Merge Gate ran and failed:[ "failure" != "success" ]→ "Merge gate blocked" →exit 1. - On the fix PR's own run, with nothing forced, the report and the Merge Gate both succeed:
pull_requestrun 37240875213 on ci(brain): let the merge gate fail, and fail on a failed detect-build #884,📋 Brain Health Reportsuccess and🔒 Merge Gatesuccess ([ "success" != "success" ]false → "Merge gate passed"). The PR's three other reds (doc-refs,orphan-artefacts×2) are gft_mul: the product wire is 32 bits and GF-T32 needs 52 #510's gft references, which fix(gates): green doc-refs and orphan-artefacts on main after #510 #872 fixes. - The diff merges cleanly with ci(brain): skip the health report when the run itself was cancelled #882, ci(brain): stop calling tri stress --record, and let the weekly stress step fail #880, ci: give the 102 push workflows a dispatch-safe concurrency group #870, ci: run nine workflows once per PR commit, on every path their push run watched #876, ci: run the nine document gates on push to main only #867 and fix(gates): green doc-refs and orphan-artefacts on main after #510 #872 (
git merge-tree, rc 0 each).
Not in this issue
- Whether
🔒 Merge Gateshould exist at all, given that the report already fails. That is the owner's call. This issue makes it truthful and does not remove it.
🤖 Generated with Claude Code
Activity
ci(brain): let the merge gate fail, and fail on a failed detect-build
style(brain): name the bool the detect-build verdict tests
ci(brain): let the merge gate fail, and fail on a failed detect-build
style(brain): name the bool the detect-build verdict tests
test(brain): force detect-build to fail on main (throwaway, #883)
ci(brain): let the merge gate fail, and fail on a failed detect-build
test(brain): force detect-build to fail on the fix (throwaway, #883)