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>
This commit is contained in:
2026-05-02 19:58:02 +02:00
parent d8726bac94
commit fddb70f877
5 changed files with 179 additions and 9 deletions

View File

@@ -98,6 +98,8 @@ private slots:
void probe();
void onProbeFinished();
void onChildFinished(int exitCode, QProcess::ExitStatus status);
void onUpdateCheckFinished(int exitCode, QProcess::ExitStatus status);
void onUpdateApplyFinished(int exitCode, QProcess::ExitStatus status);
private:
void initDevMode();
@@ -135,6 +137,12 @@ private:
QProcess* m_child = nullptr;
int m_supervisorRetries = 0;
static constexpr int kMaxSupervisorRetries = 5;
QProcess* m_updateCheck = nullptr;
QProcess* m_updateApply = nullptr;
QString resolveSidecarUpdater() const;
QString currentAppImagePath() const;
};
} // namespace PhpQml::Bridge