From e2efcb6570d860718360e1571f0a0d662dafd825 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 27 Jul 2026 13:47:31 +0000 Subject: [PATCH] =?UTF-8?q?fix(ci):=20dogfood=20gate=20passes=20cancelled?= =?UTF-8?q?=20runs=20through=20=E2=80=94=20a=20cancelled=20matrix=20is=20n?= =?UTF-8?q?ot=20a=20failed=20one?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #3668. With cancel-in-progress on, every consecutive push cancelled the in-flight dogfood matrix (the longest job in the workflow) and the gate's catch-all branch turned that into a red X on the superseded SHA — two observed on #3660 alone. False reds train everyone to ignore the one check that must never be ignored. Safety premise verified experimentally before landing (per the issue's own ask): run 30271824408 executed a fail-fast matrix where shard 1 really failed and fail-fast cancelled shard 2 mid-run — the aggregate needs..result reads 'failure', not 'cancelled'. Failure dominates, so an aggregate of 'cancelled' can only come from the whole run being stopped externally (supersession or manual cancel) and passing it masks no real regression. The manual-cancel case going green is the issue's accepted trade-off; the rejected alternative (skipping the gate via !cancelled()) would republish the #3622 required-context deadlock. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01ECTCrcCdZpCHw5zFSgcmGt --- .changeset/dogfood-gate-cancelled-not-failure.md | 4 ++++ .github/workflows/ci.yml | 15 ++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 .changeset/dogfood-gate-cancelled-not-failure.md diff --git a/.changeset/dogfood-gate-cancelled-not-failure.md b/.changeset/dogfood-gate-cancelled-not-failure.md new file mode 100644 index 0000000000..5cc4c58a51 --- /dev/null +++ b/.changeset/dogfood-gate-cancelled-not-failure.md @@ -0,0 +1,4 @@ +--- +--- + +CI-only: the Dogfood Regression Gate no longer reports a superseded (cancelled) run as a failure — `cancelled` joins the pass branch, backed by a fail-fast experiment showing a real shard failure always aggregates as `failure`. Releases nothing. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6019a739a6..4102eaf029 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -286,8 +286,21 @@ jobs: run: | result="${{ needs.dogfood.result }}" echo "dogfood matrix aggregate result: $result" + # cancelled is a run-lifecycle state, not a shard verdict (#3668): + # with cancel-in-progress on, every superseded push cancelled the + # in-flight dogfood matrix — the longest job, so almost always the + # one still running — and the old `*)` fallthrough painted a false + # red on the old SHA. Verified experimentally (run 30271824408, a + # fail-fast matrix with one real failure + one cancelled sibling): + # a real shard failure DOMINATES the aggregate — it reads "failure", + # never "cancelled" — so "cancelled" here can only mean the whole + # run was stopped from outside (supersession, or a manual cancel — + # accepted trade-off), and passing it masks no regression. + # Deliberately NOT `if: !cancelled()` on the job instead: a skipped + # gate publishes no required-check context on the SHA, which is the + # #3622 merge-deadlock all over again. case "$result" in - success|skipped) echo "Dogfood gate satisfied." ;; + success|skipped|cancelled) echo "Dogfood gate satisfied ($result)." ;; *) echo "::error::Dogfood shards did not pass (aggregate result: $result)"; exit 1 ;; esac