The tool watcher has never opened a PR and cannot — report instead (#376) - #377
Conversation
…nstead (#376) Dispatching it after #374 is how this surfaced. The push is rejected: ! [remote rejected] bot/actionlint-1.7.12 (refusing to allow a GitHub App to create or update workflow .github/workflows/ci.yml without `workflows` permission) GITHUB_TOKEN may not push changes to a workflow file, and no `permissions:` key grants it — GitHub's reference lists every key and there is no `workflows` among them; that scope exists only for a PAT or GitHub App. Seven of the nine pins live in .github/workflows/**. `gh pr list --state all` confirms it: not one bot/* PR has ever existed. Every Monday since July the run went green on having found nothing to do, which from the outside is indistinguishable from a watcher that works. So it reports now, into one tracking issue, like pithead's. The PR flow was a better design — the new tool runs its own check on its own PR — but it has never once actually happened, and buying it back means a long-lived token that can rewrite this repo's CI. That is a poor trade for a repo whose posture is SHA-pinned actions and least-privilege tokens. xmrig-bump.yml keeps its PR flow: XMRig lives in rigforge.sh, so that push is not blocked, and a build-verified bump is worth having for the one pin that ships to a rig. Its push path is nonetheless untested for the same reason — that pin has been current every week too. Unreachable is not current: a failed lookup or an unparseable tag is counted, named in the report as "not checked", and fails the run. The last fully successful check date is carried forward on a failed run, so a watcher that has stopped looks different from one with nothing to say. Net -22 lines.
ponytail-review on my own diff: check()'s four branches and kcov's three each wrote the '| a | b | c | d |' format themselves — seven places for the columns to drift apart. One row() helper, one append per path. Re-extracted the edited run block verbatim and re-drove it: byte-identical table, both failure paths still counted.
…nsion zizmor rejected my own workflow on this PR — template-injection, an expression expanded straight into a run block becomes code rather than data. I had used the env form in the sibling pithead workflow and did not carry it here. Worth noting which zizmor caught it: 1.25.2, the stale pin this whole thread is about. It is doing its job at four minors behind; the argument for bumping it is that we do not know what the other four minors would catch.
zizmor rejected my own workflow, and it was right
Two things worth recording from that:
|
Closes #376.
Dispatching #374 is how this was found, and it is the bigger defect
The very first stale pin the run reached:
GITHUB_TOKENmay not push changes to a workflow file, and nopermissions:key grants it.GitHub's workflow-syntax reference lists every available key —
actions,checks,contents,pull-requests, … — and there is noworkflows. That scope exists only for a PAT or GitHub Apptoken. Seven of the nine pins live under
.github/workflows/**.It has never opened a single PR:
Every Monday since July the run went green — on having found nothing to do. From the outside that
is indistinguishable from a watcher that works. This program's signature defect, in the watcher
itself.
What this does
Reports into one tracking issue instead, the same mechanism pithead adopted in
PR #1143. Works for every pin wherever
it lives, needs no new credential, net −22 lines.
xmrig-bump.ymlis untouched and keeps its PR flow: XMRig lives inrigforge.sh, so that push isnot blocked, and a build-verified bump is worth having for the one pin that ships to a rig.
The trade, stated plainly
The PR flow was the better design — a shellcheck bump linted by the new shellcheck is real
verification that a table in an issue cannot give you. I am not pretending otherwise. But it has
never once actually happened, and buying it back means storing a long-lived token that can rewrite
this repo's CI, in a repo whose entire supply-chain posture is SHA-pinned actions and
least-privilege tokens. If that trade is ever worth making, it is a deliberate decision with a
credential-rotation story, not a side effect of fixing a watcher.
What was run
The report logic, driven against the real tree (the
check()function copied verbatim from therun block):
All nine pins, four stale, matching the audit in #373 exactly.
Both failure paths, driven over stubs — unreachable must not read as current:
ponytail-review on my own diff then found the table row format written in seven places —
four branches of
check()and three in the kcov block — which is seven places for the columns todrift apart. Collapsed to one
row()helper. The probe above was then regenerated by extractingthe edited run block verbatim and re-driven, rather than trusting that a refactor of the thing
under test left it alone: byte-identical table, both failure paths still counted.
make lint-actionsclean — worth noting that actionlint shellchecks inlinerun:blocks, whichis why the logic stays inline here rather than moving to a script that nothing in this repo's lint
list would cover.
yamllint --strictclean.What is NOT proven until this merges
The workflow cannot run with these changes until they are on
develop. I will dispatch itimmediately after merging and confirm the tracking issue appears — that step is exactly what found
the defect this PR fixes, and skipping it is how the original went unnoticed for two months.