GitHub Pull Request构建失败时新增可点击按钮实现咨询
实现方案
不用第三方插件、不用注入前端脚本,全靠GitHub原生Checks API就能实现,稳定性有保障,整体链路是:
- 你现有PR触发Jenkins构建的逻辑保持不变
- Jenkins构建失败时,调用GitHub接口在对应PR上创建一个带自定义操作按钮的Check Run
- 提前配置好GitHub webhook,监听按钮点击事件,收到事件后触发你预设的自定义逻辑
前置配置
- 打开目标仓库的Settings页面,找到Personal access tokens生成入口,创建一个勾选
repo、checks:write权限的访问令牌,后续调用GitHub接口会用到 - 在仓库Webhooks配置页新增两个webhook:
- 你已经配置过的PR事件触发Jenkins的webhook,保持不变
- 新增一个监听
check_run事件的webhook,请求地址填你用来处理按钮点击逻辑的服务公网地址,记得设置webhook密钥用来校验请求来源合法性
步骤1:Jenkins构建失败时自动给PR添加按钮
按钮是Check Run的原生组件,会直接展示在PR的检查项区域,不需要额外注入前端代码。你只需要在Jenkins构建失败的回调节点加一段调用GitHub接口的逻辑即可。
下面是可直接复用的代码示例,你可以根据自己的技术栈换成Groovy(Jenkins原生支持)、Go等其他语言:
import requests import os # 以下参数均可从Jenkins内置环境变量直接读取,无需硬编码 GITHUB_TOKEN = "你提前生成的具备Checks写权限的访问令牌" REPO_FULL_NAME = os.getenv("GIT_REPO_FULLNAME") # 格式:仓库所属空间/仓库名 PR_HEAD_SHA = os.getenv("ghprbActualCommit") # PR当前最新提交的SHA,Jenkins的PR触发插件会自动注入这个变量 CURRENT_JENKINS_BUILD_URL = os.getenv("BUILD_URL") # 当前失败构建的Jenkins地址 def create_failed_build_check_with_button(): api_endpoint = f"https://api.github.com/repos/{REPO_FULL_NAME}/check-runs" request_headers = { "Accept": "application/vnd.github+json", "Authorization": f"Bearer {GITHUB_TOKEN}", "X-GitHub-Api-Version": "2022-11-28" } request_payload = { "name": "Jenkins构建检查", "head_sha": PR_HEAD_SHA, "status": "completed", "conclusion": "failure", "details_url": CURRENT_JENKINS_BUILD_URL, "output": { "title": "Jenkins构建执行失败", "summary": "本次PR触发的构建任务未通过,可点击下方按钮执行预设修复操作后重试" }, # 自定义按钮配置,单个Check Run最多支持添加3个按钮 "actions": [ { "label": "执行自定义修复并重试", # 按钮上展示的文字 "description": "自动执行缓存清理、依赖重装等预设操作后重跑构建", "identifier": "custom_fix_rebuild_001", # 按钮唯一标识,后续点击事件靠这个区分 } ] } resp = requests.post(api_endpoint, json=request_payload, headers=request_headers) resp.raise_for_status() # 仅在构建失败时触发按钮创建逻辑 if os.getenv("BUILD_STATUS") == "FAILURE": create_failed_build_check_with_button()
代码部署位置
直接把这段逻辑放到Jenkinsfile的post失败触发块里就行,参考片段:
pipeline { agent any // 保留你原有的构建步骤 stages { // 你原来的拉代码、编译、测试等逻辑 } post { failure { script { // 执行上面的按钮创建逻辑,不想用Python的话也可以用Jenkins的httpRequest插件直接发请求 sh 'python3 ./scripts/add_pr_button.py' } } } }
步骤2:实现按钮点击后的自定义逻辑
用户点击你创建的按钮时,GitHub会向你之前配置的check_run事件webhook发送POST请求,请求中action字段值为requested_action,你只需要在接收服务里匹配按钮的唯一标识,执行对应逻辑即可。
最简接收服务示例(基于Flask,可部署在任意能被GitHub公网访问的服务器上,也可以换成GitHub Actions、云函数等托管服务):
from flask import Flask, request import hmac import hashlib app = Flask(__name__) WEBHOOK_SECRET = "你配置webhook时设置的签名密钥" def your_custom_business_logic(repo_name, pr_num): # 这里写你需要执行的自定义操作,比如: # 1. 调用Jenkins接口清理工作空间、重跑构建 # 2. 自动给PR提交修复代码、发表评论通知 # 3. 触发其他内部系统的联动流程 print(f"收到按钮点击请求,仓库{repo_name}的PR#{pr_num}开始执行自定义修复逻辑") def validate_github_signature(request): # 校验请求确实来自GitHub,避免伪造请求 signature = request.headers.get("X-Hub-Signature-256") if not signature: return False sha_name, signature_hash = signature.split("=") if sha_name != "sha256": return False mac = hmac.new(WEBHOOK_SECRET.encode(), msg=request.data, digestmod=hashlib.sha256) return hmac.compare_digest(mac.hexdigest(), signature_hash) @app.route("/github-webhook-receiver", methods=["POST"]) def webhook_entry(): if not validate_github_signature(request): return "invalid signature", 403 event_type = request.headers.get("X-GitHub-Event") payload = request.json # 只处理自定义按钮点击事件 if event_type == "check_run" and payload.get("action") == "requested_action": clicked_action = payload.get("requested_action", {}) # 匹配你之前给按钮设置的唯一标识 if clicked_action.get("identifier") == "custom_fix_rebuild_001": repo_info = payload["repository"]["full_name"] related_pr = payload["check_run"]["pull_requests"][0]["number"] your_custom_business_logic(repo_info, related_pr) return "operation triggered", 200 return "event ignored", 200 if __name__ == "__main__": app.run(host="0.0.0.0", port=8000)
步骤3:PR页面按钮展示校验
如果配置完按钮没显示,按以下顺序排查:
- 创建Check Run时传入的
head_sha必须是对应PR当前最新的commit SHA,填错会导致Check Run无法关联到PR,按钮自然不展示 - 生成访问令牌的账号必须有目标仓库的写权限,否则调用创建Check Run接口会返回404/403错误
- 不要把Check Run的可见范围设为私有,仓库内所有有PR查看权限的用户都能看到按钮
- 按钮默认展示在两个位置:PR对话页的检查项列表底部、PR的Checks标签页对应检查项的右侧,不需要额外配置前端脚本
可选优化
自定义逻辑执行过程中,你可以随时调用GitHub的Check Run更新接口,修改Check Run的状态为执行中、成功、失败,用户在PR页面可以直接看到操作的执行进度,不需要跳转其他页面。
内容的提问来源于stack exchange,提问作者Sujatha N Anjan
相关产品推荐
相关产品推荐

