Ajouter le dispatcher e-mail des alertes CI
This commit is contained in:
9
ops/ci-alert-email-dispatch.path
Normal file
9
ops/ci-alert-email-dispatch.path
Normal file
@@ -0,0 +1,9 @@
|
||||
[Unit]
|
||||
Description=Surveille la file des alertes CI Santinova
|
||||
|
||||
[Path]
|
||||
PathChanged=/opt/manus-deploy/secrets/ci-alerts/outbox
|
||||
Unit=ci-alert-email-dispatch.service
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
49
ops/ci-alert-email-dispatch.py
Normal file
49
ops/ci-alert-email-dispatch.py
Normal file
@@ -0,0 +1,49 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Expédie les alertes CI mises en file par le dashboard depuis l’hôte de recette."""
|
||||
|
||||
import json
|
||||
import subprocess
|
||||
import sys
|
||||
from email.message import EmailMessage
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
OUTBOX = Path("/opt/manus-deploy/secrets/ci-alerts/outbox")
|
||||
ARCHIVE = Path("/var/log/manus-deploy/ci-alerts-email-sent.json")
|
||||
|
||||
|
||||
def send_alert(file_path: Path) -> None:
|
||||
payload = json.loads(file_path.read_text(encoding="utf-8"))
|
||||
recipient = str(payload.get("to", "")).strip()
|
||||
subject = str(payload.get("subject", "")).strip()
|
||||
text = str(payload.get("text", "")).strip()
|
||||
if not recipient or "@" not in recipient or not subject or not text:
|
||||
raise ValueError(f"Alerte CI invalide : {file_path.name}")
|
||||
message = EmailMessage()
|
||||
message["To"] = recipient
|
||||
message["From"] = "alertes-ci@itinova.org"
|
||||
message["Subject"] = subject
|
||||
message.set_content(text)
|
||||
subprocess.run(["/usr/sbin/sendmail", "-t", "-oi"], input=message.as_bytes(), check=True, timeout=30)
|
||||
ARCHIVE.parent.mkdir(parents=True, exist_ok=True)
|
||||
ARCHIVE.write_text(json.dumps({"id": payload.get("id"), "sentAt": payload.get("createdAt")}) + "\n", encoding="utf-8")
|
||||
file_path.unlink()
|
||||
|
||||
|
||||
def main() -> int:
|
||||
OUTBOX.mkdir(parents=True, exist_ok=True, mode=0o700)
|
||||
failures = []
|
||||
for file_path in sorted(OUTBOX.glob("*.json")):
|
||||
try:
|
||||
send_alert(file_path)
|
||||
except Exception as error: # Le fichier reste en file pour réessai et investigation.
|
||||
print(f"CI_EMAIL_DISPATCH_FAILED {file_path.name}: {error}", file=sys.stderr)
|
||||
failures.append(file_path.name)
|
||||
if failures:
|
||||
return 1
|
||||
print("CI_EMAIL_DISPATCH_OK")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
8
ops/ci-alert-email-dispatch.service
Normal file
8
ops/ci-alert-email-dispatch.service
Normal file
@@ -0,0 +1,8 @@
|
||||
[Unit]
|
||||
Description=Envoi hôte des alertes CI Santinova vers le DSI
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/opt/manus-deploy/scripts/ci-alert-email-dispatch.py
|
||||
13
ops/install-ci-alert-email-dispatch.sh
Normal file
13
ops/install-ci-alert-email-dispatch.sh
Normal file
@@ -0,0 +1,13 @@
|
||||
#!/usr/bin/env bash
|
||||
set -Eeuo pipefail
|
||||
|
||||
readonly APP_DIR="${DASHBOARD_APP_DIR:-/opt/manus-deploy/apps/manus-dashboard}"
|
||||
readonly SCRIPT_DIR="/opt/manus-deploy/scripts"
|
||||
readonly OUTBOX_DIR="/opt/manus-deploy/secrets/ci-alerts/outbox"
|
||||
|
||||
install -d -m 0700 "${OUTBOX_DIR}"
|
||||
install -m 0700 "${APP_DIR}/ops/ci-alert-email-dispatch.py" "${SCRIPT_DIR}/ci-alert-email-dispatch.py"
|
||||
install -m 0644 "${APP_DIR}/ops/ci-alert-email-dispatch.service" /etc/systemd/system/ci-alert-email-dispatch.service
|
||||
install -m 0644 "${APP_DIR}/ops/ci-alert-email-dispatch.path" /etc/systemd/system/ci-alert-email-dispatch.path
|
||||
systemctl daemon-reload
|
||||
systemctl enable --now ci-alert-email-dispatch.path
|
||||
Reference in New Issue
Block a user