Merge pull request #2940 from vitorpamplona/claude/fix-ci-build-desktop-2qHSV

Replace linuxdeploy with appimagetool for AppImage packaging
This commit is contained in:
Vitor Pamplona
2026-05-16 15:08:44 -04:00
committed by GitHub
4 changed files with 48 additions and 30 deletions
+15 -9
View File
@@ -21,9 +21,13 @@ permissions:
env:
# Asset naming contract: amethyst-desktop-<version>-<family>-<arch>.<ext>
# Single source of truth in scripts/asset-name.sh.
# linuxdeploy pinned release — bump via Dependabot, verify SHA256 via env var below.
LINUXDEPLOY_URL: https://github.com/linuxdeploy/linuxdeploy/releases/download/1-alpha-20240109-1/linuxdeploy-x86_64.AppImage
LINUXDEPLOY_SHA256: c86d6540f1df31061f02f539a2d3445f8d7f85cc3994eee1e74cd1ac97b76df0
# appimagetool pinned release — bump via Dependabot, verify SHA256 via env var below.
# We used to use linuxdeploy here, but it auto-walks the AppDir with ldd to
# bundle deps — that fights jpackage's self-contained JRE (libjvm.so RPATH
# mismatch) and the UPX-compressed VLC plugins. appimagetool only embeds the
# AppDir as-is, which is what we actually want.
APPIMAGETOOL_URL: https://github.com/AppImage/appimagetool/releases/download/1.9.0/appimagetool-x86_64.AppImage
APPIMAGETOOL_SHA256: 46fdd785094c7f6e545b61afcfb0f3d98d8eab243f644b4b17698c01d06083d1
jobs:
# ---------------------------------------------------------------------------
@@ -83,17 +87,19 @@ jobs:
if: matrix.family == 'linux'
run: sudo apt-get update && sudo apt-get install -y rpm fakeroot
- name: Fetch linuxdeploy (linux-portable only, SHA-verified)
- name: Fetch appimagetool (linux-portable only, SHA-verified)
if: matrix.family == 'linux-portable'
run: |
set -euo pipefail
curl -fsSL --retry 3 "$LINUXDEPLOY_URL" -o desktopApp/packaging/appimage/linuxdeploy-x86_64.AppImage
actual=$(sha256sum desktopApp/packaging/appimage/linuxdeploy-x86_64.AppImage | awk '{print $1}')
if [[ "$actual" != "$LINUXDEPLOY_SHA256" ]]; then
echo "::error::linuxdeploy SHA256 mismatch. Expected $LINUXDEPLOY_SHA256, got $actual"
# appimagetool 1.9.0 validates the .desktop file via desktop-file-validate.
sudo apt-get update && sudo apt-get install -y desktop-file-utils
curl -fsSL --retry 3 "$APPIMAGETOOL_URL" -o desktopApp/packaging/appimage/appimagetool-x86_64.AppImage
actual=$(sha256sum desktopApp/packaging/appimage/appimagetool-x86_64.AppImage | awk '{print $1}')
if [[ "$actual" != "$APPIMAGETOOL_SHA256" ]]; then
echo "::error::appimagetool SHA256 mismatch. Expected $APPIMAGETOOL_SHA256, got $actual"
exit 1
fi
chmod +x desktopApp/packaging/appimage/linuxdeploy-x86_64.AppImage
chmod +x desktopApp/packaging/appimage/appimagetool-x86_64.AppImage
- name: Build desktop artifacts
uses: nick-fields/retry@ad984534de44a9489a53aefd81eb77f87c70dc60 # v4.0.0
+1 -2
View File
@@ -167,8 +167,7 @@ desktopApp/src/jvmMain/appResources/macos/
desktopApp/src/jvmMain/appResources/windows/
# CI-fetched AppImage tooling (downloaded by create-release workflow; not committed)
desktopApp/packaging/appimage/linuxdeploy-x86_64.AppImage
desktopApp/packaging/appimage/linuxdeploy-extracted/
desktopApp/packaging/appimage/appimagetool-x86_64.AppImage
desktopApp/packaging/appimage/squashfs-root/
# Git worktrees
+9 -5
View File
@@ -27,7 +27,8 @@ Platform-specific:
- **macOS**: Xcode Command Line Tools (`xcode-select --install`)
- **Windows**: WiX Toolset 3.x on PATH (for MSI). `winget install WiXToolset.WiXToolset`
- **Linux (all)**: nothing extra for `.deb`; `rpm` + `fakeroot` for `.rpm`; `linuxdeploy` for AppImage
- **Linux (all)**: nothing extra for `.deb`; `rpm` + `fakeroot` for `.rpm`;
`appimagetool` + `desktop-file-utils` for AppImage
Install Linux RPM tooling:
@@ -39,12 +40,15 @@ sudo apt-get install -y rpm fakeroot
sudo dnf install -y rpm-build
```
Install linuxdeploy locally (CI fetches its own — SHA-verified):
Install appimagetool locally (CI fetches its own — SHA-verified):
```bash
curl -fsSL -o desktopApp/packaging/appimage/linuxdeploy-x86_64.AppImage \
https://github.com/linuxdeploy/linuxdeploy/releases/download/1-alpha-20240109-1/linuxdeploy-x86_64.AppImage
chmod +x desktopApp/packaging/appimage/linuxdeploy-x86_64.AppImage
# Debian/Ubuntu — appimagetool calls desktop-file-validate on the .desktop entry
sudo apt-get install -y desktop-file-utils
curl -fsSL -o desktopApp/packaging/appimage/appimagetool-x86_64.AppImage \
https://github.com/AppImage/appimagetool/releases/download/1.9.0/appimagetool-x86_64.AppImage
chmod +x desktopApp/packaging/appimage/appimagetool-x86_64.AppImage
```
---
+23 -14
View File
@@ -186,27 +186,39 @@ tasks.withType<Download>().configureEach {
// --- AppImage packaging (Linux) ---
//
// Compose Multiplatform's TargetFormat.AppImage is known-broken in 1.10.x (CMP-7101).
// Instead: wrap `createReleaseDistributable` output with `linuxdeploy` (which
// auto-bundles libraries, handles rpath, and calls appimagetool internally).
// Instead: wrap `createReleaseDistributable` output with `appimagetool`, which
// just packages an AppDir as-is. We deliberately avoid `linuxdeploy` here —
// linuxdeploy auto-walks every binary in the AppDir with ldd to bundle deps,
// but jpackage already ships a self-contained tree we don't want it touching:
// - The bundled JRE puts libjvm.so under usr/lib/runtime/lib/server/ while
// sibling libs (libmanagement.so, libawt_xawt.so, libfontmanager.so) have
// RPATH=$ORIGIN, so ldd cannot resolve libjvm.so without help.
// - The bundled VLC plugins are UPX-compressed; linuxdeploy aborts on those
// with "patchelf: no section headers" because they look like static ELFs.
// - Several VLC libs have RUNPATH that does not point at sibling libs in
// the same directory, so ldd errors with "Could not find dependency".
// appimagetool sidesteps all of this — it only embeds the AppDir into a
// SquashFS, runtime-prepended, signed AppImage. AppRun handles LD_LIBRARY_PATH
// at launch.
//
// Build inputs live in desktopApp/packaging/appimage/:
// - AppRun shell launcher (sets LD_LIBRARY_PATH including bundled VLC)
// - amethyst.desktop XDG desktop entry
// - amethyst.png 512x512 icon
//
// linuxdeploy binary is fetched by CI (SHA-verified) into
// desktopApp/packaging/appimage/ as linuxdeploy-x86_64.AppImage.
// appimagetool binary is fetched by CI (SHA-verified) into
// desktopApp/packaging/appimage/ as appimagetool-x86_64.AppImage.
// BUILDING.md documents local-dev fetch.
val createReleaseAppImage by tasks.registering(Exec::class) {
group = "compose desktop"
description = "Bundle createReleaseDistributable output into a Linux AppImage via linuxdeploy."
description = "Package createReleaseDistributable output into a Linux AppImage via appimagetool."
dependsOn("createReleaseDistributable")
val distDir = layout.buildDirectory.dir("compose/binaries/main-release/app/Amethyst")
val appDir = layout.buildDirectory.dir("appimage/Amethyst.AppDir")
val outFile = layout.buildDirectory.file("appimage/Amethyst-$appVersion-x86_64.AppImage")
val toolRoot = layout.projectDirectory.dir("packaging/appimage")
val linuxdeployTool = toolRoot.file("linuxdeploy-x86_64.AppImage")
val appimagetool = toolRoot.file("appimagetool-x86_64.AppImage")
inputs.dir(distDir)
inputs.dir(toolRoot)
@@ -231,19 +243,16 @@ val createReleaseAppImage by tasks.registering(Exec::class) {
if (dirIcon.exists()) dirIcon.delete()
Files.createSymbolicLink(dirIcon.toPath(), File("amethyst.png").toPath())
if (!linuxdeployTool.asFile.canExecute()) {
linuxdeployTool.asFile.setExecutable(true)
if (!appimagetool.asFile.canExecute()) {
appimagetool.asFile.setExecutable(true)
}
}
commandLine(
linuxdeployTool.asFile.absolutePath,
"--appdir", appDir.get().asFile.absolutePath,
"--output", "appimage",
"--desktop-file", "${appDir.get().asFile}/amethyst.desktop",
"--icon-file", "${appDir.get().asFile}/amethyst.png",
appimagetool.asFile.absolutePath,
appDir.get().asFile.absolutePath,
outFile.get().asFile.absolutePath,
)
environment("OUTPUT", outFile.get().asFile.absolutePath)
environment("ARCH", "x86_64")
// Bypass FUSE requirement on CI runners (ubuntu-latest lacks libfuse.so.2).
// AppImage standard env var: extracts + runs without mounting.