mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-10-19 10:33:29 +00:00
Route mock alert cleanup through managed runtime
This commit is contained in:
parent
ec99ef6018
commit
9b9ee97f85
3 changed files with 142 additions and 5 deletions
|
|
@ -199,6 +199,11 @@ Makefile targets, `scripts/toggle-mock.sh`, and `scripts/clean-mock-alerts.sh` m
|
||||||
route through the managed runtime control plane when they are operating on the
|
route through the managed runtime control plane when they are operating on the
|
||||||
local dev stack, instead of resurrecting lane-local `hot-dev.sh` or raw Vite
|
local dev stack, instead of resurrecting lane-local `hot-dev.sh` or raw Vite
|
||||||
process management through separate shell folklore.
|
process management through separate shell folklore.
|
||||||
|
When `scripts/clean-mock-alerts.sh` needs to quiesce a local dev runtime, it
|
||||||
|
must stop the managed session through `hot-dev-bg` before touching legacy
|
||||||
|
compatibility services, and its operator recovery guidance must point back to
|
||||||
|
the canonical repo-root `npm run dev` and `npm run dev:foreground` controls
|
||||||
|
instead of treating `pulse-hot-dev` service management as the primary dev path.
|
||||||
That same rule now extends to the macOS auto-start surface. The launchd helper
|
That same rule now extends to the macOS auto-start surface. The launchd helper
|
||||||
may not boot a separate legacy foreground runtime beside the managed dev stack:
|
may not boot a separate legacy foreground runtime beside the managed dev stack:
|
||||||
`scripts/dev-launchd-wrapper.sh`, `scripts/dev-launchd-setup.sh`, and the
|
`scripts/dev-launchd-wrapper.sh`, `scripts/dev-launchd-setup.sh`, and the
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,9 @@ GREEN='\033[0;32m'
|
||||||
YELLOW='\033[1;33m'
|
YELLOW='\033[1;33m'
|
||||||
NC='\033[0m' # No Color
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
ALERT_HISTORY="/etc/pulse/alerts/alert-history.json"
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
|
HOT_DEV_BG_PATH="${HOT_DEV_BG_PATH:-${ROOT_DIR}/scripts/hot-dev-bg.sh}"
|
||||||
|
ALERT_HISTORY="${ALERT_HISTORY:-/etc/pulse/alerts/alert-history.json}"
|
||||||
|
|
||||||
if ! command -v jq >/dev/null 2>&1; then
|
if ! command -v jq >/dev/null 2>&1; then
|
||||||
echo -e "${RED}Error: jq is required but not installed${NC}"
|
echo -e "${RED}Error: jq is required but not installed${NC}"
|
||||||
|
|
@ -33,6 +35,16 @@ run_privileged() {
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
managed_runtime_running() {
|
||||||
|
if [ ! -x "$HOT_DEV_BG_PATH" ]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
local status_output
|
||||||
|
status_output="$("$HOT_DEV_BG_PATH" status 2>/dev/null || true)"
|
||||||
|
[[ "$status_output" == *"[hot-dev-bg] Running (pid:"* ]]
|
||||||
|
}
|
||||||
|
|
||||||
if [ ! -f "$ALERT_HISTORY" ]; then
|
if [ ! -f "$ALERT_HISTORY" ]; then
|
||||||
echo -e "${RED}Error: Alert history file not found at $ALERT_HISTORY${NC}"
|
echo -e "${RED}Error: Alert history file not found at $ALERT_HISTORY${NC}"
|
||||||
exit 1
|
exit 1
|
||||||
|
|
@ -57,7 +69,12 @@ echo -e "${GREEN}✓ Backup created: $BACKUP_FILE${NC}"
|
||||||
|
|
||||||
# Stop backend to prevent writes during cleanup
|
# Stop backend to prevent writes during cleanup
|
||||||
echo "Stopping backend..."
|
echo "Stopping backend..."
|
||||||
|
if managed_runtime_running; then
|
||||||
|
echo "Stopping managed development runtime..."
|
||||||
|
"$HOT_DEV_BG_PATH" stop
|
||||||
|
fi
|
||||||
pkill -x pulse 2>/dev/null || true
|
pkill -x pulse 2>/dev/null || true
|
||||||
|
# Legacy compatibility for service-based deployments that are not using the managed dev runtime.
|
||||||
run_privileged systemctl stop pulse-hot-dev 2>/dev/null || true
|
run_privileged systemctl stop pulse-hot-dev 2>/dev/null || true
|
||||||
run_privileged systemctl stop pulse 2>/dev/null || true
|
run_privileged systemctl stop pulse 2>/dev/null || true
|
||||||
run_privileged systemctl stop pulse-backend 2>/dev/null || true
|
run_privileged systemctl stop pulse-backend 2>/dev/null || true
|
||||||
|
|
@ -84,7 +101,7 @@ run_privileged chown pulse:pulse "$ALERT_HISTORY"
|
||||||
echo -e "${GREEN}✓ Mock alerts removed successfully${NC}"
|
echo -e "${GREEN}✓ Mock alerts removed successfully${NC}"
|
||||||
echo ""
|
echo ""
|
||||||
echo "To restart the backend, run:"
|
echo "To restart the backend, run:"
|
||||||
echo " npm run dev (managed development runtime)"
|
echo " (cd \"${ROOT_DIR}\" && npm run dev) (managed development runtime)"
|
||||||
echo " ./scripts/hot-dev.sh (foreground development escape hatch)"
|
echo " (cd \"${ROOT_DIR}\" && npm run dev:foreground) (foreground development escape hatch)"
|
||||||
echo " sudo systemctl start pulse (systemd)"
|
echo " sudo systemctl start pulse (systemd)"
|
||||||
echo " sudo systemctl start pulse-backend (legacy)"
|
echo " sudo systemctl start pulse-backend (legacy)"
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ set -euo pipefail
|
||||||
|
|
||||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||||
HOT_DEV_BG="${ROOT_DIR}/scripts/hot-dev-bg.sh"
|
HOT_DEV_BG="${ROOT_DIR}/scripts/hot-dev-bg.sh"
|
||||||
|
CLEAN_MOCK_ALERTS="${ROOT_DIR}/scripts/clean-mock-alerts.sh"
|
||||||
PACKAGE_JSON="${ROOT_DIR}/package.json"
|
PACKAGE_JSON="${ROOT_DIR}/package.json"
|
||||||
FRONTEND_PACKAGE_JSON="${ROOT_DIR}/frontend-modern/package.json"
|
FRONTEND_PACKAGE_JSON="${ROOT_DIR}/frontend-modern/package.json"
|
||||||
DEV_LAUNCHD_WRAPPER="${ROOT_DIR}/scripts/dev-launchd-wrapper.sh"
|
DEV_LAUNCHD_WRAPPER="${ROOT_DIR}/scripts/dev-launchd-wrapper.sh"
|
||||||
|
|
@ -251,6 +252,119 @@ PY
|
||||||
assert_contains "frontend package keeps explicit frontend-only escape hatch" "${output}" "dev:frontend-only=vite"
|
assert_contains "frontend package keeps explicit frontend-only escape hatch" "${output}" "dev:frontend-only=vite"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test_clean_mock_alerts_prefers_managed_runtime() {
|
||||||
|
local test_dir fake_bin alert_history fake_hot_dev_bg action_log output
|
||||||
|
test_dir="$(mktemp -d)"
|
||||||
|
temp_dirs+=("${test_dir}")
|
||||||
|
fake_bin="${test_dir}/bin"
|
||||||
|
mkdir -p "${fake_bin}"
|
||||||
|
action_log="${test_dir}/actions.log"
|
||||||
|
alert_history="${test_dir}/alert-history.json"
|
||||||
|
fake_hot_dev_bg="${test_dir}/hot-dev-bg.sh"
|
||||||
|
|
||||||
|
cat > "${alert_history}" <<'EOF'
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"alert": {
|
||||||
|
"resourceId": "mock-resource-1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alert": {
|
||||||
|
"resourceId": "real-resource-1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat > "${fake_hot_dev_bg}" <<'EOF'
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
printf 'hot-dev-bg %s\n' "$*" >> "${ACTION_LOG}"
|
||||||
|
case "${1:-}" in
|
||||||
|
status)
|
||||||
|
echo "[hot-dev-bg] Running (pid: 12345)"
|
||||||
|
;;
|
||||||
|
stop)
|
||||||
|
echo "[hot-dev-bg] Stopped"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "unexpected hot-dev-bg command: $*" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
EOF
|
||||||
|
chmod +x "${fake_hot_dev_bg}"
|
||||||
|
|
||||||
|
cat > "${fake_bin}/sudo" <<'EOF'
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
printf 'sudo %s\n' "$*" >> "${ACTION_LOG}"
|
||||||
|
exec "$@"
|
||||||
|
EOF
|
||||||
|
chmod +x "${fake_bin}/sudo"
|
||||||
|
|
||||||
|
cat > "${fake_bin}/systemctl" <<'EOF'
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
printf 'systemctl %s\n' "$*" >> "${ACTION_LOG}"
|
||||||
|
exit 0
|
||||||
|
EOF
|
||||||
|
chmod +x "${fake_bin}/systemctl"
|
||||||
|
|
||||||
|
cat > "${fake_bin}/chown" <<'EOF'
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
printf 'chown %s\n' "$*" >> "${ACTION_LOG}"
|
||||||
|
exit 0
|
||||||
|
EOF
|
||||||
|
chmod +x "${fake_bin}/chown"
|
||||||
|
|
||||||
|
cat > "${fake_bin}/pkill" <<'EOF'
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
printf 'pkill %s\n' "$*" >> "${ACTION_LOG}"
|
||||||
|
exit 0
|
||||||
|
EOF
|
||||||
|
chmod +x "${fake_bin}/pkill"
|
||||||
|
|
||||||
|
output="$(
|
||||||
|
PATH="${fake_bin}:$PATH" \
|
||||||
|
ACTION_LOG="${action_log}" \
|
||||||
|
ALERT_HISTORY="${alert_history}" \
|
||||||
|
HOT_DEV_BG_PATH="${fake_hot_dev_bg}" \
|
||||||
|
"${CLEAN_MOCK_ALERTS}"
|
||||||
|
)"
|
||||||
|
|
||||||
|
local actions
|
||||||
|
actions="$(cat "${action_log}")"
|
||||||
|
assert_contains "clean-mock-alerts checks managed runtime state" "${actions}" "hot-dev-bg status"
|
||||||
|
assert_contains "clean-mock-alerts stops managed runtime first" "${actions}" "hot-dev-bg stop"
|
||||||
|
assert_contains "clean-mock-alerts still stops compatibility services" "${actions}" "systemctl stop pulse-hot-dev"
|
||||||
|
assert_contains "clean-mock-alerts advertises managed restart" "${output}" "npm run dev"
|
||||||
|
assert_contains "clean-mock-alerts advertises foreground escape hatch" "${output}" "npm run dev:foreground"
|
||||||
|
|
||||||
|
local order_output
|
||||||
|
order_output="$(
|
||||||
|
ACTION_LOG_PATH="${action_log}" python3 - <<'PY'
|
||||||
|
import os
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
lines = Path(os.environ["ACTION_LOG_PATH"]).read_text(encoding="utf-8").splitlines()
|
||||||
|
stop_index = next(i for i, line in enumerate(lines) if line == "hot-dev-bg stop")
|
||||||
|
systemctl_index = next(i for i, line in enumerate(lines) if line == "systemctl stop pulse-hot-dev")
|
||||||
|
print(f"managed_before_systemctl={stop_index < systemctl_index}")
|
||||||
|
PY
|
||||||
|
)"
|
||||||
|
assert_contains "managed runtime stop precedes legacy service stop" "${order_output}" "managed_before_systemctl=True"
|
||||||
|
|
||||||
|
local cleaned_count mock_count
|
||||||
|
cleaned_count="$(jq 'length' "${alert_history}")"
|
||||||
|
mock_count="$(jq '[.[] | select((.alert.resourceId // "" | contains("mock")))] | length' "${alert_history}")"
|
||||||
|
assert_contains "clean-mock-alerts removes only mock alerts" "${cleaned_count}" "1"
|
||||||
|
assert_contains "clean-mock-alerts leaves no mock alerts" "${mock_count}" "0"
|
||||||
|
}
|
||||||
|
|
||||||
test_backend_restart_requires_managed_runtime() {
|
test_backend_restart_requires_managed_runtime() {
|
||||||
local frontend_port backend_port output
|
local frontend_port backend_port output
|
||||||
local state_dir
|
local state_dir
|
||||||
|
|
@ -330,6 +444,7 @@ main() {
|
||||||
test_launchd_wrapper_uses_managed_supervisor
|
test_launchd_wrapper_uses_managed_supervisor
|
||||||
test_root_package_exposes_managed_runtime_entrypoints
|
test_root_package_exposes_managed_runtime_entrypoints
|
||||||
test_frontend_package_exposes_managed_runtime_entrypoints
|
test_frontend_package_exposes_managed_runtime_entrypoints
|
||||||
|
test_clean_mock_alerts_prefers_managed_runtime
|
||||||
test_backend_restart_requires_managed_runtime
|
test_backend_restart_requires_managed_runtime
|
||||||
test_status_without_runtime
|
test_status_without_runtime
|
||||||
test_detects_unmanaged_listeners
|
test_detects_unmanaged_listeners
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue