bug(gates): enumerate the required contexts that have never actually run #1475
Labels
No labels
bump
major
bump
minor
bump
patch
kind
bug
kind
chore
kind
docs
kind
epic
kind
feature
loop/paused
mirror-drift
priority
critical
priority
high
priority
low
priority
medium
size
L
size
M
size
S
size
XL
status
blocked
No milestone
No project
No assignees
3 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
frankenbit/release-toolkit#1475
Loading…
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?
A required status context whose job carries an
if:that never matches reports skipped-as-success on every PR, so it is in the required set and has never graded anything. We found one by accident; nobody knows how many there are.go-ci / record reviewed vs landed commit (pull_request)is in main's required set. Its job isif: github.event_name == 'push', so on every pull request it is skipped, and a skipped Forgejo job postsstatus=successwithdescription="Has been skipped". It has never run on a PR, and it was hiding a job that hung for its full 20-minute timeout on most merges (#1469).25 workflows carry an
if:. The required set is currently 25 contexts.An earlier probe of mine used a push head, which is the wrong surface for a
(pull_request)context question — that read is could-not-grade, not zero.Acceptance criteria
description, sincestatusissuccesseither wayRelated
crew-doctrine#198carries the statuses-endpoint half: a skipped job and a passing job are indistinguishable by every structural field on/commits/<sha>/statuses, and branch protection gates on.status.Anchor
Found by the operator noticing a CI job running over 12 minutes, 2026-09-08. Diagnosed by @bosun.
rt-bugfix-loop (implementer session): evaluated 2026-10-07 and not claimed. Two of the loop's stop rules apply, so this is left for Alex.
if:in.forgejo/workflows, and the re-ask AC means a new CI gate. The loop does not touch compose machinery.The read-only census (ACs 1 and 2: a named ran / never-ran / could-not-determine list) could be done on its own as groundwork, if wanted.
The census — ACs 1 and 2, read off six real PR heads
The required set is five contexts, not 25. The body says "The required set is currently 25
contexts";
GET /branch_protectionsonmainreturns five, withenable_status_check=trueandrequired_approvals=1:Named list, as AC2 asks — not a count
RAN — 5 of 5, on every head sampled. Six merged PRs spanning 2026-10-06 to 2026-10-13, each
graded on its own PR head (never a push head, per the body's own correction):
0e7f37d59048da0176da73a6e830e947c9a5e6d5f87c0d37go-ci / lint + build + testpr / gatestests / batstests / checkstoolkit-self-gates / …NEVER-RAN — none. COULD-NOT-DETERMINE — none.
*
pr / gatesis auses:caller (.forgejo/workflows/pr.yml:29→reusable-pr-gates.yml), soSuccessful in 0sis the caller's own duration; the work runs inthe called workflow's inner job, which #1550 measured at 199s cold and 10-19s warm. It ran.
🔑 Three classes, not two — and duration alone misclassifies one of them
The body names
descriptionas the discriminator becausestatusissuccesseither way. Thatis right, and the census found a third shape the ran/never-ran split does not cover:
A reader who reaches for duration instead of
descriptionreads the third as the first. Worthcarrying into whatever satisfies AC4.
Positive control, per head — the zero is measured, not an instrument failure
An all-ran result on an absence question needs the needle proved present.
"Has been skipped"occurs 11 to 25 times on every head sampled, so the discriminator fires on this corpus and
the zero among required contexts is a real zero.
The named instance is remediated — by removal, not by repair
go-ci / record reviewed vs landed commit (pull_request)is still skipped-as-success onevery head. It is no longer in the required set, so it grades nothing and gates nothing. That
is AC3's second branch taken; recording the reason here, since nothing else did: its job is
if: github.event_name == 'push', so it cannot run on a pull request, and a context that cannotrun on the surface it is required for has no repair short of changing what it triggers on.
Eleven contexts are skipped-as-success, and none of them are required
Latest row per context on
c9a5e6d5:The seven
pr / *rows are the split-layout jobs, skipped becausepr.ymlrunslayout: combinedon a one-slot runner — the shape #1550's comments describe. They are harmlesswhile unrequired, and they are exactly what this issue warns against requiring: each would be
green-forever.
What is left
AC4 only: something has to re-ask. Today's answer is a hand-run census, and a required
context that stops running next month produces the same silent green. The census is cheap enough
to automate — five contexts, one API read per PR head,
descriptionas the discriminator — andnow that the required set is five rather than 25, the shape of that check is clear.
Method
GET /branch_protectionsfor the required set;GET /commits/<sha>/statusespaginated to anempty page (3 to 5 pages per head, 100-156 rows), newest row per context by
created_at. Read2026-10-19 08:50 against
origin/mainf87c0d3.