From a192e4b545edecbec673e180aa8426efa67965fb Mon Sep 17 00:00:00 2001 From: KtzeAbyss Date: Tue, 21 Jul 2026 13:10:02 +0800 Subject: [PATCH] fix(release): strip bundled Wayland libraries from AppImage --- .github/workflows/desktop-release.yml | 14 +++ scripts/release/postprocess-linux-appimage.sh | 113 ++++++++++++++++++ 2 files changed, 127 insertions(+) create mode 100755 scripts/release/postprocess-linux-appimage.sh diff --git a/.github/workflows/desktop-release.yml b/.github/workflows/desktop-release.yml index 2e17e1b5e..04b6a5c05 100644 --- a/.github/workflows/desktop-release.yml +++ b/.github/workflows/desktop-release.yml @@ -294,6 +294,20 @@ jobs: LIVEAGENT_UPDATE_REPOSITORY: ${{ github.repository }} run: pnpm tauri build --config src-tauri/tauri.linux.release.conf.json --config "$LIVEAGENT_TAURI_VERSION_CONFIG" --target x86_64-unknown-linux-gnu --bundles appimage deb rpm + - name: Strip bundled Wayland libraries and re-sign AppImage + env: + TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} + TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }} + run: | + set -euo pipefail + appimage_path="$(find crates/agent-gui/src-tauri/target target -type f -name '*.AppImage' -path '*bundle*' -print -quit 2>/dev/null || true)" + test -n "$appimage_path" + appimage_path="$(realpath "$appimage_path")" + scripts/release/postprocess-linux-appimage.sh "$appimage_path" + test ! -e "$appimage_path.sig" + pnpm --dir crates/agent-gui tauri signer sign "$appimage_path" + test -s "$appimage_path.sig" + - name: Stage Linux artifacts run: | set -euo pipefail diff --git a/scripts/release/postprocess-linux-appimage.sh b/scripts/release/postprocess-linux-appimage.sh new file mode 100755 index 000000000..715c71947 --- /dev/null +++ b/scripts/release/postprocess-linux-appimage.sh @@ -0,0 +1,113 @@ +#!/usr/bin/env bash +set -euo pipefail + +readonly APPIMAGETOOL_VERSION="1.9.1" +readonly APPIMAGETOOL_SHA256="ed4ce84f0d9caff66f50bcca6ff6f35aae54ce8135408b3fa33abfc3cb384eb0" +readonly APPIMAGETOOL_URL="https://github.com/AppImage/appimagetool/releases/download/${APPIMAGETOOL_VERSION}/appimagetool-x86_64.AppImage" + +usage() { + echo "Usage: $0 " >&2 +} + +fail() { + echo "postprocess-linux-appimage: $*" >&2 + exit 1 +} + +if [ "$#" -ne 1 ]; then + usage + exit 2 +fi + +for command_name in curl find grep head realpath sha256sum; do + command -v "$command_name" >/dev/null 2>&1 || fail "missing required command: $command_name" +done + +appimage_path="$(realpath "$1")" +test -f "$appimage_path" || fail "AppImage not found: $appimage_path" +test -x "$appimage_path" || fail "AppImage is not executable: $appimage_path" + +appimage_dir="$(dirname "$appimage_path")" +work_dir="$(mktemp -d "$appimage_dir/.liveagent-appimage.XXXXXX")" +cleanup() { + rm -rf -- "$work_dir" +} +trap cleanup EXIT + +extract_dir="$work_dir/extract" +mkdir -p "$extract_dir" +( + cd "$extract_dir" + "$appimage_path" --appimage-extract >/dev/null +) + +app_dir="$extract_dir/squashfs-root" +test -x "$app_dir/AppRun" || fail "extracted AppImage is missing executable AppRun" +test -x "$app_dir/AppRun.wrapped" || fail "extracted AppImage is missing executable AppRun.wrapped" + +mapfile -d '' bundled_wayland_libraries < <( + find "$app_dir/usr/lib" \( -type f -o -type l \) \ + -name 'libwayland-*.so*' -print0 +) +if [ "${#bundled_wayland_libraries[@]}" -eq 0 ]; then + fail "no bundled libwayland libraries found; refusing to rewrite an unexpected AppImage" +fi + +echo "Removing bundled Wayland libraries:" +for library_path in "${bundled_wayland_libraries[@]}"; do + echo " ${library_path#"$app_dir"/}" +done +rm -f -- "${bundled_wayland_libraries[@]}" + +if find "$app_dir/usr/lib" \( -type f -o -type l \) \ + -name 'libwayland-*.so*' -print -quit | grep -q .; then + fail "bundled libwayland libraries remain after cleanup" +fi + +runtime_offset="$("$appimage_path" --appimage-offset)" +case "$runtime_offset" in + ''|*[!0-9]*) fail "invalid AppImage runtime offset: $runtime_offset" ;; +esac +if [ "$runtime_offset" -le 0 ]; then + fail "invalid AppImage runtime offset: $runtime_offset" +fi +runtime_path="$work_dir/runtime-x86_64" +head -c "$runtime_offset" "$appimage_path" > "$runtime_path" + +if [ -n "${APPIMAGETOOL_PATH:-}" ]; then + appimagetool_path="$(realpath "$APPIMAGETOOL_PATH")" + test -x "$appimagetool_path" || fail "APPIMAGETOOL_PATH is not executable: $appimagetool_path" +else + appimagetool_path="$work_dir/appimagetool-x86_64.AppImage" + curl --fail --location --retry 3 --silent --show-error \ + --output "$appimagetool_path" "$APPIMAGETOOL_URL" + echo "$APPIMAGETOOL_SHA256 $appimagetool_path" | sha256sum --check --status || \ + fail "appimagetool checksum verification failed" + chmod +x "$appimagetool_path" +fi + +repacked_path="$work_dir/repacked.AppImage" +ARCH=x86_64 APPIMAGE_EXTRACT_AND_RUN=1 "$appimagetool_path" \ + --no-appstream \ + --runtime-file "$runtime_path" \ + "$app_dir" "$repacked_path" +test -s "$repacked_path" || fail "appimagetool did not produce an AppImage" +chmod --reference="$appimage_path" "$repacked_path" + +verify_dir="$work_dir/verify" +mkdir -p "$verify_dir" +( + cd "$verify_dir" + "$repacked_path" --appimage-extract >/dev/null +) +verified_app_dir="$verify_dir/squashfs-root" +test -x "$verified_app_dir/AppRun" || fail "repacked AppImage is missing executable AppRun" +test -x "$verified_app_dir/AppRun.wrapped" || fail "repacked AppImage is missing executable AppRun.wrapped" +if find "$verified_app_dir/usr/lib" \( -type f -o -type l \) \ + -name 'libwayland-*.so*' -print -quit | grep -q .; then + fail "repacked AppImage still contains bundled libwayland libraries" +fi + +mv -f -- "$repacked_path" "$appimage_path" +rm -f -- "$appimage_path.sig" +echo "Repacked AppImage without bundled Wayland libraries: $appimage_path"