From 76a2d9609ba72b8a198d5aa8121c7f0cb2cf9b55 Mon Sep 17 00:00:00 2001 From: Duncan Tourolle Date: Fri, 21 Aug 2026 23:14:16 +0200 Subject: [PATCH] fix(release): produce updater artifacts, and point the manifest at them Two defects on the release path, both of which would have failed the v0.10.0 build after all three platforms had already compiled -- caught by running a real signed build locally instead of waiting for the tag. **createUpdaterArtifacts was never set.** Without it Tauri emits only the plain .AppImage and .exe: no signatures at all. The manifest step then finds none and aborts by design, so the release dies at Create Release having spent ~40 minutes building artifacts it cannot publish. **The manifest looked for the wrong filename.** Tauri v2 signs the .AppImage *itself* and writes .AppImage.sig beside it. The .AppImage.tar.gz form this workflow globbed for only exists under createUpdaterArtifacts: "v1Compatible". A real signed build produced: 154M JellyTau_0.10.0_amd64.AppImage 420 JellyTau_0.10.0_amd64.AppImage.sig so the glob would have matched nothing and the step would have aborted for a second, entirely different reason. Both the artifact collection and the manifest now use the v2 names, and the AppImage and its .sig ship together -- a manifest referencing a signature that was never uploaded fails only on the user's machine. Verified before tagging rather than after: the manifest logic was run against the real artifacts (420-char minisign signature read correctly) and the resulting latest.json checked for validity and shape. The Windows side already used the correct pattern (.exe.sig), which is why only Linux needed the change. --- .gitea/workflows/build-release.yml | 18 +++++++++++++----- src-tauri/tauri.conf.json | 1 + 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/.gitea/workflows/build-release.yml b/.gitea/workflows/build-release.yml index 8c24fe92..624118d1 100644 --- a/.gitea/workflows/build-release.yml +++ b/.gitea/workflows/build-release.yml @@ -190,12 +190,15 @@ jobs: # Without nullglob an unmatched pattern stays literal, so test each # candidate instead. Same POSIX-only rule as traceability-check.yml. # - # The .AppImage.tar.gz + .sig pair is what the updater downloads and - # verifies; the plain .AppImage is what a human downloads. Both ship. + # Tauri v2 signs the .AppImage ITSELF and writes .AppImage.sig + # beside it -- there is no .AppImage.tar.gz unless + # bundle.createUpdaterArtifacts is set to "v1Compatible". The updater + # downloads the same AppImage a human does and verifies that .sig, so + # both files must ship or the manifest points at a signature nobody + # can fetch. for bundle in \ src-tauri/target/release/bundle/appimage/*.AppImage \ - src-tauri/target/release/bundle/appimage/*.AppImage.tar.gz \ - src-tauri/target/release/bundle/appimage/*.AppImage.tar.gz.sig \ + src-tauri/target/release/bundle/appimage/*.AppImage.sig \ src-tauri/target/release/bundle/deb/*.deb \ src-tauri/target/release/bundle/rpm/*.rpm; do [ -e "$bundle" ] || continue @@ -499,8 +502,13 @@ jobs: APPIMAGE_URL="" NSIS_URL="" - for f in artifacts/linux/*.AppImage.tar.gz; do + # Tauri v2 signs the AppImage itself; .AppImage.sig sits beside + # it. Verified against a real signed build before tagging -- the + # v1-style .AppImage.tar.gz is never produced with + # createUpdaterArtifacts: true. + for f in artifacts/linux/*.AppImage; do [ -e "$f" ] || continue + case "$f" in *.sig) continue;; esac APPIMAGE_URL="${BASE}/$(basename "$f")" [ -e "$f.sig" ] && APPIMAGE_SIG="$(cat "$f.sig")" done diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 4104ae08..73982d7e 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -44,6 +44,7 @@ }, "bundle": { "active": true, + "createUpdaterArtifacts": true, "targets": [ "deb", "rpm",