diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b0c2fc..079d2a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ Bugfix release closing the four follow-ups identified during the v0.1.0 shakedow ### Fixed +- **Wipe Symfony cache on bundled-mode launch.** Symfony's compiled container bakes `kernel.project_dir` as an absolute path. In bundled mode that path lives inside the AppImage's FUSE mount (`/tmp/.mount_`), which is regenerated every launch. So the cache from launch N referenced mount-N's path; launch N+1 (different mount) hit `InvalidDirectory` from doctrine-migrations on the first launch-2 (and similar at any kernel.project_dir-sensitive lookup). `BackendConnection::initBundledMode` now `rmdir`s the cache before each spawn. Costs ~1-2s of warmup per launch; build-time cache warmup is the permanent fix (PLAN.md §13 v0.2.0). The bundled-supervisor integration test gained a 2nd-launch-from-fresh-staging step so this regresses if forgotten. - **`HealthController` deep-loads the bundle.** Constructor-injects `Publisher` so `/healthz` returns 200 only when `BridgeBundle` is fully container-resolvable. v0.1.0's `/healthz` returned 200 against half-loaded bundles — both the path-repo symlink dangling at runtime and the read-only-cache failure shipped green through perfsmoke as a result. Response body now includes `bundle: "PhpQml\\Bridge\\Publisher"` as the canary value. - **Caddyfile formatting.** `framework/skeleton/Caddyfile` and `examples/todo/Caddyfile` reformatted with `caddy fmt`. The "Caddyfile input is not formatted; run 'caddy fmt --overwrite'" warning that fired on every FrankenPHP boot is gone. diff --git a/examples/todo/tests/bundled-supervisor.sh b/examples/todo/tests/bundled-supervisor.sh index 81f3e89..a55affc 100755 --- a/examples/todo/tests/bundled-supervisor.sh +++ b/examples/todo/tests/bundled-supervisor.sh @@ -138,4 +138,52 @@ if [ -d "$ROOT/usr/share/$APP_NAME/symfony/var/cache/prod" ] && \ fail "Symfony wrote into the read-only staging tree — Kernel::getCacheDir override broken" fi -step "All bundled-supervisor assertions passed." +# ── Second launch: same XDG_DATA_HOME, fresh staging mount ───────────── +# Real AppImages get a fresh /tmp/.mount_ per launch but reuse the +# user data dir, so any cached absolute path from launch N is stale by N+1. +# Tear down the running host, re-run from a NEW staging dir (mimicking the +# fresh-mount situation), assert /healthz comes back up. +step "tear down + relaunch from fresh staging (regression: cache-baked-mount-path)" +kill -TERM "$PID" 2>/dev/null || true +for _ in 1 2 3 4 5 6 7 8 9 10; do + kill -0 "$PID" 2>/dev/null || break + sleep 0.2 +done +kill -KILL "$PID" 2>/dev/null || true +PID="" +chmod -R u+w "$ROOT/usr/share/$APP_NAME/symfony" 2>/dev/null +rm -rf "$ROOT" +ROOT="$(mktemp -d)" +mkdir -p "$ROOT/usr/bin" "$ROOT/usr/share/$APP_NAME" +cp "$HOST_BIN" "$ROOT/usr/bin/$APP_NAME" +ln -s "$(command -v frankenphp)" "$ROOT/usr/bin/frankenphp" +cp -a "$STAGING/." "$ROOT/usr/share/$APP_NAME/symfony/" +cp "$CADDYFILE" "$ROOT/usr/share/$APP_NAME/Caddyfile" +chmod -R a-w "$ROOT/usr/share/$APP_NAME/symfony" + +LOG2="$DATA_DIR/host2.log" +env -u BRIDGE_URL \ + XDG_DATA_HOME="$DATA_DIR/share" \ + XDG_CACHE_HOME="$DATA_DIR/cache" \ + XDG_CONFIG_HOME="$DATA_DIR/config" \ + QT_QPA_PLATFORM=offscreen \ + "$ROOT/usr/bin/$APP_NAME" > "$LOG2" 2>&1 & +PID=$! + +DEADLINE=$(( $(date +%s) + 30 )) +HEALTHZ2_BODY="" +while [ "$(date +%s)" -lt "$DEADLINE" ]; do + if ! kill -0 "$PID" 2>/dev/null; then + sed 's/^/ /' "$LOG2" >&2 || true + fail "host died during 2nd boot" + fi + if HEALTHZ2_BODY="$(curl -fsS -m 1 "http://127.0.0.1:$PORT/healthz" 2>/dev/null)"; then + break + fi + sleep 0.2 +done +[ -n "$HEALTHZ2_BODY" ] || { sed 's/^/ /' "$LOG2" >&2 || true; fail "/healthz never responded on 2nd launch — stale cache?"; } +echo "$HEALTHZ2_BODY" | grep -q '"status":"ok"' \ + || fail "2nd-launch /healthz didn't return status:ok" + +step "All bundled-supervisor assertions passed (incl. 2nd-launch cache wipe)." diff --git a/framework/qml/src/BackendConnection.cpp b/framework/qml/src/BackendConnection.cpp index cf5bac1..44f0d88 100644 --- a/framework/qml/src/BackendConnection.cpp +++ b/framework/qml/src/BackendConnection.cpp @@ -109,6 +109,9 @@ void BackendConnection::initBundledMode() m_dataDir = userDataDir(); QDir().mkpath(m_dataDir + "/var/log"); + // Wipe Symfony cache: kernel.project_dir bakes the AppImage FUSE mount path + // (different every launch), so cache from a previous launch is always stale. + QDir(m_dataDir + "/var/cache").removeRecursively(); QDir().mkpath(m_dataDir + "/var/cache"); setToken(randomSecret(32));