From 8fc77413df891770941bc749d30bd5e072f04693 Mon Sep 17 00:00:00 2001 From: PJ Date: Sun, 6 Sep 2026 14:16:36 +0530 Subject: [PATCH] fix Flatpak tooling and AppImage graphics on modern Linux --- .github/workflows/ci.yml | 4 +++- .github/workflows/release.yml | 3 ++- docs/release.md | 13 +++++++++---- flatpak/build.sh | 11 +++++++---- justfile | 2 +- scripts/prepare-bundle.mjs | 32 ++++++++++++++++++++++++++++++++ src-tauri/tauri.conf.json | 2 ++ 7 files changed, 56 insertions(+), 11 deletions(-) create mode 100644 scripts/prepare-bundle.mjs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9b12a94..0905d78 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -157,6 +157,7 @@ jobs: - name: Install Linux dependencies run: | + sudo add-apt-repository -y ppa:flatpak/stable sudo apt-get update sudo apt-get install -y \ libwebkit2gtk-4.1-dev \ @@ -167,7 +168,8 @@ jobs: libxdo-dev \ libssl-dev \ build-essential \ - flatpak + flatpak \ + flatpak-builder - uses: actions/setup-node@v6 with: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index af58a99..464cff2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -261,8 +261,9 @@ jobs: ref: ${{ needs.prepare.outputs.tag }} - run: | + sudo add-apt-repository -y ppa:flatpak/stable sudo apt-get update - sudo apt-get install -y flatpak + sudo apt-get install -y flatpak flatpak-builder - name: Build the flatpak from the published deb env: diff --git a/docs/release.md b/docs/release.md index 06be920..6d0ac2d 100644 --- a/docs/release.md +++ b/docs/release.md @@ -84,6 +84,11 @@ the ones that did not. Linux builds on Ubuntu 22.04 on purpose. The bundle will not run on anything older than the glibc it was linked against, so it is built on the oldest release that is supported. +Before bundling on Linux, `scripts/prepare-bundle.mjs` prepares a pinned GTK packaging plugin in +the project's tools cache. It leaves Wayland libraries to the host, alongside the host's graphics +driver: bundling Ubuntu's older Wayland makes recent Mesa fail to load and leaves the AppImage +window blank. This happens before Tauri generates updater signatures. + The Windows installers are not code-signed, so SmartScreen warns on the first download until the app has built up reputation. A certificate would go in as `WINDOWS_CERTIFICATE` and `WINDOWS_CERTIFICATE_PASSWORD` and needs nothing else changed. @@ -105,10 +110,10 @@ against. The sandbox gets the network, the notification service and the download nothing else. CI builds the same manifest on every push to main, against a deb built there, which is the only way a break in it gets found before a release. -On Linux, `just flatpak` builds the deb and repackages it locally. Install `flatpak` first; the -build script installs the GNOME runtime and `org.flatpak.Builder` from Flathub for your user. -Both CI and local builds use that builder because Ubuntu 22.04's `flatpak-builder` calls the old -`appstream-compose` tool, which the GNOME 48 SDK no longer includes. +On Linux, `just flatpak` builds the deb and repackages it locally. Install `flatpak` and +`flatpak-builder` 1.4.4 or newer first; the script installs the GNOME runtime for your user. +CI gets these tools from the Flatpak team's stable PPA because Ubuntu 22.04's original builder +calls `appstream-compose`, which the GNOME 48 SDK no longer includes. The **nix** job runs after the publish, so the flake can only ever point at a release that survived the manifest check. It hashes the published deb into `nix/release.json`, builds the package to diff --git a/flatpak/build.sh b/flatpak/build.sh index a326710..a3837c1 100755 --- a/flatpak/build.sh +++ b/flatpak/build.sh @@ -13,19 +13,22 @@ bundle=${1:-$here/margin-mail.flatpak} [ -f "$deb" ] || { echo "flatpak/build.sh: no $deb beside this script." >&2; exit 1; } +builder_version=$(flatpak-builder --version | sed -E 's/^flatpak-builder[- ]//') +if [ "$(printf '1.4.4\n%s\n' "$builder_version" | sort -V | head -1)" != 1.4.4 ]; then + echo "flatpak/build.sh: flatpak-builder >= 1.4.4 is required for GNOME 48's AppStream tools." >&2 + exit 1 +fi + runtime_version=$(sed -n "s/^runtime-version: *'\(.*\)'/\1/p" "$id.yml") # --user so nothing here needs root, and --if-not-exists so a second run is free. flatpak remote-add --user --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo flatpak install --user --noninteractive flathub \ - org.flatpak.Builder \ "org.gnome.Platform//$runtime_version" \ "org.gnome.Sdk//$runtime_version" rm -rf build repo -# Ubuntu 22.04's builder calls appstream-compose, which GNOME 48 no longer ships. -# Use the Flathub builder for its current AppStream support on CI and local builds alike. -flatpak run org.flatpak.Builder --user --disable-rofiles-fuse --force-clean --repo=repo build "$id.yml" +flatpak-builder --user --disable-rofiles-fuse --force-clean --repo=repo build "$id.yml" flatpak build-bundle repo "$bundle" "$id" echo "Wrote $bundle" diff --git a/justfile b/justfile index 8c0f39f..5c31a07 100644 --- a/justfile +++ b/justfile @@ -58,7 +58,7 @@ build: *) echo "just: no local build for $(uname -s); macOS and Linux are the desktop targets." >&2; exit 1 ;; esac -# Wants flatpak, and pulls the Flathub builder and GNOME runtime if they are not installed. +# Wants flatpak and flatpak-builder >= 1.4.4, and pulls the GNOME runtime if needed. # The release workflow runs the same script over the deb it published. # Build the flatpak, which is the deb repackaged. Linux only. flatpak: diff --git a/scripts/prepare-bundle.mjs b/scripts/prepare-bundle.mjs new file mode 100644 index 0000000..42c4897 --- /dev/null +++ b/scripts/prepare-bundle.mjs @@ -0,0 +1,32 @@ +// Tauri's AppImage GTK plugin bundles Ubuntu's Wayland libraries but uses the host's Mesa. +// Recent Mesa needs symbols absent from that older Wayland, so WebKit aborts before rendering. +// Keep the graphics driver's matching Wayland libraries on the host. Run before bundling so +// Tauri signs the final AppImage, and use a project-local tools cache to isolate this adjustment. +import { createHash } from "node:crypto"; +import { execFileSync } from "node:child_process"; +import { mkdir, writeFile } from "node:fs/promises"; +import { join } from "node:path"; + +if (process.env.TAURI_ENV_PLATFORM === "linux") { + const revision = "b5eb8d05b4c0ed40107fe2158c5d8527f94568ef"; + const url = `https://raw.githubusercontent.com/tauri-apps/linuxdeploy-plugin-gtk/${revision}/linuxdeploy-plugin-gtk.sh`; + const response = await fetch(url); + if (!response.ok) throw new Error(`GTK bundling plugin: HTTP ${response.status}`); + const source = await response.text(); + const hash = createHash("sha256").update(source).digest("hex"); + if (hash !== "cb379f9b0733e9ad9f8bd78f8c2fa038aef2478523bb7d4c8e64ff6a1ea3501a") { + throw new Error("GTK bundling plugin does not match the pinned source"); + } + + const metadata = JSON.parse(execFileSync("cargo", [ + "metadata", "--no-deps", "--format-version", "1", + "--manifest-path", "src-tauri/Cargo.toml", + ], { encoding: "utf8" })); + const tools = join(metadata.target_directory, ".tauri"); + await mkdir(tools, { recursive: true }); + await writeFile(join(tools, "linuxdeploy-plugin-gtk.sh"), `${source} +# Use the host Wayland libraries alongside the host graphics driver. +find "$APPDIR/usr/lib" -name 'libwayland-*.so*' -delete +`, { mode: 0o755 }); + console.log("Prepared AppImage GTK plugin with host Wayland libraries"); +} diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index ee848ff..c54fdf1 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -7,6 +7,7 @@ "beforeDevCommand": "pnpm dev", "devUrl": "http://localhost:1450", "beforeBuildCommand": "pnpm build", + "beforeBundleCommand": "node scripts/prepare-bundle.mjs", "frontendDist": "../dist" }, "app": { @@ -46,6 +47,7 @@ }, "bundle": { "active": true, + "useLocalToolsDir": true, "targets": [ "app", "dmg",