Commit Graph

2 Commits

Author SHA1 Message Date
fddb70f877 Phase 4a sub-commit 4: AppImageUpdate sidecar + appcast + checkForUpdates()
Wires in the option-(a) sidecar approach: the AppImage carries a
bundled AppImageUpdate AppImage and an embedded update-info string
in the .upd_info ELF section. BackendConnection drives both the
check and the apply via QProcess.

BackendConnection:
  - Q_INVOKABLE checkForUpdates()
        Bundled mode only. Spawns AppImageUpdate.AppImage with
        --check-for-update <APPIMAGE>. Exits 0 → noUpdatesAvailable,
        1 → updatesAvailable, anything else → updateCheckFailed.
        Dev mode: emits updateCheckFailed("…dev-mode only").
  - Q_INVOKABLE applyUpdate()
        Bundled mode only. Spawns AppImageUpdate.AppImage with
        --remove-old <APPIMAGE>. Replaces the running AppImage in
        place; user must restart. Emits updateApplied or
        updateApplyFailed.
  - Sidecar path resolves to applicationDirPath()/AppImageUpdate.AppImage
    by default, overridable via BRIDGE_APPIMAGEUPDATE_BIN.
  - APPIMAGE env (set by the AppImage runtime) determines the target
    file. Outside an AppImage both methods fail loudly.

build-appimage.sh:
  - Auto-downloads AppImageUpdate-x86_64.AppImage into the cached
    tools dir and copies it into AppDir/usr/bin/AppImageUpdate.AppImage.
  - New --update-info flag, forwarded to appimagetool's -u so the
    .upd_info ELF section carries an "zsync|<URL>" string the sidecar
    will fetch.

examples/todo Makefile forwards APPIMAGE_UPDATE_INFO env to the
script as --update-info.

release.yml:
  - Builds the AppImage with APPIMAGE_UPDATE_INFO set to the canonical
    Gitea Releases asset URL for this tag.
  - Installs zsync, runs zsyncmake to generate Todo-x86_64.AppImage.zsync.
  - Generates a JSON appcast (latest.json) with version / url / sha256 /
    size / zsync URL / released_at — useful as an HTTP-fetchable
    fallback for clients that prefer a structured manifest.
  - SHA256SUMS now covers AppImage + zsync + latest.json.
  - Uploads all four assets to the Gitea Release.

AppImage size grows from ~104 MB to ~152 MB with the sidecar bundled.
Embedding verified: objdump shows .upd_info populated with the
expected zsync URL after a local build.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 19:58:02 +02:00
26124266e7 Phase 4a sub-commit 2: AppImage recipe (build-appimage.sh + make appimage)
packaging/linux/build-appimage.sh produces a single-file Linux
AppImage from a built host + Symfony tree + FrankenPHP binary.
Auto-downloads (cached in tools/, gitignored) the three pieces of
upstream tooling:

  - linuxdeploy + linuxdeploy-plugin-qt — gathers Qt runtime and QML
    modules into the AppDir, and bundles the offscreen platform
    plugin via EXTRA_PLATFORM_PLUGINS so headless CI can smoke it.
  - appimagetool — squashes the AppDir into the .AppImage.
  - runtime-x86_64 — appimagetool's prepended runtime stub, fetched
    once and passed via --runtime-file (ad-hoc downloads stalled on
    some networks).

The two stages are kept separate (linuxdeploy stages, then we invoke
appimagetool ourselves) so failures are observable rather than
swallowed by linuxdeploy's bundled-tool path.

AppDir layout matches BackendConnection's resolve* fallbacks:
  AppDir/usr/bin/<app>
  AppDir/usr/bin/frankenphp
  AppDir/usr/share/<app>/symfony/
  AppDir/usr/share/<app>/Caddyfile

examples/todo gets `make appimage`: stages a no-dev composer install
into build/staging-symfony, points the path repo at the bundle's
absolute path so Composer can find php-qml/bridge from the staging
dir, then drives build-appimage.sh. Output:
build/Todo-x86_64.AppImage (~104 MB).

Verified locally: `make appimage` produces a working AppImage; mount
+ inspect + extract all clean. Headless run requires the bundled
offscreen plugin (now wired); a real desktop launches it normally.

Includes a 64×64 placeholder PNG icon (todo.png) and a minimal
.desktop file for the example.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 19:42:51 +02:00