diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml index ff9b24e..bc448a4 100644 --- a/.github/workflows/docker-build.yml +++ b/.github/workflows/docker-build.yml @@ -65,3 +65,60 @@ jobs: GITHUB_REPO_URL=https://github.com/WrBug/PolyHermes cache-from: type=registry,ref=wrbug/polyhermes:latest cache-to: type=inline + + - name: Send Telegram notification + env: + TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }} + TELEGRAM_CHAT_ID: ${{ secrets.TELEGRAM_CHAT_ID }} + run: | + # 检查必要的环境变量 + if [ -z "$TELEGRAM_BOT_TOKEN" ] || [ -z "$TELEGRAM_CHAT_ID" ]; then + echo "⚠️ Telegram Bot Token 或 Chat ID 未配置,跳过通知" + exit 0 + fi + + # 获取构建信息 + VERSION="${{ steps.extract_version.outputs.VERSION }}" + TAG="${{ steps.extract_version.outputs.TAG }}" + RELEASE_NAME="${{ github.event.release.name }}" + RELEASE_URL="${{ github.event.release.html_url }}" + REPO_NAME="${{ github.repository }}" + + # 构建消息内容(使用 HTML 格式) + MESSAGE="✅ Docker 镜像构建成功 + +📦 版本: ${VERSION} +🏷️ Tag: ${TAG} +🔗 Release: 查看 Release +🐳 Docker 镜像: wrbug/polyhermes:${TAG}" + + # 添加 Release 名称(如果有) + if [ -n "$RELEASE_NAME" ] && [ "$RELEASE_NAME" != "null" ] && [ "$RELEASE_NAME" != "" ]; then + RELEASE_NAME_ESCAPED=$(echo "$RELEASE_NAME" | sed 's/&/\&/g' | sed 's//\>/g') + MESSAGE="${MESSAGE} +📝 Release 名称: ${RELEASE_NAME_ESCAPED}" + fi + + # 发送 Telegram 消息(使用 jq 转义 JSON) + curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \ + -H "Content-Type: application/json" \ + -d "$(jq -n \ + --arg chat_id "$TELEGRAM_CHAT_ID" \ + --arg text "$MESSAGE" \ + '{chat_id: $chat_id, text: $text, parse_mode: "HTML", disable_web_page_preview: false}')" > /tmp/telegram_response.json + + # 检查发送结果 + if [ $? -eq 0 ]; then + RESPONSE=$(cat /tmp/telegram_response.json) + if echo "$RESPONSE" | grep -q '"ok":true'; then + echo "✅ Telegram 通知发送成功" + else + echo "❌ Telegram 通知发送失败: $RESPONSE" + # 构建成功,通知失败不应该导致整个 job 失败 + exit 0 + fi + else + echo "❌ 发送 Telegram 消息时发生错误" + # 构建成功,通知失败不应该导致整个 job 失败 + exit 0 + fi \ No newline at end of file diff --git a/.github/workflows/telegram-notify.yml b/.github/workflows/telegram-notify.yml new file mode 100644 index 0000000..5af1259 --- /dev/null +++ b/.github/workflows/telegram-notify.yml @@ -0,0 +1,156 @@ +name: Telegram Notification on PR Merge + +on: + pull_request: + types: + - closed # 当 PR 被关闭(合并或关闭)时触发 + +jobs: + notify: + runs-on: ubuntu-latest + + # 只在 PR 被合并到 main 分支时执行 + if: github.event.pull_request.merged == true && github.event.pull_request.base.ref == 'main' + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Get PR details + id: pr_details + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + PR_NUMBER="${{ github.event.pull_request.number }}" + REPO="${{ github.repository }}" + + # 获取 PR 详细信息 + PR_RESPONSE=$(curl -s -H "Authorization: token ${GITHUB_TOKEN}" \ + -H "Accept: application/vnd.github.v3+json" \ + "https://api.github.com/repos/${REPO}/pulls/${PR_NUMBER}") + + # 获取 PR 变更的文件列表 + FILES_RESPONSE=$(curl -s -H "Authorization: token ${GITHUB_TOKEN}" \ + -H "Accept: application/vnd.github.v3+json" \ + "https://api.github.com/repos/${REPO}/pulls/${PR_NUMBER}/files") + + # 提取 PR 描述(body),保留换行,限制长度 + PR_BODY=$(echo "$PR_RESPONSE" | jq -r '.body // ""') + if [ ${#PR_BODY} -gt 500 ]; then + PR_BODY="${PR_BODY:0:500}..." + fi + + # 保存到输出变量(使用 base64 编码避免特殊字符问题) + echo "pr_body<> $GITHUB_OUTPUT + echo "$PR_BODY" >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + + - name: Send Telegram notification + env: + TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }} + TELEGRAM_CHAT_ID: ${{ secrets.TELEGRAM_CHAT_ID }} + run: | + # 检查必要的环境变量 + # 注意:TELEGRAM_CHAT_ID 可以是个人聊天 ID(正数)或群组 ID(负数,如 -1001234567890) + if [ -z "$TELEGRAM_BOT_TOKEN" ] || [ -z "$TELEGRAM_CHAT_ID" ]; then + echo "⚠️ Telegram Bot Token 或 Chat ID 未配置,跳过通知" + exit 0 + fi + + # 获取 PR 基本信息 + PR_NUMBER="${{ github.event.pull_request.number }}" + PR_TITLE="${{ github.event.pull_request.title }}" + PR_URL="${{ github.event.pull_request.html_url }}" + PR_MERGE_COMMIT="${{ github.event.pull_request.merge_commit_sha }}" + + # 获取 PR 详细信息 + PR_BODY="${{ steps.pr_details.outputs.pr_body }}" + + # 转义 PR 标题和描述中的 HTML 特殊字符(但保留已有的 HTML 标签) + PR_TITLE_ESCAPED=$(echo "$PR_TITLE" | sed 's/&/\&/g' | sed 's//\>/g') + + # 构建消息内容(使用 HTML 格式) + MESSAGE="🚀 PR 已合并到 main 分支 + +📝 PR #${PR_NUMBER}: ${PR_TITLE_ESCAPED} +🔗 链接: 查看 PR +🔀 合并提交: ${PR_MERGE_COMMIT:0:7}" + + # 添加 PR 描述(如果有) + if [ -n "$PR_BODY" ] && [ "$PR_BODY" != "null" ] && [ "$PR_BODY" != "" ]; then + # 使用 Python 将 Markdown 转换为 HTML(更可靠) + PR_BODY_HTML=$(python3 << 'PYTHON_SCRIPT' +import sys +import re + +text = sys.stdin.read() + +# 转义 HTML 特殊字符(先转义,避免破坏后续的转换) +text = text.replace('&', '&') +text = text.replace('<', '<') +text = text.replace('>', '>') + +# 代码块:```code``` →
code
+text = re.sub(r'```([^`]+)```', r'
\1
', text, flags=re.DOTALL) + +# 行内代码:`code` → code(不在代码块中) +text = re.sub(r'`([^`]+)`', r'\1', text) + +# 粗体:**text** → text +text = re.sub(r'\*\*([^*]+)\*\*', r'\1', text) + +# 斜体:*text* → text(不在粗体或代码中) +text = re.sub(r'(?]*)\*([^*<>]+)\*(?![^<]*>)', r'\1', text) + +# 链接:[text](url) → text +text = re.sub(r'\[([^\]]+)\]\(([^)]+)\)', r'\1', text) + +# 标题:# Heading → Heading +text = re.sub(r'^### (.+)$', r'\1', text, flags=re.MULTILINE) +text = re.sub(r'^## (.+)$', r'\1', text, flags=re.MULTILINE) +text = re.sub(r'^# (.+)$', r'\1', text, flags=re.MULTILINE) + +# 列表项:- item → • item +text = re.sub(r'^- (.+)$', r'• \1', text, flags=re.MULTILINE) +text = re.sub(r'^ - (.+)$', r' • \1', text, flags=re.MULTILINE) +text = re.sub(r'^ - (.+)$', r' • \1', text, flags=re.MULTILINE) + +# 换行处理:Telegram HTML 模式不支持
标签,直接保留换行符 \n +# Telegram 会自动将 \n 渲染为换行 + +# 限制长度 +if len(text) > 1000: + text = text[:1000] + '...\n(内容已截断)' + +print(text, end='') +PYTHON_SCRIPT + <<< "$PR_BODY") + + MESSAGE="${MESSAGE} + +📄 PR 描述: +${PR_BODY_HTML}" + fi + + # 发送 Telegram 消息(使用 jq 转义 JSON) + curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \ + -H "Content-Type: application/json" \ + -d "$(jq -n \ + --arg chat_id "$TELEGRAM_CHAT_ID" \ + --arg text "$MESSAGE" \ + '{chat_id: $chat_id, text: $text, parse_mode: "HTML", disable_web_page_preview: false}')" > /tmp/telegram_response.json + + # 检查发送结果 + if [ $? -eq 0 ]; then + RESPONSE=$(cat /tmp/telegram_response.json) + if echo "$RESPONSE" | grep -q '"ok":true'; then + echo "✅ Telegram 通知发送成功" + else + echo "❌ Telegram 通知发送失败: $RESPONSE" + exit 1 + fi + else + echo "❌ 发送 Telegram 消息时发生错误" + exit 1 + fi +