CI-9: correct the guard comment's grading claim, and name the third blind spot
checks / unit (pull_request) Successful in 7m54s
checks / unit (pull_request) Successful in 7m54s
Documentation only - no change to the guard, the trigger, or any step. The guard's comment block contradicted itself. It said the pull request that reintroduces a filter "is still graded by the unfiltered workflow which is on the base today", while the checkout step's note a few lines below says grading uses the HEAD's workflow. The head's is correct, and the review measured it on PR #101: head carrying a filter that excludes the base, base carrying the unfiltered workflow -> no run, context posted `skipped`, rollup `success`, gate cleared (409). The wrong version made the step sound like an unconditional ratchet. What is actually true is narrower: it bites whenever the reintroduced filter still names the pull request's own base, which is the ordinary case. That correction exposes a third blind spot, worse than the two already listed. A reintroduced `branches:` filter that simply does not name the base escapes the guard entirely, because the pull request carrying it is itself skipped. It needs no craft - `branches: [main]` from a template, or a tidy-up to `[master]`, which nothing in this repository's history has ever targeted - and it lands as a skipped, laundered, untested merge into release/1.0. After that every subsequent pull request is skipped as well: the gate off completely, not merely the stacked case leaking. It is documented, not fixed, and deliberately so. No in-repo guard can close it, because any such guard lives inside the workflow that gets skipped. Closing it needs a second permanently unfiltered workflow whose context is added to release/1.0's `status_check_contexts` - a forge change, the owner's decision, being put to them separately, and explicitly not a blocker on CI-9. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BwRLw7eKYj2byVdwB6kbjU
This commit is contained in:
@@ -341,10 +341,26 @@ jobs:
|
|||||||
# that detects its own workflow having been skipped) as impossible. That
|
# that detects its own workflow having been skipped) as impossible. That
|
||||||
# option is impossible because a skipped workflow runs no steps, so there
|
# option is impossible because a skipped workflow runs no steps, so there
|
||||||
# is nothing alive to notice. This is the different, tractable case: it
|
# is nothing alive to notice. This is the different, tractable case: it
|
||||||
# fires on the pull request that REINTRODUCES a filter, and that pull
|
# fires on the pull request that REINTRODUCES a filter, and it does so
|
||||||
# request is still graded by the unfiltered workflow which is on the base
|
# whenever the filter being reintroduced STILL NAMES THAT PULL REQUEST'S
|
||||||
# today. The edit has to get past this step before it can start causing
|
# OWN BASE - the ordinary case, because a filter put back by hand names
|
||||||
# skips. It is a ratchet, not a skip detector.
|
# the release branch people are actually targeting. The edit then has to
|
||||||
|
# get past this step before it can start causing skips. It is a ratchet,
|
||||||
|
# not a skip detector.
|
||||||
|
#
|
||||||
|
# ⚠️ AND IT IS THE HEAD'S WORKFLOW THAT DECIDES WHETHER ANYTHING RUNS, NOT
|
||||||
|
# THE BASE'S. An earlier draft of this comment claimed the reintroducing
|
||||||
|
# pull request "is still graded by the unfiltered workflow which is on the
|
||||||
|
# base today". That was wrong, it contradicted the checkout step's own note
|
||||||
|
# a few lines below, and the error was not cosmetic: it made this step
|
||||||
|
# sound like an unconditional ratchet, which is exactly the false comfort
|
||||||
|
# CI-9 exists to stamp out. MEASURED on PR #101 - head carrying a filter
|
||||||
|
# that excludes the base, base carrying the unfiltered workflow - and the
|
||||||
|
# result was no run at all, the context posted `skipped`, the rollup
|
||||||
|
# reading `success`, and the gate CLEARED (409). Gitea takes the workflow
|
||||||
|
# file from refs/pull/<n>/head, so a head that filters itself out is simply
|
||||||
|
# never graded, and nothing on the base can reach out and stop it. That is
|
||||||
|
# what blind spot 3 below is made of.
|
||||||
#
|
#
|
||||||
# WHAT IT INSPECTS is the MERGED tree in $WS - the content that would
|
# WHAT IT INSPECTS is the MERGED tree in $WS - the content that would
|
||||||
# actually land on the base - not the branch tip and not the copy of this
|
# actually land on the base - not the branch tip and not the copy of this
|
||||||
@@ -352,18 +368,44 @@ jobs:
|
|||||||
# trees here (see the long note on the checkout step) and only the merged
|
# trees here (see the long note on the checkout step) and only the merged
|
||||||
# one is the thing being authorised.
|
# one is the thing being authorised.
|
||||||
#
|
#
|
||||||
# ⚠️ TWO ACKNOWLEDGED BLIND SPOTS, both needing a branch-protection change
|
# ⚠️ THREE ACKNOWLEDGED BLIND SPOTS. NOT ONE OF THEM IS CLOSEABLE FROM
|
||||||
# to close, which is the repository owner's call and not this file's:
|
# INSIDE THIS FILE, and the reason is the same in all three: each is a case
|
||||||
|
# where THIS WORKFLOW IS ITSELF THE THING THAT GETS SKIPPED, and a guard
|
||||||
|
# that lives inside a skipped workflow does not run. Closing them needs a
|
||||||
|
# SECOND, permanently unfiltered workflow whose own context is added to
|
||||||
|
# release/1.0's `status_check_contexts`, so that something survives to
|
||||||
|
# report when this file is sat out. That is a forge change and the
|
||||||
|
# repository owner's decision; it is being put to them separately and is
|
||||||
|
# deliberately NOT held as a blocker on CI-9.
|
||||||
#
|
#
|
||||||
# 1. A reintroduced `paths:` filter crafted to exclude the reintroducing
|
# 1. A reintroduced `paths:` filter crafted to exclude the reintroducing
|
||||||
# pull request's OWN diff would skip that pull request, so this step
|
# pull request's OWN diff would skip that pull request, so this step
|
||||||
# would not run to object to it.
|
# would not run to object to it.
|
||||||
|
#
|
||||||
# 2. An edit that lands on a feature branch through a stacked pull
|
# 2. An edit that lands on a feature branch through a stacked pull
|
||||||
# request is graded by the HEAD's workflow, so a filter already
|
# request is graded by the HEAD's workflow, so a filter already
|
||||||
# present in the head hides the edit from this step - until that
|
# present in the head hides the edit from this step - until that
|
||||||
# branch is proposed for release/1.0, where the base matches the
|
# branch is proposed for release/1.0, where (unless it is case 3) the
|
||||||
# reintroduced filter and this step runs and bites. Caught at the
|
# base matches the reintroduced filter and this step runs and bites.
|
||||||
# release boundary, which is the boundary that matters.
|
# Caught at the release boundary, which is the boundary that matters.
|
||||||
|
#
|
||||||
|
# 3. ⚠️ THE WORST OF THE THREE, AND WORSE THAN BOTH OF THE OTHERS PUT
|
||||||
|
# TOGETHER: a reintroduced `branches:` filter that simply DOES NOT
|
||||||
|
# NAME THE BASE escapes this step entirely, because the pull request
|
||||||
|
# carrying it is itself skipped. It takes no craft and no malice to
|
||||||
|
# write - `branches: [main]` copied out of a GitHub template, or a
|
||||||
|
# tidy-up to `[master]`, a branch that NO pull request in this
|
||||||
|
# repository's history has ever targeted - and it arrives as a
|
||||||
|
# skipped, laundered, untested merge into release/1.0.
|
||||||
|
#
|
||||||
|
# What makes it categorically worse is what happens the moment after.
|
||||||
|
# Once that file is ON release/1.0, every subsequent pull request is
|
||||||
|
# graded against it and every one of them is skipped too. This is not
|
||||||
|
# the stacked case leaking through a crack; it is the gate off
|
||||||
|
# completely, for everything, silently, with every badge green. The
|
||||||
|
# only thing standing between the repository and that state today is
|
||||||
|
# a human reading this file - which is precisely the kind of defence
|
||||||
|
# this step exists because it has already failed once (9c1a23328a).
|
||||||
#
|
#
|
||||||
# It is deliberately a FAILURE and not a warning: a warning would leave
|
# It is deliberately a FAILURE and not a warning: a warning would leave
|
||||||
# the required context green, which is the precise defect CI-9 is about.
|
# the required context green, which is the precise defect CI-9 is about.
|
||||||
|
|||||||
Reference in New Issue
Block a user