diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 863fe2526..0548a8fb3 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -210,7 +210,7 @@ jobs: sudo apt-get update sudo apt-get install -y --no-install-recommends \ libxkbcommon-dev libwayland-dev libx11-dev libxrandr-dev libxi-dev libgl1-mesa-dev \ - desktop-file-utils appstream python3-yaml + desktop-file-utils appstream python3-yaml zsync curl -fsSL -o "$RUNNER_TEMP/nfpm.deb" \ "https://github.com/goreleaser/nfpm/releases/download/v${NFPM_VERSION}/nfpm_${NFPM_VERSION}_${{ matrix.deb }}.deb" sudo dpkg -i "$RUNNER_TEMP/nfpm.deb" @@ -235,6 +235,9 @@ jobs: for appimage in dist/release/*.AppImage; do chmod +x "$appimage" APPIMAGE_EXTRACT_AND_RUN=1 "$appimage" --version + # Update information (#349) is embedded, and the .zsync for delta updates sits beside it. + "$appimage" --appimage-updateinformation | grep -F 'gh-releases-zsync|' + test -s "$appimage.zsync" done - uses: actions/upload-artifact@v4 with: diff --git a/docs/releasing.md b/docs/releasing.md index 4fcdbc022..da9c39f93 100644 --- a/docs/releasing.md +++ b/docs/releasing.md @@ -51,8 +51,8 @@ in the dialog. | macOS 11+ (universal: Apple silicon + Intel) | `photocraft--macos-universal.dmg`, `photocraft-cli--macos-universal.zip` | `macos-15` | | Windows 10+ x64 | `photocraft--windows-x64.msi`, `photocraft--windows-x64-portable.zip` | `windows-latest` | | Windows 10+ x86 (32-bit) | `photocraft--windows-x86.msi`, `photocraft--windows-x86-portable.zip` | `windows-latest` | -| Linux x86_64 | `photocraft--linux-x86_64.{AppImage,deb,rpm,tar.gz,flatpak}` | `ubuntu-22.04` (Flatpak: `ubuntu-24.04`) | -| Linux aarch64 | `photocraft--linux-aarch64.{AppImage,deb,rpm,tar.gz,flatpak}` | `ubuntu-22.04-arm` (Flatpak: `ubuntu-24.04-arm`) | +| Linux x86_64 | `photocraft--linux-x86_64.{AppImage,AppImage.zsync,deb,rpm,tar.gz,flatpak}` | `ubuntu-22.04` (Flatpak: `ubuntu-24.04`) | +| Linux aarch64 | `photocraft--linux-aarch64.{AppImage,AppImage.zsync,deb,rpm,tar.gz,flatpak}` | `ubuntu-22.04-arm` (Flatpak: `ubuntu-24.04-arm`) | | FreeBSD 14 x86_64 | `photocraft--freebsd-x86_64.tar.gz` | FreeBSD 14.3 VM on `ubuntu-latest` | | Web | `photocraft-web-.zip` (static site; see [`packaging/web/README.md`](../packaging/web/README.md)) | `ubuntu-latest` | @@ -159,6 +159,9 @@ Why these formats: - **AppImage** runs on any distribution without installing anything. It's the download-and-go option and the fallback for distros the packages don't cover. It's built with the maintained `AppImage/appimagetool`, whose static runtime doesn't need libfuse2. + Each AppImage embeds update information (`gh-releases-zsync|…|latest|…`, #349) and ships + with a `.zsync` beside it, so AppImageUpdate, AppImageLauncher and similar tools can find + the next release and download only the blocks that changed. - **.deb** covers Debian, Ubuntu, Mint, Pop!_OS and elementary. **.rpm** covers Fedora, RHEL and its clones, and openSUSE. Both integrate with the menu, MIME and icon caches (the `postinst.sh` hook) and uninstall cleanly. Both are built by diff --git a/packaging/linux/package.sh b/packaging/linux/package.sh index b295cc452..0669d8073 100755 --- a/packaging/linux/package.sh +++ b/packaging/linux/package.sh @@ -2,6 +2,7 @@ # Build and package PhotoCraft for Linux ( is x86_64 or aarch64): # # $DIST/photocraft--linux-.AppImage any distro with glibc >= the build host's +# $DIST/photocraft--linux-.AppImage.zsync delta updates (needs zsyncmake) # $DIST/photocraft--linux-.deb Debian, Ubuntu, Mint, Pop!_OS, ... # $DIST/photocraft--linux-.rpm Fedora, openSUSE, RHEL, ... # $DIST/photocraft--linux-.tar.gz plain FHS-style tree (bin/, share/) @@ -10,7 +11,8 @@ # # Needs: cargo; nfpm for deb/rpm (https://nfpm.goreleaser.com); appimagetool for the AppImage # (downloaded into $CARGO_TARGET_DIR if missing). Build on an old distro (CI: Ubuntu 22.04, -# glibc 2.35) so the binaries run on newer ones. Optional: desktop-file-validate, appstreamcli. +# glibc 2.35) so the binaries run on newer ones. Optional: desktop-file-validate, appstreamcli, +# zsyncmake (the zsync package) for the AppImage's .zsync. set -euo pipefail # shellcheck source=../env.sh . "$(dirname "${BASH_SOURCE[0]}")/../env.sh" @@ -108,11 +110,29 @@ if has appimage; then chmod +x "$TOOL" fi fi - OUT="$DIST/$BASENAME.AppImage" + # Absolute, because appimagetool runs in $DIST below (CARGO_TARGET_DIR or APPIMAGETOOL may be + # relative, e.g. target/agent-). + OUT="$(cd "$DIST" && pwd)/$BASENAME.AppImage" + APPDIR="$(cd "$APPDIR" && pwd)" + TOOL="$(cd "$(dirname "$TOOL")" && pwd)/$(basename "$TOOL")" + # A .zsync left by an earlier run would hide a missing zsyncmake and describe another file. + rm -f "$OUT.zsync" + # Update information (#349): AppImageUpdate, AppImageLauncher and the like read it from the + # file and fetch only the blocks that changed in a newer release, through the .zsync published + # next to each AppImage on GitHub Releases. `latest` is the newest published release that is + # not a pre-release. A fork's builds point at its own releases through GITHUB_REPOSITORY. + REPO="${GITHUB_REPOSITORY:-storytold/photocraft}" + UPDATE_INFO="gh-releases-zsync|${REPO%%/*}|${REPO#*/}|latest|photocraft-*-linux-$ARCH.AppImage.zsync" # Extract-and-run: works without FUSE (containers, CI). The output embeds the static runtime, - # so users don't need libfuse2 either. - ARCH="$ARCH" APPIMAGE_EXTRACT_AND_RUN=1 "$TOOL" --no-appstream "$APPDIR" "$OUT" + # so users don't need libfuse2 either. With zsyncmake on the host (CI installs the zsync + # package) appimagetool also writes the .zsync, into its working directory, hence the cd. + (cd "$DIST" && ARCH="$ARCH" APPIMAGE_EXTRACT_AND_RUN=1 "$TOOL" --no-appstream -u "$UPDATE_INFO" "$APPDIR" "$OUT") echo "wrote $OUT" + if [ -s "$OUT.zsync" ]; then + echo "wrote $OUT.zsync" + else + warn "zsyncmake not found, so $OUT.zsync was not written; AppImage delta updates need it" + fi fi "$STAGE/usr/bin/photocraft-cli" --version