From 4c95f0541f2c868d5458a6b986f513ff1f1a2c1c Mon Sep 17 00:00:00 2001 From: Robin Ebers Date: Fri, 10 Jul 2026 04:58:11 +0400 Subject: [PATCH] build: stabilize dev app lifecycle checks --- docs/debugging.md | 12 +++++++++--- script/build_and_run.sh | 34 +++++++++++++++++++++++++++++----- 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/docs/debugging.md b/docs/debugging.md index 1e7c3bc9b..8e25e530c 100644 --- a/docs/debugging.md +++ b/docs/debugging.md @@ -13,10 +13,16 @@ The project script owns the build/run loop. From the repo root: ./script/build_and_run.sh verify # launch and confirm the process is running ``` +Every invocation asks any running `OpenUsage` process to exit and waits up to five seconds before +rebuilding. `verify` also polls the new launch for up to five seconds. The script fails loudly if either +lifecycle transition stalls. + The script builds a signed app bundle under `dist/` and launches it in place — nothing is installed to -`/Applications`. The dev build uses its own bundle id (`com.robinebers.openusage.dev`), so it keeps its -own settings and keychain and never disturbs a released OpenUsage. It ships no update feed, so it never -checks for updates — test updates with a real signed, notarized release build. +`/Applications`. The dev build uses its own bundle id (`com.robinebers.openusage.dev`), so its app +preferences and single-instance state stay separate from the released bundle. Provider credential +files, databases, keychain items, and OpenUsage API-key files remain shared intentionally, so +authentication changes can affect provider tools or a released OpenUsage. The dev build ships no +update feed; test updates with a real signed, notarized release build. ## Stream logs diff --git a/script/build_and_run.sh b/script/build_and_run.sh index 871012cc0..11947eec4 100755 --- a/script/build_and_run.sh +++ b/script/build_and_run.sh @@ -5,8 +5,9 @@ set -euo pipefail # to /Applications. The dev build: # - is signed with a stable Apple Development identity, so keychain/permission grants stick across # rebuilds (macOS keys those to the signing identity + bundle id, not the install location); -# - uses its own bundle id (com.robinebers.openusage.dev), so it never touches the real installed -# app's settings or keychain. To run against the real app's data instead, set BUNDLE_ID to +# - uses its own bundle id (com.robinebers.openusage.dev), isolating app preferences and +# single-instance state. Provider credential files, databases, and keychain items remain shared +# intentionally. To test the release app's settings domain, set BUNDLE_ID to # com.robinebers.openusage below; # - ships no Sparkle feed, so it never checks for or installs updates (test updates with a real # signed + notarized release build — that's the only honest way). @@ -36,7 +37,31 @@ INFO_PLIST="$APP_CONTENTS/Info.plist" RESOURCE_BUNDLE_NAME="${TARGET_NAME}_${TARGET_NAME}.bundle" ENTITLEMENTS="$ROOT_DIR/script/OpenUsage.dev.entitlements.plist" -pkill -x "$TARGET_NAME" >/dev/null 2>&1 || true +wait_for_app_exit() { + pkill -x "$TARGET_NAME" >/dev/null 2>&1 || return 0 + for ((attempt = 0; attempt < 50; attempt++)); do + if ! pgrep -x "$TARGET_NAME" >/dev/null; then + return 0 + fi + sleep 0.1 + done + echo "timed out waiting for the previous $APP_DISPLAY process to exit" >&2 + return 1 +} + +wait_for_app_launch() { + for ((attempt = 0; attempt < 50; attempt++)); do + if pgrep -x "$TARGET_NAME" >/dev/null; then + echo "==> running" + return 0 + fi + sleep 0.1 + done + echo "$APP_DISPLAY exited before launch verification completed" >&2 + return 1 +} + +wait_for_app_exit echo "==> swift build ($CONFIG)" swift build -c "$CONFIG" @@ -177,8 +202,7 @@ case "$MODE" in ;; verify) launch_app - sleep 1 - pgrep -x "$TARGET_NAME" >/dev/null && echo "==> running" + wait_for_app_launch ;; *) echo "usage: $0 [run|build|logs|verify]" >&2