From 043c2d95b9860f5f752848fcc4c55eb3119b5764 Mon Sep 17 00:00:00 2001 From: James Rich <2199651+jamesarich@users.noreply.github.com> Date: Sat, 3 Oct 2026 09:37:22 -0500 Subject: [PATCH] feat(desktop): embed AppImage update information and publish .zsync Release AppImages now carry `gh-releases-zsync` update information pointing at the latest release, and ship the matching `.zsync` so AppImageUpdate and AppImage managers can delta-update them. Snapshot and PR builds embed nothing. Fixes #7153 --- .github/workflows/release.yml | 4 ++++ scripts/build-appimage.sh | 34 +++++++++++++++++++++++++++------- 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 156f85abb35..cbda1a63133 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -322,6 +322,8 @@ jobs: if: runner.os == 'Linux' env: APP_VERSION_NAME: ${{ inputs.version_name }} + # GitHub's `latest` skips prereleases, so internal builds also update to the newest production release. + UPDATE_RELEASE_TAG: latest run: scripts/build-appimage.sh - name: List Desktop Binaries @@ -340,6 +342,7 @@ jobs: desktopApp/build/compose/binaries/main-release/*/*.deb desktopApp/build/compose/binaries/main-release/*/*.rpm desktopApp/build/compose/binaries/main-release/*/*.AppImage + desktopApp/build/compose/binaries/main-release/*/*.AppImage.zsync desktopApp/build/compose/jars/*-release.jar retention-days: 1 if-no-files-found: ignore @@ -355,6 +358,7 @@ jobs: desktopApp/build/compose/binaries/main-release/*/*.deb desktopApp/build/compose/binaries/main-release/*/*.rpm desktopApp/build/compose/binaries/main-release/*/*.AppImage + desktopApp/build/compose/binaries/main-release/*/*.AppImage.zsync desktopApp/build/compose/jars/*-release.jar create-flatpak-src: diff --git a/scripts/build-appimage.sh b/scripts/build-appimage.sh index 47d69b5daf1..726aa1f7561 100755 --- a/scripts/build-appimage.sh +++ b/scripts/build-appimage.sh @@ -7,8 +7,8 @@ # AppImage bundle format. This script builds the AppDir scaffolding (AppRun, # .desktop entry, icon) around that directory and packs it with appimagetool. # -# The output lands in main-release/appimage/ so the existing release upload -# and attestation globs (main-release/*/*.AppImage) pick it up unchanged. +# The .AppImage (and its .zsync when UPDATE_RELEASE_TAG is set) land in +# /appimage/, where the upload and attestation globs pick them up. # # Expects to run on a Linux host of the target architecture (x86_64/aarch64) # with APP_VERSION_NAME set (e.g. 2.8.0). appimagetool and the AppImage @@ -111,15 +111,35 @@ curl -fsSL --retry 5 --retry-delay 10 --connect-timeout 10 --max-time 300 -o "${ "https://github.com/AppImage/type2-runtime/releases/download/${RUNTIME_VERSION}/runtime-${ARCH}" echo "${RUNTIME_SHA256} ${tools_dir}/runtime" | sha256sum -c - -output="${out_dir}/${app_name// /_}-${VERSION}-${ARCH}.AppImage" +asset_prefix="${app_name// /_}" +output="${out_dir}/${asset_prefix}-${VERSION}-${ARCH}.AppImage" + +# UPDATE_RELEASE_TAG (e.g. `latest`) embeds AppImageUpdate information pointing at that +# release's .zsync. appimagetool's bundled zsyncmake writes the .zsync into the working +# directory, so pack from inside out_dir to keep it beside the .AppImage. +update_args=() +if [ -n "${UPDATE_RELEASE_TAG:-}" ]; then + repo="${GITHUB_REPOSITORY:-meshtastic/Meshtastic-Android}" + update_args=(-u "gh-releases-zsync|${repo%%/*}|${repo#*/}|${UPDATE_RELEASE_TAG}|${asset_prefix}-*-${ARCH}.AppImage.zsync") +fi + # APPIMAGE_EXTRACT_AND_RUN: run appimagetool itself without FUSE. # --runtime-file: embed the pinned runtime instead of downloading `continuous`. # --no-appstream: we ship no AppStream metadata, skip that validation. -ARCH="$ARCH" APPIMAGE_EXTRACT_AND_RUN=1 "${tools_dir}/appimagetool" \ - --no-appstream --runtime-file "${tools_dir}/runtime" \ - "$appdir" "$output" +( + cd "$out_dir" + ARCH="$ARCH" APPIMAGE_EXTRACT_AND_RUN=1 "${tools_dir}/appimagetool" \ + --no-appstream --runtime-file "${tools_dir}/runtime" \ + "${update_args[@]}" \ + "$(basename "$appdir")" "$(basename "$output")" +) + +if [ -n "${UPDATE_RELEASE_TAG:-}" ] && [ ! -f "${output}.zsync" ]; then + echo "::error::appimagetool did not write ${output}.zsync" >&2 + exit 1 +fi -# Drop the AppDir so only the .AppImage remains for upload/attestation globs. +# Drop the AppDir so only the packed outputs remain for upload/attestation globs. rm -rf "$appdir" echo "Built $(du -h "$output" | cut -f1) AppImage: ${output}"