bug(ci): build-ref-check asks for a runner label that does not exist, so it has never run #1361

Closed
opened 2026-09-06 17:46:52 +02:00 by bosun · 1 comment
Owner

build-ref-check.yml asks for a runner label that does not exist, so it has never run once. The operator noticed the warning on the Actions page.

Measured

.forgejo/workflows/build-ref-check.yml:28   runs-on: docker

forgejo-runner declared labels:
  dotnet  godot  python  go  playwright  squadron-test  docker-build  squadron-deploy
                                                        ^^^^^^^^^^^^ not "docker"

No runner offers docker. It is the only workflow in the repo using that label; every other Go job uses go, and the two non-Go ones use playwright and docker-build.

tags on origin              118
matching runs in the last 50  0

It triggers on push: tags: v*, so it should have fired on every cut since it was added. Nothing can claim the job, so it queues and the Actions page shows a warning — the only surface where this is visible.

The fix is one word

The job's own step is go build -o "$RUNNER_TEMP/rt" ./cmd/rt. It needs the Go image. runs-on: go maps to git.frankenbit.de/frankenbit/forgejo-ci-go:latest, which is what every other Go job in this repo uses.

docker-build is the near neighbour and is wrong — it is :host and exists for image builds.

What it means that this went unnoticed

This workflow exists to catch a tree tagged without being baked for its tag. Its own header records why that matters: "the release being bad and nobody knowing for fourteen months — which is what happened to v1.0.0-alpha.0."

And its positive-control step carries this comment:

A gate whose green is usually vacuous is indistinguishable from a gate that never ran (/srv/CLAUDE.md § "A GATE'S SILENCE"), and every correctly-baked tag passes this verb — so assert it still REFUSES the case it was built for before trusting anything it says.

The author anticipated the exact failure mode, wrote a positive control against it, and the control has never executed. ¶34 on a workflow that cites ¶34.

The reason a never-run workflow is invisible here is that it produces no status on any PR — it runs on tag push, so its silence appears on no surface a reviewer reads. #1348 is the same shape for mirror-drift-check, which at least reddens its own run.

AC

  • build-ref-check.yml names a label a registered runner offers — go, which maps to forgejo-ci-go:latest and is what every other Go job here uses.
  • The .gitea twin matches. rt gitea-twin --check rc=0. Only one file carried the label; the twin is generated and was regenerated clean.
  • It is confirmed to actually RUN, and its positive control refuses v1.0.0-alpha.0. Run 23972: status=success — the first run this workflow has ever produced. The job's success DEPENDS on the control: the step exits 1 unless v1.0.0-alpha.0 grades exactly 1. Verified independently rather than inferred:\n\n\nrt build-ref-check --ref v1.0.0-alpha.0 rc=1 marker holds \"main\", want \"v1.0.0-alpha.0\"\nrt build-ref-check --ref v0.61.1 rc=0 9/9 canonical files carry v0.61.1\n\n\n⚠️ Caveat: this was a workflow_dispatch, not a tag push. The push: tags: v* path is unchanged by this fix and has not fired since. The observable @engineer named still applies to that path — a run APPEARING, not a waiting job being claimed.
  • Whether other workflows name unclaimable labels is checked. Swept every runs-on: in .forgejo/workflows and .gitea/workflows against the runner's eight declared labels: before = 1 unclaimable (docker), after = 0.

#1348 (a gate's red reaching nobody), #1214 (what this workflow grades), ¶34

Anchor

Noticed by the operator on the Actions page — the only surface it appears on. Measured by @bosun against the runner's declared labels.

`build-ref-check.yml` asks for a runner label that does not exist, so it has never run once. The operator noticed the warning on the Actions page. ## Measured ``` .forgejo/workflows/build-ref-check.yml:28 runs-on: docker forgejo-runner declared labels: dotnet godot python go playwright squadron-test docker-build squadron-deploy ^^^^^^^^^^^^ not "docker" ``` No runner offers `docker`. It is the only workflow in the repo using that label; every other Go job uses `go`, and the two non-Go ones use `playwright` and `docker-build`. ``` tags on origin 118 matching runs in the last 50 0 ``` It triggers on `push: tags: v*`, so it should have fired on every cut since it was added. Nothing can claim the job, so it queues and the Actions page shows a warning — the only surface where this is visible. ## The fix is one word The job's own step is `go build -o "$RUNNER_TEMP/rt" ./cmd/rt`. It needs the Go image. `runs-on: go` maps to `git.frankenbit.de/frankenbit/forgejo-ci-go:latest`, which is what every other Go job in this repo uses. `docker-build` is the near neighbour and is wrong — it is `:host` and exists for image builds. ## What it means that this went unnoticed This workflow exists to catch a tree tagged without being baked for its tag. Its own header records why that matters: *"the release being bad and nobody knowing for fourteen months — which is what happened to v1.0.0-alpha.0."* And its positive-control step carries this comment: > *A gate whose green is usually vacuous is indistinguishable from a gate that never ran (/srv/CLAUDE.md § "A GATE'S SILENCE"), and every correctly-baked tag passes this verb — so assert it still REFUSES the case it was built for before trusting anything it says.* The author anticipated the exact failure mode, wrote a positive control against it, and the control has never executed. `¶34` on a workflow that cites `¶34`. The reason a never-run workflow is invisible here is that it produces no status on any PR — it runs on tag push, so its silence appears on no surface a reviewer reads. `#1348` is the same shape for `mirror-drift-check`, which at least reddens its own run. ## AC - [x] `build-ref-check.yml` names a label a registered runner offers — `go`, which maps to `forgejo-ci-go:latest` and is what every other Go job here uses. - [x] The `.gitea` twin matches. **`rt gitea-twin --check` rc=0.** Only one file carried the label; the twin is generated and was regenerated clean. - [x] It is confirmed to actually RUN, and its positive control refuses `v1.0.0-alpha.0`. **Run 23972: `status=success`** — the first run this workflow has ever produced. The job's success DEPENDS on the control: the step exits 1 unless `v1.0.0-alpha.0` grades exactly 1. Verified independently rather than inferred:\n\n```\nrt build-ref-check --ref v1.0.0-alpha.0 rc=1 marker holds \"main\", want \"v1.0.0-alpha.0\"\nrt build-ref-check --ref v0.61.1 rc=0 9/9 canonical files carry v0.61.1\n```\n\n⚠️ **Caveat: this was a `workflow_dispatch`, not a tag push.** The `push: tags: v*` path is unchanged by this fix and has not fired since. The observable @engineer named still applies to that path — a run APPEARING, not a waiting job being claimed. - [x] Whether other workflows name unclaimable labels is checked. **Swept every `runs-on:` in `.forgejo/workflows` and `.gitea/workflows` against the runner's eight declared labels: before = 1 unclaimable (`docker`), after = 0.** ## Related `#1348` (a gate's red reaching nobody), `#1214` (what this workflow grades), `¶34` ## Anchor Noticed by the operator on the Actions page — the only surface it appears on. Measured by @bosun against the runner's declared labels.
bosun self-assigned this 2026-09-06 17:46:52 +02:00
Author
Owner

Closing. The workflow has now produced its first run, and the positive control has fired.

build-ref-check.yml also carries a workflow_dispatch with a ref input — the same escape that let #1348 prove its never-executed reporting steps. Dispatched against v0.61.1 after runs-on: go landed:

run 23972   status=success       <- the first run this workflow has ever produced

The job's success is not incidental: its positive-control step exits 1 unless v1.0.0-alpha.0 grades exactly rc=1. Verified independently rather than inferred from the green:

rt build-ref-check --ref v1.0.0-alpha.0   rc=1   marker holds "main", want "v1.0.0-alpha.0"
rt build-ref-check --ref v0.61.1          rc=0   9/9 canonical files carry v0.61.1

So the verb discriminates in both directions, and the gate whose green would otherwise be vacuous has a control that demonstrably refuses.

Caveat kept rather than dropped: this was a dispatch, not a tag push. The push: tags: v* trigger is unchanged and has not fired since the fix. @engineer's note still governs that path — the observable is a run APPEARING, not a waiting job being claimed, because there was never a waiting job to claim.

The operator found this as a warning on the Actions page, which was the only surface it appeared on. It ran on tag push, produced no status on any PR, and its silence therefore showed up nowhere a reviewer reads.

Its own positive-control comment cites /srv/CLAUDE.md § "A GATE'S SILENCE" — a gate whose green is usually vacuous is indistinguishable from a gate that never ran. The author anticipated the exact failure mode, wrote a control against it, and the control had never executed. It has now.

Closing. The workflow has now produced its first run, and the positive control has fired. `build-ref-check.yml` also carries a `workflow_dispatch` with a `ref` input — the same escape that let `#1348` prove its never-executed reporting steps. Dispatched against `v0.61.1` after `runs-on: go` landed: ``` run 23972 status=success <- the first run this workflow has ever produced ``` The job's success is not incidental: its positive-control step exits 1 unless `v1.0.0-alpha.0` grades exactly `rc=1`. Verified independently rather than inferred from the green: ``` rt build-ref-check --ref v1.0.0-alpha.0 rc=1 marker holds "main", want "v1.0.0-alpha.0" rt build-ref-check --ref v0.61.1 rc=0 9/9 canonical files carry v0.61.1 ``` So the verb discriminates in both directions, and the gate whose green would otherwise be vacuous has a control that demonstrably refuses. Caveat kept rather than dropped: this was a dispatch, not a tag push. The `push: tags: v*` trigger is unchanged and has not fired since the fix. @engineer's note still governs that path — the observable is a run APPEARING, not a waiting job being claimed, because there was never a waiting job to claim. The operator found this as a warning on the Actions page, which was the only surface it appeared on. It ran on tag push, produced no status on any PR, and its silence therefore showed up nowhere a reviewer reads. Its own positive-control comment cites `/srv/CLAUDE.md` § "A GATE'S SILENCE" — *a gate whose green is usually vacuous is indistinguishable from a gate that never ran*. The author anticipated the exact failure mode, wrote a control against it, and the control had never executed. It has now.
bosun closed this issue 2026-09-06 18:13:12 +02:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
frankenbit/release-toolkit#1361
No description provided.