mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2026-10-30 07:37:38 +00:00
The Linux packages ran on X11 only: the bundled Temurin runtime's AWT has no Wayland toolkit, and the Flatpak required --socket=x11. On a Wayland session the app needed XWayland, and with no Xwayland it could not start. - Linux packages now bundle the JetBrains Runtime 21, whose AWT has a Wayland toolkit (WLToolkit). CI's Linux legs install it with actions/setup-java (distribution: jetbrains), and release CI fails a Linux build whose runtime lacks libawt_wlawt.so. macOS and Windows keep Temurin. - WaylandDisplay picks WLToolkit in main() when $WAYLAND_DISPLAY names a live socket and the runtime has it, and sets the Wayland app_id ($FLATPAK_ID, else "Amethyst", which the desktop entries already match). AMETHYST_X11=1 keeps a Wayland session on XWayland. - Compose's Window can't draw under WLToolkit (Skiko's surface locks the window through JAWT for an X11 handle), so AppWindow hosts the main window and the fullscreen video window in a Swing frame with a ComposePanel that draws through Swing on Skiko's CPU renderer, carrying the WindowState both ways, the close request, window-wide shortcuts and the crash window. On X11, macOS and Windows it is Compose's Window, as before. The crash dialog follows the same split. - JBR's Wayland toolkit detaches every window from a shutdown hook off the event thread, which Compose rejects: each logout or kill left a crash report. The Wayland frames skip that teardown off the event thread. - Flatpak: --socket=wayland + --socket=fallback-x11 instead of x11. - .rpm requires libwayland-client, libwayland-cursor and libxkbcommon; scripts/add-deb-wayland-deps.sh adds libxkbcommon0 (opened with dlopen) to the .deb. - Compose marks its jlink/jpackage tasks' JDK @Internal, so the build cache restored a Temurin runtime image into a JBR build. The JDK's release file is now a task input. - scripts/wayland-smoke-test.sh starts a packaged app on a headless sway with Xwayland off and passes only on a native Wayland window; the PR .deb smoke test runs it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UEcMZXsXFEWpfxgSMAgFKq
223 lines
9.0 KiB
YAML
223 lines
9.0 KiB
YAML
name: Desktop Smoke Test
|
|
|
|
on:
|
|
workflow_dispatch:
|
|
pull_request:
|
|
paths:
|
|
- 'desktopApp/**'
|
|
- '.github/workflows/smoke-test-desktop.yml'
|
|
# The keyring self-test exercises these, and the libraries they pin.
|
|
- 'commons/src/jvmMain/kotlin/com/vitorpamplona/amethyst/commons/keystorage/**'
|
|
- 'scripts/keyring-self-test.sh'
|
|
- 'gradle/libs.versions.toml'
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
concurrency:
|
|
group: smoke-desktop-${{ github.ref }}
|
|
cancel-in-progress: true
|
|
|
|
jobs:
|
|
# -------------------------------------------------------------------------
|
|
# 1) Compose UI test — verifies the composable tree renders (login screen)
|
|
# under the dev classpath. Catches missing string resources, broken
|
|
# composables, and basic dependency-graph issues.
|
|
# -------------------------------------------------------------------------
|
|
compose-ui-test:
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 30
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v7
|
|
|
|
- name: Set up JDK 21
|
|
uses: actions/setup-java@v6.0.1
|
|
with:
|
|
distribution: 'temurin'
|
|
java-version: 21
|
|
|
|
- name: Set up Gradle
|
|
uses: gradle/actions/setup-gradle@v6
|
|
with:
|
|
cache-read-only: true
|
|
|
|
- name: Install xvfb
|
|
run: sudo apt-get update && sudo apt-get install -y xvfb
|
|
|
|
- name: Run desktop tests (including UI smoke test)
|
|
run: xvfb-run --auto-servernum ./gradlew :desktopApp:test
|
|
|
|
# -------------------------------------------------------------------------
|
|
# 2) Release .deb build + launch — builds the ProGuard'd, jlink'd .deb
|
|
# package, installs it, and verifies the process stays alive for 10s.
|
|
# Catches ProGuard stripping (JNI, reflection), missing jlink modules
|
|
# (java.management, java.prefs), and native lib bundling issues.
|
|
#
|
|
# Runs on both x64 and arm64 hosted runners so release-time arm64 breakage
|
|
# (e.g. ProGuard rules missing an arch-specific reflection root) is caught
|
|
# at PR time instead of on the tag build.
|
|
# -------------------------------------------------------------------------
|
|
release-deb-launch:
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
os: [ubuntu-latest, ubuntu-24.04-arm]
|
|
runs-on: ${{ matrix.os }}
|
|
timeout-minutes: 45
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v7
|
|
|
|
# As in create-release.yml: Linux packages bundle the JetBrains Runtime (native Wayland).
|
|
- name: Set up JDK 21
|
|
uses: actions/setup-java@v6.0.1
|
|
with:
|
|
distribution: 'jetbrains'
|
|
java-version: 21
|
|
|
|
- name: Set up Gradle
|
|
uses: gradle/actions/setup-gradle@v6
|
|
with:
|
|
cache-read-only: true
|
|
|
|
- name: Install xvfb + packaging deps
|
|
# gnome-keyring + dbus: the keyring self-test below needs a Secret Service session.
|
|
# sway: the Wayland-only launch below.
|
|
run: sudo apt-get update && sudo apt-get install -y xvfb fakeroot gnome-keyring dbus sway
|
|
|
|
- name: Build release .deb
|
|
uses: nick-fields/retry@ad984534de44a9489a53aefd81eb77f87c70dc60 # v4.0.0
|
|
with:
|
|
max_attempts: 2
|
|
timeout_minutes: 20
|
|
command: ./gradlew --no-daemon :desktopApp:packageReleaseDeb
|
|
|
|
- name: Relax build-host-pinned deps
|
|
run: |
|
|
set -euo pipefail
|
|
chmod +x scripts/relax-deb-libicu.sh
|
|
scripts/relax-deb-libicu.sh desktopApp/build/compose/binaries/main-release/deb/*.deb
|
|
|
|
# Mirrors the same step in create-release.yml so this job exercises the
|
|
# exact .deb release ships. libskiko-linux-arm64.so has libEGL.so.1 in
|
|
# DT_NEEDED and jpackage does not scan lib/app/ for Depends, so without
|
|
# this the arm64 app dies at startup with
|
|
# UnsatisfiedLinkError: libEGL.so.1: cannot open shared object file
|
|
# See scripts/add-deb-libegl-dep.sh for the full rationale.
|
|
- name: Add libegl1 dep to arm64 .deb
|
|
run: |
|
|
set -euo pipefail
|
|
chmod +x scripts/add-deb-libegl-dep.sh
|
|
scripts/add-deb-libegl-dep.sh desktopApp/build/compose/binaries/main-release/deb/*.deb
|
|
|
|
# Also mirrors create-release.yml, so the install below resolves the same Depends.
|
|
- name: Add GStreamer deps to .deb
|
|
run: |
|
|
set -euo pipefail
|
|
chmod +x scripts/add-deb-gstreamer-deps.sh
|
|
scripts/add-deb-gstreamer-deps.sh desktopApp/build/compose/binaries/main-release/deb/*.deb
|
|
|
|
# Also mirrors create-release.yml: the bundled JBR opens libxkbcommon with dlopen.
|
|
- name: Add Wayland deps to .deb
|
|
run: |
|
|
set -euo pipefail
|
|
chmod +x scripts/add-deb-wayland-deps.sh
|
|
scripts/add-deb-wayland-deps.sh desktopApp/build/compose/binaries/main-release/deb/*.deb
|
|
|
|
# Also mirrors create-release.yml. Without it, jpackage's postinst runs
|
|
# xdg-desktop-menu, which fails here as on any system without menu
|
|
# directories ("No writable system menu directory found").
|
|
- name: Fix desktop entry in .deb
|
|
run: |
|
|
set -euo pipefail
|
|
chmod +x scripts/fix-deb-desktop-entry.sh
|
|
scripts/fix-deb-desktop-entry.sh desktopApp/build/compose/binaries/main-release/deb/*.deb
|
|
|
|
- name: Install .deb
|
|
run: |
|
|
set -euo pipefail
|
|
# Installed via apt (not `dpkg -i`) so the .deb's declared Depends are
|
|
# actually resolved — that is what pulls in libegl1 on the arm64
|
|
# runner, which does not ship it preinstalled. A failed install,
|
|
# maintainer scripts included, fails the job.
|
|
sudo apt-get install -y ./desktopApp/build/compose/binaries/main-release/deb/*.deb
|
|
dpkg-query -W -f='${Status}\n' amethyst | grep -qx 'install ok installed'
|
|
test -f /usr/share/applications/amethyst-Amethyst.desktop
|
|
echo "Installed files:"
|
|
dpkg -L amethyst | sed -n '1,30p'
|
|
# Fail if the binary wasn't actually extracted
|
|
test -d /opt/amethyst || test -d /opt/Amethyst || {
|
|
echo "FAIL: /opt/amethyst not found after dpkg -i"
|
|
exit 1
|
|
}
|
|
|
|
- name: Smoke test — app launches and stays alive
|
|
run: |
|
|
set -euo pipefail
|
|
|
|
# Find the launcher binary
|
|
LAUNCHER=$(find /opt -name "Amethyst" -type f -executable 2>/dev/null | head -1)
|
|
if [[ -z "$LAUNCHER" ]]; then
|
|
# Fallback: search dpkg file list
|
|
LAUNCHER=$(dpkg -L amethyst | grep -E '/bin/[Aa]methyst$' | head -1)
|
|
fi
|
|
if [[ -z "$LAUNCHER" ]]; then
|
|
echo "FAIL: could not find Amethyst launcher binary"
|
|
dpkg -L amethyst
|
|
exit 1
|
|
fi
|
|
echo "Launcher: $LAUNCHER"
|
|
|
|
# Launch under xvfb with a timeout safety net
|
|
xvfb-run --auto-servernum timeout 30 "$LAUNCHER" &
|
|
APP_PID=$!
|
|
echo "PID: $APP_PID"
|
|
|
|
# Wait 10s — if the process is still alive, the app launched successfully
|
|
sleep 10
|
|
|
|
if kill -0 "$APP_PID" 2>/dev/null; then
|
|
echo "PASS: Application launched and stayed alive for 10s"
|
|
kill "$APP_PID" || true
|
|
wait "$APP_PID" 2>/dev/null || true
|
|
else
|
|
wait "$APP_PID" 2>/dev/null
|
|
EXIT_CODE=$?
|
|
echo "FAIL: Application exited with code $EXIT_CODE within 10s"
|
|
exit 1
|
|
fi
|
|
|
|
# Wayland-only session (sway, Xwayland off): the app must open a native Wayland window,
|
|
# which needs the bundled JetBrains Runtime and the app picking its Wayland toolkit.
|
|
- name: Smoke test - app opens a native Wayland window
|
|
run: |
|
|
set -euo pipefail
|
|
LAUNCHER=$(find /opt -name "Amethyst" -type f -executable 2>/dev/null | head -1)
|
|
if [[ -z "$LAUNCHER" ]]; then
|
|
LAUNCHER=$(dpkg -L amethyst | grep -E '/bin/[Aa]methyst$' | head -1)
|
|
fi
|
|
[[ -n "$LAUNCHER" ]] || { echo "FAIL: could not find Amethyst launcher binary"; exit 1; }
|
|
bash scripts/wayland-smoke-test.sh "$LAUNCHER"
|
|
|
|
# The release build must keep keys in the OS keyring: ProGuard once stripped the D-Bus
|
|
# transport and broke a signed jar, so every Linux release silently stopped using it.
|
|
# See commons/plans/2026-10-12-desktop-key-storage.md.
|
|
- name: Keyring self-test - the installed app keeps keys in GNOME Keyring
|
|
run: |
|
|
set -euo pipefail
|
|
LAUNCHER=$(find /opt -name "Amethyst" -type f -executable 2>/dev/null | head -1)
|
|
if [[ -z "$LAUNCHER" ]]; then
|
|
LAUNCHER=$(dpkg -L amethyst | grep -E '/bin/[Aa]methyst$' | head -1)
|
|
fi
|
|
[[ -n "$LAUNCHER" ]] || { echo "FAIL: could not find Amethyst launcher binary"; exit 1; }
|
|
bash scripts/keyring-self-test.sh "$LAUNCHER"
|
|
|
|
- name: Upload .deb artifact (for manual testing)
|
|
if: always()
|
|
uses: actions/upload-artifact@v7
|
|
with:
|
|
# Artifact names must be unique across a run — disambiguate per arch.
|
|
name: Release DEB (smoke-tested, ${{ matrix.os }})
|
|
path: desktopApp/build/compose/binaries/main-release/deb/*.deb
|