合并后触发通知需通过CI/CD流水线判断merge事件,提取PR/MR信息,调用Webhook发送钉钉/企微通知,注意区分平台元数据、校验merge真实性、管理token安全及避免重复发送。

合并后怎么触发通知脚本
Git 本身不执行合并后的命令,得靠 CI/CD 流水线或 Git 钩子来驱动。GitHub/GitLab 的「合并成功」事件无法直接调用本地脚本,必须走 Webhook 或 CI 的 job 后置步骤。常见做法是:在 main(或 release)分支的 CI 流水线里加一步,判断当前 commit 是否由 merge 引入(即 git log -1 --merges 能查到),再决定是否发通知。
容易踩的坑:
- 误把普通 push 当成 merge —— 要检查
git log -1 --merges --format='%H' HEAD是否返回当前 commit hash - CI 环境没权限访问企业微信/钉钉机器人 token —— token 必须设为 secret,不能硬编码在脚本里
- GitHub Actions 默认 checkout 是 detached HEAD,需显式
fetch-depth: 0才能查到 merge 记录
怎么用 curl 发钉钉/企微机器人通知
钉钉和企微都要求 POST JSON 到 webhook 地址,但字段名和签名方式不同。企微必须带 timestamp 和 sign(HMAC-SHA256 加密),钉钉可选加签,但建议加上防伪造。
实操建议:
CNB 云原生构建平台的 Git 操作技能,支持代码克隆、提交、推送、分支管理、Merge Request 管理、流水线触发与结果读取。初次使用需收集用户的 Git 用户名和邮箱。
- 用
curl -X POST -H 'Content-Type: application/json' -d @payload.json https://qyapi.weixin.qq.com/...发企微 - 企微
sign生成命令:echo -n "16987654321\nYOUR_SECRET" | openssl sha256 | awk '{print $NF}'(注意 timestamp 是秒级整数) - 钉钉 payload 中
atMobiles字段只对群内启用了「@所有人」权限的人有效,别指望它总能 @ 成功
通知内容里怎么提取 MR/PR 关键信息
CI 环境变量因平台而异:GitHub Actions 提供 GITHUB_EVENT_PATH,GitLab CI 提供 CI_MERGE_REQUEST_IID 和 CI_PROJECT_URL。不能靠 git log -1 解析标题,因为 merge commit 消息格式不统一(例如 Merge pull request #123 from feat/login 或 Merge branch 'dev')。
推荐做法:
- GitHub:解析
$GITHUB_EVENT_PATH中的.pull_request.title、.pull_request.user.login、.pull_request.html_url - GitLab:用
curl -H "PRIVATE-TOKEN: $GITLAB_TOKEN" "$CI_API_V4_URL/projects/$CI_PROJECT_ID/merge_requests/$CI_MERGE_REQUEST_IID"获取详情 - 避免用正则从 commit message 提取 PR 编号 —— 人工 squash 合并时会丢失原始 PR 上下文
为什么通知经常发重或漏发
根本原因是「谁该负责发通知」没厘清。常见错误模式:
- 在 feature 分支上也跑通知脚本 —— 应只在目标发布分支(如
main、staging)的流水线中启用 - 多个 job 并行执行,都判断自己是 merge —— 加个
if: ${{ github.event_name == 'pull_request' && github.event.action == 'closed' && github.event.pull_request.merged == true }}(GitHub) - CI job 被重试,导致重复发送 —— 在发通知前先查 Redis 或写临时标记文件(如
/tmp/notify_$(git rev-parse HEAD)),存在就跳过
最麻烦的是跨平台兼容性:GitLab 的 MR 和 GitHub 的 PR 元数据结构完全不同,如果团队同时用两者,脚本得做两套解析逻辑,而不是幻想一个通用字段能覆盖全部场景。

















