You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
release.yml runs the verifier under Zsh but never installs it, so publication always fails #496
ubuntu-latest has no Zsh, so the step exits 127 before any verification happens:
/home/runner/work/_temp/....sh: line 1: zsh: command not found
##[error]Process completed with exit code 127
Every other workflow in the repository that runs Zsh installs it first, for example promotion-readiness.yml:27 and zsh-n.yml:84 (sudo apt-get install -yq zsh). release.yml is the only one that does not.
How it surfaced
The workflow reached main only with #494, since #470 added it on next before v2.0.0 shipped. Pushing v2.0.1 was therefore its first ever execution, and it failed on that first run. The defect has been latent since #470.
Impact
Publication is blocked for every tag. The failure is also awkward to recover from: verify-release-tag.zsh requires the tag target to equal the current origin/main, so landing a fix moves main and invalidates any tag already pushed. That forces either a moved tag or a burned version number.
v2.0.1 was published manually to avoid moving a public tag. The verifier itself was run locally against the exact tag first and passed:
Release authorization verified for v2.0.1 at 86758198344052d60b25f454cd3b64269a8ef2ea.
so only the broken execution environment was bypassed, not the authorization logic.
Fix
Add a Zsh install step to the publish job before the verification step, matching the pattern the rest of the repository uses.
Worth considering separately
The tag-equals-main precondition makes a failed publication expensive to retry, because any fix to the release path invalidates the pending tag. Loosening it to "tag target is an ancestor of origin/main" would keep the intent, that a release comes from reviewed stable history, while allowing a retry after a workflow fix. Not addressed here.
The fix reaches main at the next promotion, so the release path stays broken on main until then. Tagging again before promoting would fail the same way.
The tag-equals-main precondition noted above is left open as a separate design decision and is not addressed by #497.
Closing here rather than on merge, since Closes only fires against the default branch and this landed on next.
Following up on the relaxation suggested above: not doing it. Recording why, so it is a decision rather than an omission.
The proposal was to change
[[ $target==$main ]] || fail "tag target is not the current origin/main"
to accept any ancestor of origin/main, so a failed publication could be retried after fixing the release path without moving a tag or burning a version.
release.yml publishes with --latest (line 51). Under the relaxed check, any commit reachable from main could be tagged and published as the newest release, including one predating a known fix. That converts a hard guarantee, a release is the current reviewed stable tip, into a convention that a mistake can silently violate, and the failure mode is user-visible: stale code presented as latest.
The retry difficulty that motivated the idea was a symptom of the publish job never installing Zsh, which is fixed in #497. With a working release path the precondition costs nothing, because the tag is created at the tip and published minutes later.
If retry ergonomics become a real problem, the safer shape is to keep the equality check and make recovery cheap another way, for example by allowing a re-run against an unchanged main. Weakening the ancestry requirement is the wrong lever.
Activity
ss-o commentedon Sep 3, 2026
Fixed by #497, merged to
next.The fix reaches
mainat the next promotion, so the release path stays broken onmainuntil then. Tagging again before promoting would fail the same way.The tag-equals-
mainprecondition noted above is left open as a separate design decision and is not addressed by #497.Closing here rather than on merge, since
Closesonly fires against the default branch and this landed onnext.ss-o commentedon Sep 3, 2026
Following up on the relaxation suggested above: not doing it. Recording why, so it is a decision rather than an omission.
The proposal was to change
to accept any ancestor of
origin/main, so a failed publication could be retried after fixing the release path without moving a tag or burning a version.release.ymlpublishes with--latest(line 51). Under the relaxed check, any commit reachable frommaincould be tagged and published as the newest release, including one predating a known fix. That converts a hard guarantee, a release is the current reviewed stable tip, into a convention that a mistake can silently violate, and the failure mode is user-visible: stale code presented as latest.The retry difficulty that motivated the idea was a symptom of the publish job never installing Zsh, which is fixed in #497. With a working release path the precondition costs nothing, because the tag is created at the tip and published minutes later.
If retry ergonomics become a real problem, the safer shape is to keep the equality check and make recovery cheap another way, for example by allowing a re-run against an unchanged
main. Weakening the ancestry requirement is the wrong lever.