fix(labels): wake the sweep over REST, so board events reconcile in seconds
`.github/workflows/labels.yml` dispatched the sweep with `gh workflow run`,
the eighth runtime gh call site the 0.6.0 merge reintroduced and the only one
!204 did not port. On this forge the runner carries neither gh nor a GitHub
API, so the step refused and the entire event-driven reconcile path ended
there — every transition waiting up to an hour for the scheduled sweep.
The workflow-dispatch endpoint has the SAME shape on both forges:
POST {api}/repos/{owner}/{repo}/actions/workflows/{file}/dispatches
{"ref": "<branch>", "inputs": {...}} -> 204, empty body
so the step no longer decides a forge at all. The CEREMONY_FORGE_CLIENT=gh
declaration and both inline refusals are removed rather than ported, and
test/no-runtime-gh.test.sh now asserts their ABSENCE — an opt-out with no gh
behind it is a standing permission slip.
The ref is supplied explicitly and taken from the repository, never from
GITHUB_REF_NAME: on a pull_request_target run that is `<n>/merge`, which is
not a branch. A non-204 still fails the job, keeping the misconfiguration
alarm the trigger exists to be, and the diagnostic explains Forgejo's empty
500 rather than passing a bare status to a reader who will go looking for an
outage that is not there.
test/labels-dispatch.test.sh extracts the shipped step and executes it against
a recording stub, asserting the method, endpoint, ref and inputs actually
sent. Dropping the inputs or ignoring a non-204 both red the suite.
Refs #205
2026-08-05 16:58:05 +00:00
|
|
|
### Fixed
|
|
|
|
|
|
|
|
|
|
- `.github/workflows/labels.yml` wakes the sweep over REST instead of
|
|
|
|
|
`gh workflow run`, so a board event reconciles within seconds on any forge
|
|
|
|
|
rather than waiting up to an hour for the scheduled sweep (#205).
|
|
|
|
|
|
|
|
|
|
- The workflow-dispatch endpoint has the same shape on both forges, so that
|
|
|
|
|
step no longer decides one: the `CEREMONY_FORGE_CLIENT=gh` declaration and
|
|
|
|
|
both inline refusals are gone rather than ported (#205).
|
|
|
|
|
|
|
|
|
|
- The dispatch supplies its `ref` explicitly, because REST has no default
|
|
|
|
|
branch where `gh workflow run` had one, and refuses without it (#205).
|
|
|
|
|
|
|
|
|
|
- It takes that ref from the repository, never from `GITHUB_REF_NAME` — on a
|
|
|
|
|
`pull_request_target` run that is `<n>/merge`, which is not a branch (#205).
|
|
|
|
|
|
|
|
|
|
- A failed dispatch names the endpoint, the ref and the status, and says that
|
|
|
|
|
an empty `500` body from Forgejo means the workflow name or the ref did not
|
|
|
|
|
resolve — a bare status sends the reader after a server fault that is not
|
|
|
|
|
there (#205).
|
|
|
|
|
|
|
|
|
|
### Added
|
|
|
|
|
|
|
|
|
|
- `test/labels-dispatch.test.sh` extracts the shipped step and executes it
|
|
|
|
|
against a recording stub, asserting the method, endpoint, ref and
|
|
|
|
|
`inputs.bootstrap` actually sent (#205).
|
|
|
|
|
|
|
|
|
|
- That test also drives the failure path: any non-204 still fails the job, so
|
|
|
|
|
the misconfiguration alarm the trigger exists to be cannot decay into a
|
|
|
|
|
warning (#205).
|
2026-08-05 17:16:30 +00:00
|
|
|
|
|
|
|
|
- An unset `GITHUB_API_URL` refuses before any request instead of defaulting
|
|
|
|
|
to `api.github.com`. Guessing sent this forge's dispatch to GitHub and
|
|
|
|
|
reported success — the "Never 'probably github'" rule, and the same
|
|
|
|
|
unset-environment refusal #201 established for docs-sync (#205).
|
|
|
|
|
|
|
|
|
|
- A dispatch that never reaches the forge names the failure. Letting `set -e`
|
|
|
|
|
carry curl's exit code out did fail the job, but with a bare status and no
|
|
|
|
|
sentence (#205).
|
|
|
|
|
|
|
|
|
|
- `docs/CONSUMERS.md` and both caller comments describe the REST dispatch, and
|
|
|
|
|
the manual bootstrap command carries a forge-neutral form beside the `gh`
|
|
|
|
|
one — a cross-forge runbook that directs this forge to a missing binary is
|
|
|
|
|
wrong even where the surrounding prose is right (#205).
|