Files
mudler-agentandEttore Di Giacinto 33459f2e2a feat(launcher): ship an AppImage on tagged releases (#12647)
* feat(launcher): package a Linux AppImage

Ship the existing Fyne launcher as an additive release asset without
bundling the server or changing its runtime downloader.

Pin packaging tools and the type-2 runtime, preserve the caller
environment, and document the native amd64 graphics requirements.
Validate packaging contracts and wire extraction smoke checks into CI.

Assisted-by: Codex:gpt-5

* fix(launcher): harden AppImage release checks

PR builds must not receive repository write credentials. Isolate uploads
in a gated job that consumes the tested artifact without checkout.
Keep the existing release check and dependency on GoReleaser.

A surviving process does not prove that the UI event loop works.
Require observable startup progress, reject initialization errors, and
bound termination. Document the remaining limits without changing the
launcher application. Add permission and smoke failure regressions.

Assisted-by: nib:unknown

* fix(launcher): install file for AppImage builds

appimagetool fails after Go compilation when file is missing. Install
it explicitly in CI and document the local build dependency. Check for
it before compilation and cover the missing-command failure in tests.

Assisted-by: nib:unknown

---------

Co-authored-by: Ettore Di Giacinto <mudler@localai.io>
2026-10-12 17:17:43 +02:00

43 lines
1.7 KiB
Bash
Executable File

#!/usr/bin/env bash
# SPDX-License-Identifier: MIT
set -euo pipefail
root=$(cd "$(dirname "$0")/../.." && pwd)
image="$root/dist/LocalAI-Launcher-x86_64.AppImage"
work="$root/dist/appimage/smoke"
rm -rf "$work"
mkdir -p "$work/home" "$work/tmp"
export TMPDIR="$work/tmp"
(cd "$work" && "$image" --appimage-extract >/dev/null)
app="$work/squashfs-root"
test -x "$app/AppRun"
test -f "$app/local-ai-launcher.desktop"
test -f "$app/local-ai-launcher.png"
test ! -e "$app/usr/bin/local-ai"
desktop-file-validate "$app/local-ai-launcher.desktop"
ldd "$app/usr/bin/local-ai-launcher" > "$work/ldd.txt"
if grep -q 'not found' "$work/ldd.txt"; then
cat "$work/ldd.txt" >&2
exit 1
fi
# Prevent Initialize from downloading or starting the server during the smoke.
printf '%s\n' '{"auto_start_server":false,"show_welcome":false}' > "$work/config.json"
mkdir -p "$work/home/.localai"
cp "$work/config.json" "$work/home/.localai/launcher.json"
set +e
HOME="$work/home" XDG_CONFIG_HOME="$work/home/.config" LIBGL_ALWAYS_SOFTWARE=1 \
timeout --kill-after=5s 15s xvfb-run -a "$app/AppRun" > "$work/launch.log" 2>&1
status=$?
set -e
# This is a bounded startup check, not a UI event-loop heartbeat.
# Early exit (even code 0) and forced SIGKILL are failures.
[[ $status == 124 ]]
if grep -Ei 'panic:|fatal error:|failed to initialize GLFW|Failed to initialize launcher:|APIUnavailable' "$work/launch.log"; then
exit 1
fi
# On a fresh home this milestone follows config loading and startup setup.
# Survival alone could accept a process stalled before initialization.
grep -Fq 'No LocalAI installation found' "$work/launch.log"
test -d "$work/home/.localai/models"
test -d "$work/home/.localai/backends"
test ! -e "$work/home/.localai/bin/local-ai"