Skip to content

Commit 8d1718b

Browse files
ci(release): sign desktop bundles + publish the updater manifest
Pass the minisign signing key to the bundle build so each updatable artifact gets a .sig, then merge the per-platform slices into a single latest.json and attach it to the release — the static endpoint the updater polls. Asset URLs account for GitHub rewriting spaces in the AppImage name to dots.
1 parent 883ed7b commit 8d1718b

1 file changed

Lines changed: 75 additions & 0 deletions

File tree

.github/workflows/release.yml

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,11 @@ jobs:
378378
SIGN: ${{ secrets.GPG_PRIVATE_KEY != '' && '1' || '' }}
379379
SIGN_KEY: ${{ secrets.GPG_KEY_ID }}
380380
APPIMAGETOOL_SIGN_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
381+
# minisign key for the auto-updater — makes `tauri build` emit a `.sig`
382+
# next to each updatable artifact (AppImage / NSIS). Distinct from the
383+
# GPG key above, which signs the AppImage file for manual verification.
384+
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
385+
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
381386
run: |
382387
# Inject the real product version (module.prop is the single source of
383388
# truth) so the bundles aren't the 0.0.0 placeholder.
@@ -442,3 +447,73 @@ jobs:
442447
with:
443448
tag_name: ${{ needs.prepare.outputs.version }}
444449
files: dist/*
450+
451+
# Per-platform slice of the updater manifest: the `.sig` content + the asset
452+
# URL. The `updater-manifest` job merges every platform's slice into one
453+
# latest.json (the updater endpoint must list all platforms in a single file).
454+
- name: Build updater manifest fragment
455+
shell: bash
456+
run: |
457+
case "${{ matrix.target }}" in
458+
*linux*) plat=linux-x86_64; sig=$(find dist -maxdepth 1 -name '*.AppImage.sig' | head -1) ;;
459+
*windows*) plat=windows-x86_64; sig=$(find dist -maxdepth 1 -name '*-setup.exe.sig' | head -1) ;;
460+
*) plat=""; sig="" ;;
461+
esac
462+
if [ -z "${sig:-}" ]; then
463+
echo "no updater signature for ${{ matrix.target }} (signing key unset?) — skipping"
464+
exit 0
465+
fi
466+
# GitHub rewrites spaces in uploaded asset names to dots — match that so
467+
# the URL resolves (the AppImage carries the "Kasumi Proxy" product name).
468+
asset=$(basename "${sig%.sig}" | tr ' ' '.')
469+
tag="${{ needs.prepare.outputs.version }}"
470+
url="https://github.com/loss-and-quick/Kasumi-Proxy/releases/download/${tag}/${asset}"
471+
mkdir -p frag
472+
jq -n --arg p "$plat" --arg s "$(cat "$sig")" --arg u "$url" \
473+
'{($p): {signature: $s, url: $u}}' > "frag/${plat}.json"
474+
cat "frag/${plat}.json"
475+
476+
- name: Upload updater manifest fragment
477+
if: hashFiles('frag/*.json') != ''
478+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
479+
with:
480+
name: updater-frag-${{ matrix.target }}
481+
path: frag/*.json
482+
retention-days: 1
483+
484+
# ── Merge the per-platform updater slices into a single latest.json and attach
485+
# it to the release — this is the static endpoint the desktop updater polls. ──
486+
updater-manifest:
487+
needs: [prepare, desktop]
488+
if: needs.prepare.outputs.skip != 'true'
489+
runs-on: ubuntu-latest
490+
steps:
491+
- name: Download manifest fragments
492+
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
493+
with:
494+
pattern: updater-frag-*
495+
path: frag
496+
merge-multiple: true
497+
498+
- name: Assemble latest.json
499+
shell: bash
500+
run: |
501+
if ! compgen -G "frag/*.json" >/dev/null; then
502+
echo "no updater fragments — skipping latest.json"
503+
exit 0
504+
fi
505+
tag="${{ needs.prepare.outputs.version }}"
506+
platforms=$(jq -s 'add' frag/*.json)
507+
jq -n \
508+
--arg version "${tag#v}" \
509+
--arg pub "$(date -u +%FT%TZ)" \
510+
--argjson platforms "$platforms" \
511+
'{version: $version, pub_date: $pub, platforms: $platforms}' > latest.json
512+
cat latest.json
513+
514+
- name: Upload latest.json to the release
515+
if: hashFiles('latest.json') != ''
516+
uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2
517+
with:
518+
tag_name: ${{ needs.prepare.outputs.version }}
519+
files: latest.json

0 commit comments

Comments
 (0)