fix(awooop): route ci notifications through event mirror
Some checks failed
Code Review / ai-code-review (push) Successful in 14s
CD Pipeline / tests (push) Successful in 1m18s
CD Pipeline / post-deploy-checks (push) Has been cancelled
CD Pipeline / build-and-deploy (push) Has been cancelled

This commit is contained in:
Your Name
2026-05-12 13:58:08 +08:00
parent d356cd32fc
commit ad8ead2546
11 changed files with 461 additions and 59 deletions

View File

@@ -1439,6 +1439,39 @@ class AlertmanagerPayload(BaseModel):
alerts: list[AlertmanagerAlert]
_CICD_JOB_STATUSES = frozenset({"running", "success", "failed", "pending"})
def _cicd_job_status_from_alert(alert: AlertmanagerAlert) -> str:
"""將 CI/CD Alertmanager label 轉成 TelegramGateway 支援的狀態。
2026-05-12 Codex: Gitea workflow 先送進 AWOOI API不能只靠
severity=info 推 success否則 failed/pending 事件進 AwoooP 後語義會失真。
"""
labels = alert.labels or {}
for key in ("status", "job_status", "ci_status"):
value = str(labels.get(key) or "").strip().lower()
if value in _CICD_JOB_STATUSES:
return value
severity = str(labels.get("severity") or "").strip().lower()
if severity == "info":
return "success"
if severity in {"critical", "error"}:
return "failed"
return "running"
def _cicd_duration_seconds_from_alert(alert: AlertmanagerAlert) -> int:
labels = alert.labels or {}
raw = labels.get("duration_seconds") or labels.get("duration") or 0
try:
value = int(str(raw).strip())
except (TypeError, ValueError):
return 0
return max(value, 0)
def is_internal_ip(client_ip: str) -> bool:
"""檢查是否為內網 IP"""
import ipaddress
@@ -2182,11 +2215,12 @@ async def alertmanager_webhook(
telegram = get_telegram_gateway()
# 解析 CI/CD 狀態
stage = alert.labels.get("stage", "")
job_status = "success" if alert.labels.get("severity") == "info" else "running"
job_status = _cicd_job_status_from_alert(alert)
commit_sha = alert.labels.get("commit", "")
triggered_by = alert.labels.get("triggered_by", "CI")
workflow_url = alert.annotations.get("workflow_url", "")
summary = alert.annotations.get("summary", alertname)
detail_message = alert.annotations.get("description", "")
await telegram.send_cicd_progress(
job_name=summary,
@@ -2194,6 +2228,8 @@ async def alertmanager_webhook(
stage=stage,
commit_sha=commit_sha,
triggered_by=triggered_by,
duration_seconds=_cicd_duration_seconds_from_alert(alert),
message=detail_message,
workflow_url=workflow_url,
)
@@ -2425,7 +2461,7 @@ async def alertmanager_webhook(
record_alert_chain_success("alertmanager")
return AlertResponse(
success=True,
message=f"✅ TYPE-1 純資訊告警已通知 (no LLM)",
message="✅ TYPE-1 純資訊告警已通知 (no LLM)",
alert_id=alert_id,
approval_created=False,
)

View File

@@ -43,7 +43,6 @@ from src.services.security_interceptor import (
get_security_interceptor,
)
from src.services.chat_manager import get_chat_manager
from src.services.notification_matrix import resolve_chat_ids # ADR-093 路由矩陣
# =============================================================================
# Snooze/Silence Redis Keys (2026-03-27 P1 優化)
@@ -996,12 +995,18 @@ class CICDProgressMessage:
safe_url = html.escape(self.workflow_url, quote=True)
workflow_link = f"\n🔗 <a href='{safe_url}'>Workflow</a>"
detail = ""
if self.message:
safe_message = html.escape(self.message[:240])
detail = f"\n📝 {safe_message}"
# 簡潔訊息
stage_label = f" | {safe_stage}" if safe_stage else ""
message = (
f"{status_emoji} <b>[AWOOOI CI/CD]</b>{stage_label}\n"
f"📦 {safe_job}{duration_str}"
f"{commit_info}"
f"{detail}"
f"{workflow_link}"
)
@@ -6168,7 +6173,7 @@ class TelegramGateway:
s = await k8s.get_pod_status_summary(namespace="awoooi-prod")
running, total = s.get("running", 0), s.get("total", 0)
problems = s.get("problem_pods", [])
lines = [f"<b>🖥 Cluster 狀態</b>", f"• Pods: {running}/{total} Running"]
lines = ["<b>🖥 Cluster 狀態</b>", f"• Pods: {running}/{total} Running"]
if problems:
lines.append(f"• 異常: {len(problems)}")
for p in problems[:5]: