#!/usr/bin/env bash # 2026-05-12 Codex: Ops 通知先走 AWOOI Alertmanager 入口,讓 TelegramGateway # 統一送出並鏡像到 AwoooP。呼叫端保留直接 Telegram fallback 作為 API 離線備援。 set -euo pipefail API_BASE="${AWOOOI_API_URL:-https://awoooi.wooo.work}" ALERTMANAGER_URL="${AWOOOI_ALERTMANAGER_URL:-${API_BASE%/}/api/v1/webhooks/alertmanager}" JOB_NAME="${AWOOI_OPS_JOB_NAME:-${AWOOOI_OPS_JOB_NAME:-Ops Job}}" STATUS_RAW="${AWOOI_OPS_STATUS:-${AWOOOI_OPS_STATUS:-success}}" SEVERITY="${AWOOI_OPS_SEVERITY:-${AWOOOI_OPS_SEVERITY:-info}}" ALERTNAME="${AWOOI_OPS_ALERTNAME:-${AWOOOI_OPS_ALERTNAME:-OpsJobStatus}}" SOURCE="${AWOOI_OPS_SOURCE:-${AWOOOI_OPS_SOURCE:-ops-script}}" HOSTNAME_VALUE="${AWOOI_OPS_HOST:-${AWOOOI_OPS_HOST:-$(hostname 2>/dev/null || echo unknown)}}" COMPONENT="${AWOOI_OPS_COMPONENT:-${AWOOOI_OPS_COMPONENT:-ops}}" SUMMARY="${AWOOI_OPS_SUMMARY:-${AWOOOI_OPS_SUMMARY:-${JOB_NAME}}}" DETAIL="${AWOOI_OPS_DETAIL:-${AWOOOI_OPS_DETAIL:-}}" DURATION_SECONDS="${AWOOI_OPS_DURATION_SECONDS:-${AWOOOI_OPS_DURATION_SECONDS:-0}}" if ! command -v python3 >/dev/null 2>&1; then echo "python3 missing; cannot build Alertmanager JSON payload" >&2 exit 2 fi payload_file="$(mktemp)" trap 'rm -f "$payload_file"' EXIT JOB_NAME="$JOB_NAME" \ STATUS_RAW="$STATUS_RAW" \ SEVERITY="$SEVERITY" \ ALERTNAME="$ALERTNAME" \ SOURCE="$SOURCE" \ HOSTNAME_VALUE="$HOSTNAME_VALUE" \ COMPONENT="$COMPONENT" \ SUMMARY="$SUMMARY" \ DETAIL="$DETAIL" \ DURATION_SECONDS="$DURATION_SECONDS" \ python3 - <<'PY' > "$payload_file" from __future__ import annotations import datetime as dt import json import os import re status = (os.environ.get("STATUS_RAW") or "success").strip().lower() if status not in {"success", "failed", "warning", "running", "skipped"}: status = "warning" severity = (os.environ.get("SEVERITY") or "info").strip().lower() if severity not in {"info", "warning", "critical"}: severity = "info" alertname = (os.environ.get("ALERTNAME") or "OpsJobStatus").strip() safe_alertname = re.sub(r"[^A-Za-z0-9_.:-]+", "_", alertname).strip("_") or "OpsJobStatus" payload = { "version": "4", "status": "firing", "receiver": "awoooi-ops", "groupLabels": {"alertname": safe_alertname}, "commonLabels": {"alertname": safe_alertname, "severity": severity}, "commonAnnotations": {}, "alerts": [ { "status": "firing", "labels": { "alertname": safe_alertname, "severity": severity, "status": status, "source": os.environ.get("SOURCE", "ops-script"), "job": os.environ.get("JOB_NAME", "Ops Job"), "host": os.environ.get("HOSTNAME_VALUE", "unknown"), "component": os.environ.get("COMPONENT", "ops"), "duration_seconds": os.environ.get("DURATION_SECONDS", "0"), }, "annotations": { "summary": os.environ.get("SUMMARY", ""), "description": os.environ.get("DETAIL", ""), }, "startsAt": dt.datetime.now(dt.timezone.utc).isoformat().replace("+00:00", "Z"), } ], } print(json.dumps(payload, ensure_ascii=False)) PY if [ "${AWOOI_OPS_DRY_RUN:-${AWOOOI_OPS_DRY_RUN:-0}}" = "1" ]; then cat "$payload_file" exit 0 fi curl -fsS \ --connect-timeout "${AWOOI_OPS_CONNECT_TIMEOUT:-5}" \ --max-time "${AWOOI_OPS_MAX_TIME:-12}" \ -H "Content-Type: application/json" \ --data-binary "@${payload_file}" \ "$ALERTMANAGER_URL" >/dev/null echo "AwoooP-mirrored ops notification sent via ${ALERTMANAGER_URL}"