#!/usr/bin/env python3 """发送 CI 失败通知到飞书/项目群 webhook。""" import json import os import sys import urllib.request def main() -> int: webhook = os.environ.get("CI_NOTIFY_WEBHOOK", "") if not webhook: print("未配置 CI_NOTIFY_WEBHOOK,跳过通知") print("如需启用,请在仓库 Settings -> Secrets and variables -> Actions 中添加 CI_NOTIFY_WEBHOOK") return 0 failed_job = os.environ.get("FAILED_JOB", "Unknown Job") branch = os.environ.get("GITHUB_REF_NAME", "unknown") commit = os.environ.get("GITHUB_SHA", "unknown")[:8] actor = os.environ.get("GITHUB_ACTOR", "unknown") run_id = os.environ.get("GITHUB_RUN_ID", "unknown") repo = os.environ.get("GITHUB_REPOSITORY", "unknown") run_url = f"https://git.xiaoxiajianji.com/{repo}/actions/runs/{run_id}" payload = { "msg_type": "interactive", "card": { "header": { "title": { "tag": "plain_text", "content": "❌ CI 构建失败", }, "status": "red", }, "elements": [ { "tag": "div", "text": { "tag": "lark_md", "content": ( f"**任务**: {failed_job}\n" f"**分支**: {branch}\n" f"**提交**: {commit}\n" f"**提交者**: {actor}\n" f"**Run ID**: {run_id}" ), }, }, { "tag": "action", "actions": [ { "tag": "button", "text": {"tag": "plain_text", "content": "查看失败日志"}, "url": run_url, "type": "danger", } ], }, ], }, } data = json.dumps(payload).encode("utf-8") req = urllib.request.Request( webhook, data=data, headers={"Content-Type": "application/json"}, method="POST", ) try: with urllib.request.urlopen(req, timeout=10) as resp: resp.read() print("通知已发送") except Exception as e: print(f"通知发送失败: {e}", file=sys.stderr) return 1 return 0 if __name__ == "__main__": sys.exit(main())