ci: fail when a workflow pins a stale copy of an action - #87
Conversation
There was a problem hiding this comment.
🟡 Changes recommended
The README example omits the full-history checkout required by the script, which can cause false failures when followed.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
Adds a guard against stale self-pinned actions and documents how to repoint them.
Changes:
- Adds
script/bump-self-refswith reporting and--fixmodes. - Adds a push/manual workflow to detect stale references.
- Repoints ten workflow references and documents the maintenance process.
File summaries
| File | Description |
|---|---|
script/bump-self-refs |
Detects and updates stale action pins |
README.md |
Documents self-reference conventions |
.github/workflows/self-check-self-refs.yaml |
Runs the stale-pin check |
.github/workflows/generate-changelog.yaml |
Updates four action pins |
.github/workflows/check-pr-title.yaml |
Updates three action pins |
.github/workflows/check-commit-messages.yaml |
Updates three action pins |
.github/CONTRIBUTING.md |
Documents the bump procedure |
Review details
- Files reviewed: 7/7 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
🟡 Changes recommended
Fix mode can skip required rewrites, and pinning fork or PR HEAD commits is unsafe across squash merges.
Get a fresh assessment by requesting another Copilot review.
Review details
Suppressed comments (1)
Previously missed (1) — in code that hasn't changed since the last review.
script/bump-self-refs:103
- With
--fix, this branch is unreachable when every pin is considered current: thestale_count == 0path exits before the Perl rewrite. That contradicts the documented--fixbehavior (and the comment below) of repointing every self reference, so older pins for unchanged actions cannot be moved toHEAD. Gate this early exit onfix=falseso fix mode always reaches the rewrite.
- Files reviewed: 7/7 changed files
- Comments generated: 1
- Review effort level: Lite
|
Two findings, one taken and one declined. Both in 0be1986. The squash-merge point is right, and the fix is different from HEAD-validation. I first tried refusing to pin when HEAD is not on the default branch, and testing showed that blocks the legitimate case: the rebase this PR itself needs would be rejected, because after rebasing, HEAD is a branch commit by definition. So Verified from a branch whose own commit was Declined: gating the early exit on The real defect there was the wording, which promised more than the behaviour: the usage line said |
Workflows reference this repository's own actions by commit SHA, and those pins do not move when an action changes, so a workflow keeps running the previous copy of it. Passing a newly added input to such an action is reported as a warning rather than an error, so the run stays green while the new behaviour does nothing. actions/create-pr was already a commit behind, which meant the bundle rebuilt in #79 was not the one the changelog workflow ran. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A bump has to be its own pull request, because --fix can only pin to a commit that already exists. And the check cannot be a required status check, since it only reports after a merge. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Pins are resolved against local history, so a shallow checkout made every one of them report as an unknown commit, which reads as a problem with the references rather than with the checkout. The documented example now shows the checkout it needs, and says that the script covers this repository only. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
--fix resolved HEAD, so running it from a branch wrote a SHA that squash and rebase merges discard, leaving a reference to a commit that never lands. It now pins at the default branch tip and says so when that differs from HEAD. Also corrects the usage text, which claimed --fix repoints every reference unconditionally when it only does so once one has fallen behind. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
#78 changed the generate-changelog and setup-commitizen actions, which the workflows still pinned from before, so they would have kept running the previous copies. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
0be1986 to
d90e64c
Compare
Workflows here pin this repository's own actions by commit SHA, as a consuming repository does. Those pins do not move when an action changes, so a workflow keeps running the previous copy of the action beside it in the tree — and quietly: a newly added input handed to an action pinned from before it existed is a warning, not an error, so the run stays green while the new behaviour does nothing.
Already true on
main:actions/create-pris a commit behind, so the bundle rebuilt in #79 to clear the undici and brace-expansion advisories is not the one the changelog workflow runs.Behaviour changes
Check Self Referencesjob fails on every push tomainwhen a pin has fallen behind the action it points at. Also available viaworkflow_dispatch.script/bump-self-refsreports those pins;--fixrepoints them at the default branch tip.For the reviewer
It fails rather than opening a bump pull request. Doing that would need
BOT_APPROVED_FILESwidened to let a bot edit workflow files and the GitHub App grantedworkflows: write— worth deciding deliberately rather than folding in here.--fixis there if we revisit it.Do not make it a required status check. It only runs after a merge, so it never reports on a pull request and one gated on it would never be mergeable. The job name is deliberately not suffixed
:required.A bump belongs in its own pull request.
--fixpins at the default branch tip, so bundling it with a change to an action pins the commit before that change and the check fails again on merge.Merge last. It conflicts with #78 in
generate-changelog.yaml, and the bump has to be recomputed against whatevermainbecomes — a rebase plus another--fix.🤖 Generated with Claude Code