From f8169810dcb1f6e00f87d830f79ea92b35b7d02c Mon Sep 17 00:00:00 2001 From: h Date: Sun, 30 Aug 2026 18:09:25 +0200 Subject: [PATCH] fix(alerts): state changes are one-shot, icon by target state --- src/healthbot/alerts.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/healthbot/alerts.py b/src/healthbot/alerts.py index b9be185..595dab5 100644 --- a/src/healthbot/alerts.py +++ b/src/healthbot/alerts.py @@ -18,15 +18,16 @@ INFORMATIONAL = frozenset( ) FAILURE = frozenset( - { - "ProcedureFailed", - "ActionFailed", - "BuildFailed", - "RepoBuildFailed", - } + {"ProcedureFailed", "ActionFailed", "BuildFailed", "RepoBuildFailed"} ) -ONE_SHOT = INFORMATIONAL | FAILURE +# Komodo создаёт их сразу с resolved=true (resolved_ts == ts): это факт +# «состояние сменилось», а не тревога, которую потом снимают. Без этого +# и running → unhealthy, и unhealthy → running приходили как «Отбой». +STATE_CHANGE = frozenset({"StackStateChange", "ContainerStateChange"}) +HEALTHY_STATES = frozenset({"running", "healthy"}) + +ONE_SHOT = INFORMATIONAL | FAILURE | STATE_CHANGE def _gb(value: Any) -> str: # noqa: ANN401 @@ -121,6 +122,9 @@ def format_alert(payload: dict) -> str: icon = "ℹ️" elif resolved: icon = "✅" + elif kind in STATE_CHANGE: + to = str((inner or {}).get("to", "")).lower() if isinstance(inner, dict) else "" + icon = "✅" if to in HEALTHY_STATES else LEVEL_ICON.get(level, "🟠") else: icon = LEVEL_ICON.get(level, "🔔")