feat: integrate ntfy.sh push notifications for supervisor

- Add NTFY_TOKEN support to send_alert() — sends Authorization header
  when token is set, backwards-compatible with plain webhook URLs
- Set ALERT_WEBHOOK_URL and NTFY_TOKEN in .env.prod.sops
- Add NTFY_TOKEN= placeholder in .env.dev.sops
- Topic: gWMeiHxj8ZqLbbqT (hard-to-guess, token-gated)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Deeman
2026-02-23 22:02:57 +01:00
parent ebba46f700
commit b5de3e0681
4 changed files with 121 additions and 109 deletions

View File

@@ -42,6 +42,7 @@ LANDING_DIR = Path(os.getenv("LANDING_DIR", "data/landing"))
DUCKDB_PATH = os.getenv("DUCKDB_PATH", "data/lakehouse.duckdb")
SERVING_DUCKDB_PATH = os.getenv("SERVING_DUCKDB_PATH", "analytics.duckdb")
ALERT_WEBHOOK_URL = os.getenv("ALERT_WEBHOOK_URL", "")
NTFY_TOKEN = os.getenv("NTFY_TOKEN", "")
WORKFLOWS_PATH = Path(os.getenv("WORKFLOWS_PATH", "infra/supervisor/workflows.toml"))
NAMED_SCHEDULES = {
@@ -282,15 +283,16 @@ def git_pull_and_sync() -> None:
# ---------------------------------------------------------------------------
def send_alert(message: str) -> None:
"""Send failure alert via webhook (ntfy.sh / Slack / Telegram)."""
"""Send alert via ntfy.sh (or any webhook accepting POST body)."""
if not ALERT_WEBHOOK_URL:
return
timestamp = datetime.now(UTC).strftime("%Y-%m-%d %H:%M UTC")
cmd = ["curl", "-s", "-d", f"[{timestamp}] {message}"]
if NTFY_TOKEN:
cmd += ["-H", f"Authorization: Bearer {NTFY_TOKEN}"]
cmd.append(ALERT_WEBHOOK_URL)
try:
subprocess.run(
["curl", "-s", "-d", f"[{timestamp}] {message}", ALERT_WEBHOOK_URL],
timeout=10, capture_output=True,
)
subprocess.run(cmd, timeout=10, capture_output=True)
except Exception:
logger.exception("Failed to send alert")