mirror of
https://github.com/gadgethd/ukmesh.git
synced 2026-10-15 18:50:05 +00:00
* test(viewshed): inject post-commit side-effect failures * fix(deploy): rollback on unhealthy or mismatched sites * fix(alerts): persist forwarding queue across restarts * perf(stats): add per-network aggregate cutover controls * docs: add Mission C5d handoff * test(viewshed): correct side-effect marker cursor row sets * fix(alerts): keep archive-only receiver live --------- Co-authored-by: gadgethd <111318106+gadgethd@users.noreply.github.com>
71 lines
2.6 KiB
Bash
Executable File
71 lines
2.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
repo_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
tmp_dir="$(mktemp -d "${repo_dir}/.test-alert-receiver.XXXXXX")"
|
|
port="$((18080 + ($$ % 1000)))"
|
|
receiver_pid=""
|
|
|
|
cleanup() {
|
|
if [ -n "$receiver_pid" ]; then
|
|
kill "$receiver_pid" >/dev/null 2>&1 || true
|
|
wait "$receiver_pid" >/dev/null 2>&1 || true
|
|
fi
|
|
rm -rf "$tmp_dir"
|
|
}
|
|
trap cleanup EXIT
|
|
|
|
(
|
|
cd "$repo_dir/backend"
|
|
ALERT_RECEIVER_PORT="$port" \
|
|
ALERT_RECEIVER_PATH="$tmp_dir/alerts.jsonl" \
|
|
node --import tsx src/workers/alert-receiver.ts
|
|
) >"$tmp_dir/receiver.log" 2>&1 &
|
|
receiver_pid="$!"
|
|
|
|
for _ in $(seq 1 40); do
|
|
if curl --silent "http://127.0.0.1:${port}/healthz" >/dev/null; then
|
|
break
|
|
fi
|
|
sleep 0.25
|
|
done
|
|
health_code="$(curl --silent --output "$tmp_dir/health.json" --write-out '%{http_code}' "http://127.0.0.1:${port}/healthz")"
|
|
test "$health_code" = 200
|
|
node -e '
|
|
const health = JSON.parse(require("fs").readFileSync(process.argv[1], "utf8"));
|
|
if (health.status !== "degraded" || !health.detail.includes("archive-only")) {
|
|
throw new Error(`unexpected archive-only liveness response: ${JSON.stringify(health)}`);
|
|
}
|
|
' "$tmp_dir/health.json"
|
|
ready_code="$(curl --silent --output "$tmp_dir/ready.json" --write-out '%{http_code}' "http://127.0.0.1:${port}/readyz")"
|
|
test "$ready_code" = 503
|
|
node -e '
|
|
const ready = JSON.parse(require("fs").readFileSync(process.argv[1], "utf8"));
|
|
if (ready.status !== "degraded" || !ready.detail.includes("archive-only")) {
|
|
throw new Error(`unexpected archive-only readiness response: ${JSON.stringify(ready)}`);
|
|
}
|
|
' "$tmp_dir/ready.json"
|
|
|
|
curl --fail --silent \
|
|
-H 'content-type: application/json' \
|
|
--data '{"kind":"alert","service":"meshcore-analytics","check":"dependency_readiness","detail":"test"}' \
|
|
"http://127.0.0.1:${port}/alerts" >/dev/null
|
|
curl --fail --silent \
|
|
-H 'content-type: application/json' \
|
|
--data '{"kind":"recovery","service":"meshcore-analytics","check":"dependency_readiness","detail":"test"}' \
|
|
"http://127.0.0.1:${port}/alerts" >/dev/null
|
|
|
|
node -e '
|
|
const fs = require("fs");
|
|
const records = fs.readFileSync(process.argv[1], "utf8").trim().split("\n").map(JSON.parse);
|
|
if (records.length !== 2) throw new Error(`expected two receipts, got ${records.length}`);
|
|
if (records[0].status !== "firing" || records[1].status !== "recovery") {
|
|
throw new Error(`unexpected receipt states: ${records.map((r) => r.status).join(",")}`);
|
|
}
|
|
if (JSON.stringify(records).includes("\"detail\"")) {
|
|
throw new Error("receipt persisted unbounded alert detail");
|
|
}
|
|
' "$tmp_dir/alerts.jsonl"
|
|
|
|
echo "Synthetic firing and recovery reached the bounded test receiver."
|