The Linux release upload failed with a bare exitcode '1' and no output. The upload step was not the cause — compute-version handed it a version that had already been released three days earlier.
How the numbering broke
The patch number was the distance from the highest tag, not a counter:
LATEST_TAG=$(git tag -l "v${MAJOR_MINOR}.*" --sort=-v:refname | ... | head -1)PATCH=$(git rev-list --count "${LATEST_TAG}..HEAD")
That resets to zero every time a tag is cut, so it wanders. Every published version is reproduced exactly by the old formula:
baseline
commits since
published
v0.4.0
3
v0.4.3
v0.4.3
4
v0.4.4
v0.4.4
2
v0.4.2 (backwards)
v0.4.4
6
v0.4.6 (skipped .5)
v0.4.6
3
v0.4.3 (already taken)
The line published 0.4.0, 0.4.3, 0.4.4, 0.4.2, 0.4.6 in that order, never used 0.4.1 or 0.4.5, and then came back round to 0.4.3.
Why this was worse than a failed build
macOS and Windows delete-then-upload each asset, so they absorbed the duplicate and rewrote releases that had been public since Aug 11:
v0.4.3-mac created 2026-08-11T19:12 dmg replaced 2026-08-14T04:37
v0.4.3-win created 2026-08-11T19:15 exe/msi replaced 2026-08-14T04:40
v0.4.3 created 2026-08-11T19:15 untouched (the build that failed)
Linux failing was the correct outcome. Its assets are the only ones still original.
The fix
Patch is now one past the highest already used. Suffixed tags count toward that, because create-tag is skipped whenever a platform job fails — a run can publish v0.4.7-mac and never create the plain v0.4.7, and reading only unsuffixed tags would hand the same number out twice. A commit that is already tagged reuses its own tag, so re-running a build does not mint a version.
Linux also gets the idempotent get-or-create the other two platforms already had, plus set -euo pipefail and -fsS. Its curl -s without -f is precisely why the 409 produced no diagnostic: the HTTP error was swallowed, the id grep came back empty, and the step died without printing anything.
Effect
Next release from main is 0.4.7. 0.4.5 is not reachable without deleting the published v0.4.6, which has already been downloaded, and would be a version downgrade for anyone running it.
Still outstanding, not addressed here: the v0.4.3-mac and v0.4.3-win assets overwritten on Aug 14 are still wrong.
The Linux release upload failed with a bare `exitcode '1'` and no output. The upload step was not the cause — `compute-version` handed it a version that had already been released three days earlier.
### How the numbering broke
The patch number was the *distance* from the highest tag, not a counter:
```bash
LATEST_TAG=$(git tag -l "v${MAJOR_MINOR}.*" --sort=-v:refname | ... | head -1)
PATCH=$(git rev-list --count "${LATEST_TAG}..HEAD")
```
That resets to zero every time a tag is cut, so it wanders. Every published version is reproduced exactly by the old formula:
| baseline | commits since | published |
|---|---|---|
| v0.4.0 | 3 | v0.4.3 |
| v0.4.3 | 4 | v0.4.4 |
| v0.4.4 | 2 | **v0.4.2** (backwards) |
| v0.4.4 | 6 | **v0.4.6** (skipped .5) |
| v0.4.6 | 3 | **v0.4.3** (already taken) |
The line published 0.4.0, 0.4.3, 0.4.4, 0.4.2, 0.4.6 in that order, never used 0.4.1 or 0.4.5, and then came back round to 0.4.3.
### Why this was worse than a failed build
macOS and Windows delete-then-upload each asset, so they absorbed the duplicate and **rewrote releases that had been public since Aug 11**:
```
v0.4.3-mac created 2026-08-11T19:12 dmg replaced 2026-08-14T04:37
v0.4.3-win created 2026-08-11T19:15 exe/msi replaced 2026-08-14T04:40
v0.4.3 created 2026-08-11T19:15 untouched (the build that failed)
```
Linux failing was the correct outcome. Its assets are the only ones still original.
### The fix
Patch is now one past the highest already used. Suffixed tags count toward that, because `create-tag` is skipped whenever a platform job fails — a run can publish `v0.4.7-mac` and never create the plain `v0.4.7`, and reading only unsuffixed tags would hand the same number out twice. A commit that is already tagged reuses its own tag, so re-running a build does not mint a version.
Linux also gets the idempotent get-or-create the other two platforms already had, plus `set -euo pipefail` and `-fsS`. Its `curl -s` without `-f` is precisely why the 409 produced no diagnostic: the HTTP error was swallowed, the id grep came back empty, and the step died without printing anything.
### Effect
Next release from `main` is **0.4.7**. 0.4.5 is not reachable without deleting the published v0.4.6, which has already been downloaded, and would be a version downgrade for anyone running it.
Still outstanding, not addressed here: the v0.4.3-mac and v0.4.3-win assets overwritten on Aug 14 are still wrong.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
The Linux release upload failed with a bare "exitcode '1'" and no output.
The cause was not the upload: compute-version handed it a version that
had already been released three days earlier.
The patch number was `git rev-list --count <highest tag>..HEAD` — how far
HEAD has drifted from whichever tag sorts highest, which resets to zero
every time a tag is cut. It is not a counter, and the published history
is what the old formula returned at each point:
v0.4.0 -> 3 commits -> v0.4.3 looked fine
v0.4.3 -> 4 commits -> v0.4.4 fine by luck, 4 > 3
v0.4.4 -> 2 commits -> v0.4.2 went backwards
v0.4.4 -> 6 commits -> v0.4.6 jumped, skipping .5
v0.4.6 -> 3 commits -> v0.4.3 already taken
So the line published 0.4.0, 0.4.3, 0.4.4, 0.4.2, 0.4.6 in that order,
never used 0.4.1 or 0.4.5, and then came back round to 0.4.3.
The patch is now one past the highest already used. Suffixed tags count
towards that: create-tag is skipped whenever a platform job fails, so a
run can publish v0.4.7-mac and never create the plain v0.4.7, and reading
only unsuffixed tags would hand the same number out twice. A commit that
is already tagged reuses its own tag, so re-running a build does not mint
a version.
Reusing a number was doing real damage, not just failing. macOS and
Windows delete-then-upload each asset, so they took the duplicate in
their stride and rewrote v0.4.3-mac and v0.4.3-win — public since
Aug 11 — with today's binaries. Linux is the only platform that failed,
and failing was the correct outcome; its v0.4.3 assets are the only ones
still original.
Linux also gets the idempotent get-or-create the other two already had,
plus `set -euo pipefail` and `-fsS`. Its `curl -s` with no `-f` is why a
409 produced no diagnostic at all: the HTTP error was swallowed, the id
grep came back empty, and the step died without ever printing why.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
jknapp
merged commit 2b2d9da606 into main2026-08-14 06:00:50 +00:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
The Linux release upload failed with a bare
exitcode '1'and no output. The upload step was not the cause —compute-versionhanded it a version that had already been released three days earlier.How the numbering broke
The patch number was the distance from the highest tag, not a counter:
That resets to zero every time a tag is cut, so it wanders. Every published version is reproduced exactly by the old formula:
The line published 0.4.0, 0.4.3, 0.4.4, 0.4.2, 0.4.6 in that order, never used 0.4.1 or 0.4.5, and then came back round to 0.4.3.
Why this was worse than a failed build
macOS and Windows delete-then-upload each asset, so they absorbed the duplicate and rewrote releases that had been public since Aug 11:
Linux failing was the correct outcome. Its assets are the only ones still original.
The fix
Patch is now one past the highest already used. Suffixed tags count toward that, because
create-tagis skipped whenever a platform job fails — a run can publishv0.4.7-macand never create the plainv0.4.7, and reading only unsuffixed tags would hand the same number out twice. A commit that is already tagged reuses its own tag, so re-running a build does not mint a version.Linux also gets the idempotent get-or-create the other two platforms already had, plus
set -euo pipefailand-fsS. Itscurl -swithout-fis precisely why the 409 produced no diagnostic: the HTTP error was swallowed, the id grep came back empty, and the step died without printing anything.Effect
Next release from
mainis 0.4.7. 0.4.5 is not reachable without deleting the published v0.4.6, which has already been downloaded, and would be a version downgrade for anyone running it.Still outstanding, not addressed here: the v0.4.3-mac and v0.4.3-win assets overwritten on Aug 14 are still wrong.
🤖 Generated with Claude Code