Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions scripts/install
Original file line number Diff line number Diff line change
Expand Up @@ -387,9 +387,16 @@ if payload.get("runtime_matches") is not True:
if (( BACKEND_ONLY )); then
printf '%s\n' "backend-only" > "$INSTALL_ROOT/INSTALL_MODE"
else
curl -fsS --max-time 5 "$MENUBAR_URL" \
| python3 -c 'import json, sys; json.load(sys.stdin)' \
|| fail "the menu bar endpoint did not return valid JSON."
# A ready index does not guarantee that the first menu-bar projection is
# cheap. Allow the same bounded startup window for this separate request.
progress_start "Checking the menu bar endpoint" "Still checking the menu bar endpoint…"
if ! menubar_json="$(curl -fsS --max-time "$READINESS_TIMEOUT_SECONDS" "$MENUBAR_URL" 2>/dev/null)"; then
fail "the menu bar endpoint did not respond within ${READINESS_TIMEOUT_SECONDS}s or returned an HTTP error."
fi
if ! printf '%s' "$menubar_json" | python3 -c 'import json, sys; json.load(sys.stdin)' 2>/dev/null; then
fail "the menu bar endpoint did not return valid JSON."
fi
progress_done "Menu bar endpoint ready"
if [[ -n "$MENUBAR_BUILD_PID" ]]; then
echo "Finishing the menu bar companion…"
else
Expand Down
12 changes: 9 additions & 3 deletions scripts/install-linux
Original file line number Diff line number Diff line change
Expand Up @@ -296,9 +296,15 @@ else
[[ "$tray_fragment" == "${XDG_CONFIG_HOME:-$HOME/.config}/systemd/user/token-meter-tray.service" ]] \
|| fail "a different unit owns token-meter-tray.service."

curl -fsS --max-time 5 "$MENUBAR_URL" \
| python3 -c 'import json, sys; json.load(sys.stdin)' \
|| fail "the menu bar endpoint did not return valid JSON."
# Index readiness does not bound the time to build the first tray payload.
progress_start "Checking the menu bar endpoint" "Still checking the menu bar endpoint…"
if ! menubar_json="$(curl -fsS --max-time "$READINESS_TIMEOUT_SECONDS" "$MENUBAR_URL" 2>/dev/null)"; then
fail "the menu bar endpoint did not respond within ${READINESS_TIMEOUT_SECONDS}s or returned an HTTP error."
fi
if ! printf '%s' "$menubar_json" | python3 -c 'import json, sys; json.load(sys.stdin)' 2>/dev/null; then
fail "the menu bar endpoint did not return valid JSON."
fi
progress_done "Menu bar endpoint ready"
printf '%s\n' "full" > "$INSTALL_ROOT/INSTALL_MODE"
fi

Expand Down
86 changes: 86 additions & 0 deletions tests/test_installer_modes.py
Original file line number Diff line number Diff line change
Expand Up @@ -924,6 +924,92 @@ def test_macos_default_install_keeps_the_native_companion(self):
),
)

def test_macos_install_waits_for_slow_menubar_response(self):
with tempfile.TemporaryDirectory() as tmp:
workspace = Path(tmp)
env, install_root, _ = self.installer_environment(workspace, "Darwin")
env.pop("BASH_ENV")
env["TOKEN_METER_READINESS_TIMEOUT_SECONDS"] = "12"
self.write_executable(
workspace / "bin" / "curl",
"""#!/usr/bin/env bash
if [[ "${*: -1}" == */health ]]; then
owned=false; [[ "$*" == *"runtime=$(cd "$TEST_INSTALL_ROOT" 2>/dev/null && pwd -P)"* ]] && owned=true
printf '{"ok": true, "state_ready": true, "runtime_matches": %s}\n' "$owned"
else
timeout=0
while (($#)); do
if [[ "$1" == --max-time ]]; then timeout="$2"; shift; fi
shift
done
if (( timeout <= 5 )); then exit 28; fi
sleep 6
printf '{"ok": true}\n'
fi
""",
)
result = subprocess.run(
["bash", str(ROOT / "scripts" / "install")],
capture_output=True, text=True, env=env, timeout=30,
)
self.assertEqual(result.returncode, 0, result.stderr)
self.assertEqual((install_root / "INSTALL_MODE").read_text(), "full\n")

def test_linux_install_waits_for_slow_menubar_response(self):
with tempfile.TemporaryDirectory() as tmp:
workspace = Path(tmp)
env, install_root, _ = self.installer_environment(workspace, "Linux")
env["TOKEN_METER_READINESS_TIMEOUT_SECONDS"] = "12"
self.write_executable(
workspace / "bin" / "curl",
"""#!/usr/bin/env bash
if [[ "${*: -1}" == */health ]]; then
owned=false; [[ "$*" == *"runtime=$(cd "$TEST_INSTALL_ROOT" 2>/dev/null && pwd -P)"* ]] && owned=true
printf '{"ok": true, "state_ready": true, "runtime_matches": %s}\n' "$owned"
else
timeout=0
while (($#)); do
if [[ "$1" == --max-time ]]; then timeout="$2"; shift; fi
shift
done
if (( timeout <= 5 )); then exit 28; fi
sleep 6
printf '{"ok": true}\n'
fi
""",
)
result = subprocess.run(
["bash", str(ROOT / "scripts" / "install")],
capture_output=True, text=True, env=env, timeout=30,
)
self.assertEqual(result.returncode, 0, result.stderr)
self.assertEqual((install_root / "INSTALL_MODE").read_text(), "full\n")

def test_macos_install_rejects_invalid_menubar_json_without_traceback(self):
with tempfile.TemporaryDirectory() as tmp:
workspace = Path(tmp)
env, install_root, _ = self.installer_environment(workspace, "Darwin")
env.pop("BASH_ENV")
self.write_executable(
workspace / "bin" / "curl",
"""#!/usr/bin/env bash
if [[ "${*: -1}" == */health ]]; then
owned=false; [[ "$*" == *"runtime=$(cd "$TEST_INSTALL_ROOT" 2>/dev/null && pwd -P)"* ]] && owned=true
printf '{"ok": true, "state_ready": true, "runtime_matches": %s}\n' "$owned"
else
printf 'invalid json\n'
fi
""",
)
result = subprocess.run(
["bash", str(ROOT / "scripts" / "install")],
capture_output=True, text=True, env=env, timeout=30,
)
self.assertNotEqual(result.returncode, 0)
self.assertIn("menu bar endpoint did not return valid JSON", result.stderr)
self.assertNotIn("Traceback", result.stderr)
self.assertFalse((install_root / "INSTALL_MODE").exists())

def test_linux_default_install_keeps_the_tray_companion(self):
with tempfile.TemporaryDirectory() as tmp:
workspace = Path(tmp)
Expand Down
Loading