139 lines
4.5 KiB
Python
Executable File
139 lines
4.5 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
|
|
"""
|
|
Mattermost Incoming Webhook 알림 송신 유틸리티 스크립트.
|
|
3인 연구팀의 협업 환경 및 빌드/테스트/실험 결과 전송용으로 사용됩니다.
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import json
|
|
import argparse
|
|
import urllib.request
|
|
from urllib.error import URLError, HTTPError
|
|
|
|
def load_env(env_path=".env"):
|
|
""".env 파일에서 환경 변수를 로드합니다."""
|
|
if os.path.exists(env_path):
|
|
with open(env_path, "r", encoding="utf-8") as f:
|
|
for line in f:
|
|
line = line.strip()
|
|
if not line or line.startswith("#"):
|
|
continue
|
|
if "=" in line:
|
|
key, value = line.split("=", 1)
|
|
os.environ[key.strip()] = value.strip().strip('"').strip("'")
|
|
|
|
def send_mattermost_message(webhook_url, text, username=None, icon_emoji=None, attachments=None):
|
|
"""
|
|
Mattermost Webhook으로 POST 요청을 보냅니다.
|
|
"""
|
|
payload = {
|
|
"text": text
|
|
}
|
|
if username:
|
|
payload["username"] = username
|
|
if icon_emoji:
|
|
payload["icon_emoji"] = icon_emoji
|
|
if attachments:
|
|
payload["attachments"] = attachments
|
|
|
|
data = json.dumps(payload).encode("utf-8")
|
|
req = urllib.request.Request(
|
|
webhook_url,
|
|
data=data,
|
|
headers={"Content-Type": "application/json"}
|
|
)
|
|
|
|
try:
|
|
with urllib.request.urlopen(req) as response:
|
|
if response.status in [200, 201]:
|
|
return True, "SUCCESS"
|
|
else:
|
|
return False, f"Unexpected response status: {response.status}"
|
|
except HTTPError as e:
|
|
return False, f"HTTP Error {e.code}: {e.reason}"
|
|
except URLError as e:
|
|
return False, f"URL Error: {e.reason}"
|
|
except Exception as e:
|
|
return False, f"General Error: {str(e)}"
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description="Mattermost webhook notification CLI utility.")
|
|
parser.add_argument("--message", "-m", required=True, help="송신할 메시지 본문 (Markdown 포맷 지원)")
|
|
parser.add_argument("--title", "-t", help="메시지 첨부 카드 제목")
|
|
parser.add_argument("--level", "-l", choices=["info", "warning", "error", "success"], default="info", help="알림 레벨")
|
|
parser.add_argument("--author", "-a", default="Multi-Agent-Backplane", help="송신자 이름")
|
|
parser.add_argument("--env", default=".env", help="환경 변수 파일 경로")
|
|
|
|
args = parser.parse_args()
|
|
|
|
# 환경 변수 로드
|
|
load_env(args.env)
|
|
|
|
webhook_url = os.environ.get("MATTERMOST_WEBHOOK_URL")
|
|
if not webhook_url:
|
|
print("[ERROR] MATTERMOST_WEBHOOK_URL 환경변수가 설정되지 않았습니다.", file=sys.stderr)
|
|
print("💡 로컬의 .env 파일에 'MATTERMOST_WEBHOOK_URL=웹훅주소' 형태로 추가하거나 셸 환경변수를 설정하십시오.", file=sys.stderr)
|
|
sys.exit(1)
|
|
|
|
# 알림 레벨별 색상 및 이모지 설정
|
|
colors = {
|
|
"info": "#2196F3", # Blue
|
|
"warning": "#FF9800", # Orange
|
|
"error": "#F44336", # Red
|
|
"success": "#4CAF50" # Green
|
|
}
|
|
emojis = {
|
|
"info": ":information_source:",
|
|
"warning": ":warning:",
|
|
"error": ":x:",
|
|
"success": ":white_check_mark:"
|
|
}
|
|
|
|
color = colors.get(args.level)
|
|
emoji = emojis.get(args.level)
|
|
|
|
username = f"{args.author} {emoji}"
|
|
|
|
attachments = None
|
|
if args.title:
|
|
attachments = [{
|
|
"fallback": f"[{args.level.upper()}] {args.title}",
|
|
"color": color,
|
|
"title": args.title,
|
|
"text": args.message,
|
|
"fields": [
|
|
{
|
|
"short": True,
|
|
"title": "Notification Level",
|
|
"value": args.level.upper()
|
|
},
|
|
{
|
|
"short": True,
|
|
"title": "Trigger Entity",
|
|
"value": args.author
|
|
}
|
|
]
|
|
}]
|
|
text = "" # attachments가 있으면 본문 텍스트는 비우거나 제목으로 대체
|
|
else:
|
|
text = f"{args.message}"
|
|
|
|
success, msg = send_mattermost_message(
|
|
webhook_url=webhook_url,
|
|
text=text,
|
|
username=username,
|
|
attachments=attachments
|
|
)
|
|
|
|
if success:
|
|
print("[SUCCESS] Mattermost 알림 전송 완료.")
|
|
else:
|
|
print(f"[ERROR] Mattermost 알림 전송 실패: {msg}", file=sys.stderr)
|
|
sys.exit(2)
|
|
|
|
if __name__ == "__main__":
|
|
main()
|