ci: fix latest.json generation in release workflow#23
Conversation
Rewrites the release workflow to eliminate three classes of bug that corrupted v0.6.2 and v0.6.3's updater manifests: 1. `v__VERSION__` template leakage into mac/linux URLs — tauri-action's `includeUpdaterJson` is now disabled and `tagName` receives the real tag, so the action no longer emits its own (racing) latest.json. 2. `untagged-<id>` slug in the Windows MSI URL — `create-release` now uses `gh release create` and asserts the release reports the correct tagName before any platform job starts uploading. 3. Parallel-write race on latest.json — the merge step is now a single authoritative composer (runs after all platform jobs) that reads .sig files, builds URLs from OWNER/REPO/TAG/ASSET, and emits the full 9-entry platforms map in one atomic jq invocation. Adds a jq-based integrity assertion in the composer that fails the workflow if any URL contains `__VERSION__` or `/releases/download/ untagged-`, any signature is empty, or the platform key set drifts from the expected 9. Catches future regressions of the same class before a broken manifest ships. Dry-run of the new composer against v0.6.4's released .sig files produced a platforms map identical to the hand-fixed latest.json currently on the v0.6.4 draft. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Reviewed on behalf of @chriso83 — sharing the analysis here so the reasoning is visible on the PR. On the "draft release" concernWorth calling out up front: this PR does not introduce draft-release behavior. The release has always been created as a draft, and it still is after this change.
Both produce a draft. The switch to Why the draft is intentionalThe draft is a staging area:
Nothing in the workflow (before or after this PR) auto-publishes, so the draft → published flip stays manual. That's the safety gate you want — a chance to review the bundle before it's live to the Tauri updater. Review of the actual fixesThe three fixes line up cleanly with the three bugs described:
The integrity gate in One thing worth emphasizingThe byte-identical dry-run against v0.6.4's TL;DRNo new drafting behavior. The PR fixes genuine updater-manifest bugs from v0.6.2 / v0.6.3 and adds assertions to prevent regressions. LGTM to merge, then validate on an rc before the next real release. |
Release candidate tag to validate the release-workflow fix landed in PR #23 before cutting v0.6.5. Marks as a GitHub pre-release so the generated `latest.json` can be inspected without being served to users on the auto-updater path. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Release candidate tag to validate the release-workflow fix landed in PR #23 before cutting v0.6.5. Marks as a GitHub pre-release so the generated `latest.json` can be inspected without being served to users on the auto-updater path. Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Tauri's MSI bundler errors on non-numeric pre-release identifiers: ``` failed to bundle project `optional pre-release identifier in app version must be numeric-only and cannot be greater than 65535 for msi target` ``` This blocks v0.6.5-rc.1 (and any `-rc.N` / `-beta.N` / `-alpha.N` tag) from producing the Windows MSI, which in turn skips compose-latest-json (it needs: build-windows), leaving the release workflow fix from PR #23 unvalidated. The constraint is Windows-specific (MSI inherits the 4-part numeric PE resource version). Fix by computing a numeric-only `wix.version` from tauri.conf.json at build time — strip everything after `-` so `0.6.5-rc.1` becomes `0.6.5` for MSI metadata only. The app's embedded semver (what the updater compares, what `env!("CARGO_PKG_VERSION")` returns) stays untouched, so pre-release tags still behave as pre-releases everywhere except the Windows installer's Add/Remove Programs display. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Tauri's MSI bundler errors on non-numeric pre-release identifiers: ``` failed to bundle project `optional pre-release identifier in app version must be numeric-only and cannot be greater than 65535 for msi target` ``` This blocks v0.6.5-rc.1 (and any `-rc.N` / `-beta.N` / `-alpha.N` tag) from producing the Windows MSI, which in turn skips compose-latest-json (it needs: build-windows), leaving the release workflow fix from PR #23 unvalidated. The constraint is Windows-specific (MSI inherits the 4-part numeric PE resource version). Fix by computing a numeric-only `wix.version` from tauri.conf.json at build time — strip everything after `-` so `0.6.5-rc.1` becomes `0.6.5` for MSI metadata only. The app's embedded semver (what the updater compares, what `env!("CARGO_PKG_VERSION")` returns) stays untouched, so pre-release tags still behave as pre-releases everywhere except the Windows installer's Add/Remove Programs display. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Tauri's MSI bundler errors on non-numeric pre-release identifiers: ``` failed to bundle project `optional pre-release identifier in app version must be numeric-only and cannot be greater than 65535 for msi target` ``` This blocks v0.6.5-rc.1 (and any `-rc.N` / `-beta.N` / `-alpha.N` tag) from producing the Windows MSI, which in turn skips compose-latest-json (it needs: build-windows), leaving the release workflow fix from PR #23 unvalidated. The constraint is Windows-specific (MSI inherits the 4-part numeric PE resource version). Fix by computing a numeric-only `wix.version` from tauri.conf.json at build time — strip everything after `-` so `0.6.5-rc.1` becomes `0.6.5` for MSI metadata only. The app's embedded semver (what the updater compares, what `env!("CARGO_PKG_VERSION")` returns) stays untouched, so pre-release tags still behave as pre-releases everywhere except the Windows installer's Add/Remove Programs display. Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Promotes v0.6.5-rc.1 (validated via the release-workflow fix in PR #23) to a full release. Draft release cut from this tag will ship via the auto-updater once published. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Promotes v0.6.5-rc.1 (validated via the release-workflow fix in PR #23) to a full release. Draft release cut from this tag will ship via the auto-updater once published. Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
Rewrites the release workflow to eliminate three classes of bug that corrupted the updater manifests in recent releases:
v__VERSION__leaked into mac/linux URLs (v0.6.3) —tauri-actionwas emitting its ownlatest.jsonfrom 3 parallel matrix jobs, with the literal template as the tag name. Fix:includeUpdaterJson: falseontauri-action, real tag passed astagName,latest.jsoncomposed once in a final job.untagged-<id>slug in the Windows MSI URL (v0.6.3) — the release was created viagh api ...without the tag fully attached, and the Windows MSI upload (fastest platform) froze that placeholder into the manifest. Fix:create-releasenow usesgh release create --draftand assertsgh release view --json tagNamematches before any platform job starts.latest.json(v0.6.2 — Intel-mac cleanup step failed trying to delete an asset another job had already deleted). Fix: only one job (compose-latest-json,needs:all platforms) ever writeslatest.json.New safety net
compose-latest-jsonruns jq assertions before uploading the manifest — fails the workflow if any URL contains__VERSION__or/releases/download/untagged-, any signature is empty/null, or the platform key set drifts from the expected 9. Catches regressions before they ship.Dry-run
Ran the new composer locally against v0.6.4's already-uploaded
.sigfiles — the generated platforms map is byte-identical to the hand-fixedlatest.jsoncurrently on the v0.6.4 draft.Test plan
rctag (e.g.v0.6.5-rc.1) and confirm the full workflow runs greenlatest.json— all 9 platform URLs should be/releases/download/v0.6.5-rc.1/...(no__VERSION__, nountagged-*)compose-latest-jsonjob logs show the integrity assertion passingv0.6.5and shipNotes
tauri-actionstays at@v0— the problem wasn't the action version (we're already on the latestv0.6.2), it was how we were driving it.🤖 Generated with Claude Code