必须选“merged results”子选项,因其仅在mr实际合并、代码写入目标分支后触发,避免重复构建或部署未合并代码;“merge requests”会在创建、更新等阶段多次触发,导致jenkins被反复调用。

GitLab Webhook 必须选 “Merged results” 而不是 “Merge requests”
选错子选项会导致 Jenkins 被反复触发,甚至部署未合并的代码。GitLab 的 Merge Request Events 有两个子选项:Merge requests(MR 创建、更新、评论时都触发)和 Merged results(仅当 MR 实际写入目标分支后触发)。只有后者能确保你拿到的是已落地的代码。
常见错误现象:Jenkins 构建了 dev 分支的代码,但实际要部署的是 main;或同一 MR 触发三次构建(创建、批准、合并各一次)。
- 必须取消勾选
Merge requests,只勾选Merged results - 不要同时启用
Push Events—— 如果走 Code Review 流程,开发不会直接 push 到 main,Push Events基本不生效 - 若项目启用了 squash merge 或 rebase merge,
Merged results仍可靠;但 fast-forward merge 下需确认 GitLab 版本 ≥ 15.2,否则 payload 中target_branch可能为空
Jenkins 如何准确提取刚合并的源分支名
Webhook payload 里的 object_attributes.source_branch 字段不可信:它在 MR 创建时就填入,后续修改 MR 目标分支也不会更新;且 squash 后该字段可能指向临时分支名。正确做法是让 Jenkins 主动调用 GitLab API 拉取最新合并记录。
实操建议:在 Jenkins 构建步骤第一行加 shell 命令:
curl -sS "https://gitlab.example.com/api/v4/projects/${GITLAB_PROJECT_ID}/merge_requests?state=merged&per_page=1" -H "PRIVATE-TOKEN: ${GITLAB_TOKEN}" | jq -r '.[0].source_branch'
关键点:
-
${GITLAB_PROJECT_ID}需提前配置为 Jenkins 全局变量或参数,不能硬编码 -
${GITLAB_TOKEN}必须是具有api权限的 Personal Access Token,不能用 Deploy Token - 返回结果要用
jq解析,避免用sed或awk处理 JSON,易出错 - 如果返回空,说明 API 调用失败或无最近合并记录,应中止构建而非 fallback 到 payload 字段
Webhook URL 必须带 token=xxx 参数
Jenkins 远程触发器(Trigger builds remotely)默认拒绝无 token 的请求,报错 HTTP 403 Forbidden 或直接静默丢弃。这不是权限配置问题,而是机制强制要求。
正确格式示例:https://jenkins.example.com/job/deploy-main/build?token=deploy-on-merge
注意:
-
token值必须与 Jenkins 项目中 “Trigger builds remotely” 设置的 secret token 完全一致,大小写敏感 - GitLab Webhook 配置页的
Secret Token字段与此无关——那是用于签名验证,而 Jenkins 远程触发器用的是 URL 参数方式 - 如果用了 Jenkins Pipeline,且通过
input或timeout等步骤阻塞构建,token仍需出现在 URL 中,否则请求根本进不来
网络连通性比配置更常被忽略
看到 Connection refused 或超时,第一反应不该是查 Jenkins 日志或 GitLab Webhook 设置,而是确认 GitLab 服务器能否访问 Jenkins 的公网地址和端口。私有化部署环境下,GitLab 和 Jenkins 往往不在同一内网段,DNS、防火墙、反向代理规则都可能拦截。
快速验证方法:
- 登录 GitLab 服务器执行:
curl -v http://jenkins.internal:8080/job/deploy-main/build?token=xxx - 若返回 403,说明网络通、Jenkins 可达、token 正确;若卡住或报 connection refused,就是网络层问题
- GitLab SaaS(gitlab.com)无法直连内网 Jenkins,必须暴露公网入口或使用反向代理 + HTTPS + 有效证书
很多团队卡在这里两周,最后发现是 GitLab 所在宿主机没配路由,或者云厂商安全组没开 Jenkins 端口。











