* fix(release): rebuild + cryptographically verify the preview updater manifest
Since ~2026-07-13 every nightly matrix leg logs 'Signature not found for
the updater JSON. Skipping upload...' - tauri-action uploads the bundles
and .sig companions but never refreshes latest.json. Combined with the
'Clear this arch's stale preview updater bundle' step (which deletes and
replaces the version-less macOS tar.gz every night), the preview
manifest's darwin signatures no longer match the published files: macOS
Preview users hit 'The signature verification failed' on every update
(latest.json frozen at 2026-07-13, tar.gz replaced nightly).
Two changes, both in the single post-matrix preview-notes job (no
per-leg race):
1. Rebuild latest.json from the release's real assets and their .sig
companions, then clobber-upload. The manifest can no longer drift
from the files it describes, regardless of what tauri-action's own
updater-JSON path does or skips.
2. Extend the existing manifest verification with a cryptographic
check: every signature in latest.json must verify (minisign
file sig + trusted-comment sig) against the artifact it points at,
using the updater pubkey from tauri.conf.json. Parity and version
format both passed for 2+ weeks while every darwin entry was
unverifiable - this is the check that was missing.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* ci(release): refuse a preview manifest built from two different runs
Bot review findings on this branch, all fixed here:
- The AppImage and MSI were picked independently by highest run number and
the larger N became *the* version, so a matrix where one leg failed or
was re-run published a manifest advertising X.Y.Z-5 while handing Windows
users the -4 MSI. That is the same manifest/artifact drift this job
exists to end, reintroduced by the fix for it. Require both legs to come
from one run and fail loudly otherwise: leaving the previous manifest in
place is a visible, already-understood state; shipping a mismatched one
is not. The darwin tarballs carry no run number, so the signature check
in the following step is what pins those to the published bytes.
- persist-credentials: false on the checkout — nothing here pushes to git.
- Floor-pin the cryptography install; this step decides whether a signed
manifest is trustworthy, so it is the one dependency worth a bound.
tests/test_release_preview_manifest_rebuild.py runs the step body extracted
from release.yml against stubbed gh, so it cannot drift from the workflow.
Fails before / passes after on the mismatch case.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* docs(changelog): note the preview updater manifest fix (#1327)
Co-Authored-By: Pinkers01 <pinky.bouw@gmail.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* ci(release): verify the preview manifest before publishing it, not after
Two more review findings on this branch, both valid, both about the
manifest being wrong in a way the existing checks structurally cannot see.
greptile P1 — verification ran AFTER the clobber-upload. A manifest that
failed the check was already live and stayed served; the job merely went
red, and every macOS Preview user stayed broken until someone noticed.
Verification now runs against the file about to be published, and the
upload is the last thing in the step. A refusal leaves the previous
manifest in place, which is a visible, already-understood state.
CodeRabbit — the darwin entries were not tied to this run. The version
comes from the AppImage name; the macOS tarballs were only checked for
existence. Signature verification cannot help there, because a stale
tarball and its stale .sig match each other perfectly — so a run whose
macOS legs never uploaded would advertise this version while serving Mac
users the previous build, and since those clients keep reporting the old
version the updater would re-offer it forever. They are now bound by
upload time, with two minutes of slack for legs that finish apart.
The selection rules move out of the YAML heredoc into
scripts/build_preview_manifest.py. Three findings in a row have been about
WHICH artifacts may be described together, and a heredoc can only be
tested by extracting it and stubbing a shell — which is what the previous
test file did, asserting against gh stubs rather than against the rules.
build_manifest is pure: assets in, manifest out, ManifestRefused on
anything it will not describe.
14 tests, including both new refusals and two that pin the workflow still
calls the module and still uploads last — an inline copy would pass every
other test and ship the original bug.
Co-Authored-By: Pinkers01 <pinky.bouw@gmail.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Pinkers01 <pinky.bouw@gmail.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>