Phase 4a sub-commit 5: performance-smoke harness + 4a closure
examples/todo/tests/perfsmoke.sh asserts the PLAN.md §11 budgets
against the built AppImage:
- Bundle size ≤ 200 MB (hard cap; ≤ 120 MB target)
- Cold start ≤ 2000 ms from launch to first /healthz 200
- Idle RSS (host + descendants in the process group) ≤ 200 MB after
a 2 s settle.
Each budget is overridable via env (PERF_COLD_START_MS etc.) for slow
shared CI runners; defaults are the strict numbers from the plan. Runs
the AppImage under xvfb-run when DISPLAY is unset; falls back to
QT_QPA_PLATFORM=offscreen otherwise (the build script already bundles
libqoffscreen.so via EXTRA_PLATFORM_PLUGINS).
Wired into:
- examples/todo/Makefile → `make perf`
- .gitea/workflows/release.yml → runs after AppImage build, before
zsync + upload, with cold-start budget bumped to 4 s for CI.
CI now also installs zsync + xvfb in one step.
examples/todo/README.md gains an "AppImage packaging (Phase 4a)"
section walking through `make appimage`, bundled-mode behaviour, the
auto-update QML hooks (BackendConnection.checkForUpdates() / applyUpdate()),
and `make perf`.
PLAN.md §13 Phase 4 marked **4a closed**. 4b (macOS) and 4c (Windows)
stay stubs until their runners + certs exist.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -79,3 +79,40 @@ todo/
|
||||
|
||||
- A CI-driven version of the multi-window / crash-recover tests lives in Phase 3 sub-commit 4 as a bridge-integration suite.
|
||||
- No persistence options (export, backup) — same SQLite `var/data.sqlite` as the skeleton. Apps move to Postgres by overriding `DATABASE_URL`.
|
||||
|
||||
## AppImage packaging (Phase 4a)
|
||||
|
||||
```bash
|
||||
FRANKENPHP=/path/to/frankenphp make appimage
|
||||
./build/Todo-x86_64.AppImage
|
||||
```
|
||||
|
||||
`make appimage` stages a `composer install --no-dev` copy of the Symfony app, downloads `linuxdeploy` + `appimagetool` + the AppImageUpdate sidecar (cached under `packaging/linux/tools/`, gitignored), and produces `build/Todo-x86_64.AppImage` (~150 MB). The AppImage carries everything needed: Qt runtime, the bundled FrankenPHP binary, the Symfony app, and an `AppImageUpdate.AppImage` sidecar for in-place updates.
|
||||
|
||||
When the AppImage runs without `BRIDGE_URL` set, `BackendConnection` switches to **bundled mode**: it spawns the embedded FrankenPHP, generates a per-session bearer token, runs first-launch migrations into `~/.local/share/php-qml/todo/var/data.sqlite`, and supervises the child. Killing FrankenPHP from outside the AppImage triggers an automatic restart with a fresh token (PLAN.md §3 *Edge cases — Per-session secret rotation*).
|
||||
|
||||
### Auto-update
|
||||
|
||||
The AppImage is built with an embedded `update-info` ELF section pointing at the canonical Gitea Releases URL for its tag (set via `APPIMAGE_UPDATE_INFO` at build time). The bundled sidecar implements the actual download and patch via zsync.
|
||||
|
||||
From QML:
|
||||
|
||||
```qml
|
||||
Connections {
|
||||
target: BackendConnection
|
||||
function onUpdatesAvailable() { ... }
|
||||
function onNoUpdatesAvailable() { ... }
|
||||
function onUpdateApplied() { ... } // restart prompt
|
||||
}
|
||||
|
||||
Button { text: "Check for updates"; onClicked: BackendConnection.checkForUpdates() }
|
||||
Button { text: "Update"; onClicked: BackendConnection.applyUpdate() }
|
||||
```
|
||||
|
||||
### Performance smoke
|
||||
|
||||
```bash
|
||||
make perf
|
||||
```
|
||||
|
||||
Asserts the §11 *Performance budgets*: bundle ≤ 200 MB, cold start ≤ 2 s (4 s on shared CI runners), idle RSS ≤ 200 MB. CI runs this on every release tag before publishing.
|
||||
|
||||
Reference in New Issue
Block a user