Every pin in the repo, checked against upstream: the ones with a watcher were
current, and five of the six without one had gone stale.
zizmor 1.25.2 -> 1.29.0 four minors
pre-commit-hooks v5.0.0 -> v6.0.0 a major
actionlint 1.7.7 -> 1.7.12
diff-cover 10.3.0 -> 10.5.1
jq 1.7.1 -> 1.8.2
lychee 0.24.2 current, by luck rather than process
zizmor is the one that matters: it audits these very workflows and it gates the
merge, so four minors behind means auditing our own supply chain with a scanner
missing four releases of rules. security.yml pins two tools; gitleaks was
watched and current, zizmor was neither.
Five join tool-bump.yml in its existing idiom. pre-commit-hooks goes to
Dependabot, which supports that ecosystem natively — better than hand-rolling a
`rev:` rewriter, and it gives the gitleaks `rev:` a second opinion alongside the
lockstep sed already here.
The work is the normalisation, not the fetch. lychee tags `lychee-v0.24.2` and
jq tags `jq-1.8.2`; newer_release strips only a leading `v` and then validates
the shape, so adding either as-is returns 2, sets failed=1, and turns the run
red every week on a repo whose pins are fine. Hence a per-tool prefix argument,
defaulted so every existing caller is byte-identical, with the strict validation
still running after the strip — normalising the spelling must not mean trusting
the value.
Closes #373.
The audit, as a natural experiment
Every pin the repo carries, checked against upstream today:
Watched — all current: XMRig (
xmrig-bump.yml), shellcheck, shfmt, gitleaks, kcov(
tool-bump.yml), GitHub Actions (dependabot).Unwatched — five of six stale:
1.25.2v1.29.0v5.0.0v6.0.01.7.7v1.7.1210.3.0v10.5.11.7.1jq-1.8.20.24.2lychee-v0.24.2Watched → current. Unwatched → stale. Nothing about these was harder to watch than the five that
already were; they were never added.
zizmor is the one that matters. It audits these workflows, it queries the GitHub Advisory
Database so a CVE against a pinned action fails the gate, and it blocks the merge. Four minors
behind means we have been auditing our own supply chain with a scanner missing four releases of
rules, with no signal anywhere that this was so.
security.ymlpins two tools — gitleaks waswatched and current, zizmor was neither.
What this does
Five join
tool-bump.ymlin its existing idiom —newer_release+open_pr, one PR per stale pin,the dispatched checks on the branch as the verification.
pre-commit-hooksgoes to dependabotinstead, which supports that ecosystem natively; that beats hand-rolling a
rev:rewriter and givesthe gitleaks
rev:a second opinion alongside the lockstepsedalready here.XMRig stays with
xmrig-bump.yml, unchanged. It is the only pin shipped to a rig, it is current, andit is current because that watcher exists — which is the argument for this PR rather than against
it.
The trap, and why the diff is not just five copy-pasted blocks
newer_releasedoeslatest="${latest#v}"and then validates^[0-9]+(\.[0-9]+)*$, returning 2on a mismatch, which the callers turn into
failed=1.lychee-v0.24.2jq-1.8.2Adding either as-is makes the shape check fail every week, on a repo whose pins are fine. So
newer_releasetakes a per-tool tag prefix, defaulted tovso every existing caller isbyte-identical — and the strict validation still runs after the strip. Normalising the spelling
must not mean trusting the value.
What was run
The comparison logic, driven against real upstream, using the exact
cur=extraction expressioneach new branch uses:
Every
curextracted correctly, both prefixes resolved, and the three existing callers areunchanged.
Mutation — drop the prefix argument (i.e. today's behaviour):
So the new argument is load-bearing, not decoration.
Every
sedapplied to the real file — all eight rewrites land and produce the expected string(a
sedthat silently matches nothing would open a no-op bump PR):The artifact URLs the bumps would fetch all resolve (so
artifact_shahas something tochecksum):
actionlint_1.7.12_linux_amd64.tar.gz200,jq-linux-amd64200,lychee-x86_64-unknown-linux-gnu.tar.gz200.make lint-actionsclean.yamllint --strictclean on both changed files.What was NOT run
develop. Dispatch it after merge and confirm the PRs it opens — I would rather that be adeliberate step than a discovery next Monday.
make testwas not run: no shell that the suite covers changed. The diff is two YAML files.backlog, not a bug; each dedups on its own branch afterwards.
Not a defect in what exists
I went looking.
tool-bump.yml's failure accounting is correct: a failedgh apileaves an emptytag, the shape check rejects it,
newer_releasereturns 2, andelse [ $? -gt 1 ] && failed=1records it — an unreachable upstream cannot read as "pin is current".
xmrig-bump.ymlvalidates thetag before it reaches a ref and re-checks the tag→commit mapping against the build. Both are good
designs; this was only ever about coverage.
Sibling work: pithead #1128 /
PR #1143 closed the same gap there —
one shape, two outputs: a build-verified PR here where the tool gates its own bump, a report-only
tracking issue there where a component bump is a data migration.