Some checks failed
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Failing after 2m6s
CD Pipeline / build-and-deploy (push) Has been skipped
CD Pipeline / post-deploy-checks (push) Has been skipped
101 lines
3.5 KiB
Bash
Executable File
101 lines
3.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
# 2026-07-02 Codex: Ops 通知只走 AWOOI Alertmanager 入口,讓 TelegramGateway
|
||
# 統一送出、鏡像到 AwoooP,並保留 DB/log receipt;禁止呼叫端再走 direct Bot API fallback。
|
||
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}"
|