Git 仓库 Webhook 配置与测试
Git 仓库 Webhook 配置与测试 本指南对应当前后端代码。先部署本次后端并重启服务,再开始测试;只修改本地代码不会让线上接口生效。启动时会按现有数据库同步配置创建回调配置表和任务表。 1. 准备条件 已通过 Git 仓库发布接口创建资源帖,记下帖子 ID,例如 123 。普通手动创建、未绑定仓库的帖子不能直接启用回调。 仓库必须是互联网公开仓库,不能是私有或组织内公开仓库。 获取配置时使用该帖发布账号的站内登录 Token,不能使用登录密钥方式的 Token。站内 Token 用于操作本网站,平台 API Token 用于后端读取仓库,回调 Secret 用于验证推送,三者用途不同。 使用源仓库管理员账号配置原生 Webhook,或能够修改该仓库的发布流水线。 后端有平台可以访问的公网 HTTPS 地址。以下示例使用 https://backend.example.com ,请替换为你的后端域名。 服务端平台凭据: 平台 后端环境变量 GitHub GIT REPOSITORY GITHUB TOKEN ,可选,用于提高 API 配额 GitLab 当前公开仓库匿名读取 Bitbucket GIT REPOSITORY BITBUCKET TOKEN ,可选 CNB GIT REPOSITORY CNB TOKEN ,必需;权限含 repo basic info:r 、 repo code:r 、 repo release:r CODING GIT REPOSITORY CODING CREDENTIALS ,必需;按团队配置 JSON,例如 {"my team":"username:token"} ,需要代码仓库和版本的读取权限 AtomGit GIT REPOSITORY ATOMGIT TOKEN ,必需 环境变量配置方法另见 Git 仓库接口文档 。不需要每个发帖用户提交平台 Token。 2. 获取本帖的回调地址和 Secret 在 PowerShell 执行,替换前四个变量: $OutputEncoding = [System.Text.UTF8Encoding]::new($false) [Console]::OutputEncoding = [System.Text.UTF8Encoding]::new($false) $backendOrigin = 'https://backend.example.com' $apiPrefix = '/api' 未启用后端 Prefix 时改成空字符串 '' $postId = 123 $siteToken = '帖子发布账号的站内登录Token' $apiBase = "$backendOrigin$apiPrefix" $authHeaders = @{ Authorization = "Bearer $siteToken" } $hookResult = Invoke RestMethod Method Post Uri "$apiBase/git repository/$postId/webhook" Headers $authHeaders $hook = $hookResult.data $callbackUrl = "$backendOrigin$($hook.callbackPath)" $callbackUrl $hook | Format List 请求无请求体。首次调用创建配置,后续调用返回相同 Secret,不会自动重置。该 POST 接口返回 HTTP 201 属于正常创建响应,响应体的 code 为 200 。 重点保存以下字段: 字段 用途 callbackPath 后端已处理 /api 前缀的回调路径,拼接后端域名得到完整地址 secret 本帖的回调密钥,填入平台 Secret 或发布脚本的密钥变量 mode native 为原生 Webhook; pipeline 为发布脚本通知 events 原生模式需要订阅的事件 完整回调地址示例: https://backend.example.com/api/git repository/123/webhook/receive 。平台回调不携带站内登录 Token,验证依靠回调 Secret。 3. GitHub 打开源仓库 → Settings → Webhooks → Add webhook 。 按下表填写,保持 SSL verification 和 Active 启用。 设置项 填写内容 Payload URL 第 2 步得到的 $callbackUrl Content type application/json Secret 配置接口返回的 secret Which events… Let me select individual events ,只勾选 Releases 保存。GitHub 会发送 ping ,在 Webhook 的 Recent Deliveries 中检查 HTTP 200。 ping 对应 queued: false 是正常的,不会创建版本。 真正测试时,先上传好发行版附件,再发布一个新的 Release,或编辑已有已发布 Release 的发行说明并保存。 再检查投递记录与第 7 节的站内同步状态。单纯 push 代码、创建 tag 或保存草稿不会触发本接口的 Release 导入。 该接入处理 release.published 和 release.edited ,包括已发布的预发布版,忽略草稿和删除事件。官方设置说明: GitHub 创建 Webhook 。 4. GitLab 打开公开项目 → Settings → Webhooks → Add new webhook 。 填入以下内容: 设置项 填写内容 URL 第 2 步得到的 $callbackUrl Secret token 配置接口返回的 secret Trigger 勾选 Release events SSL verification 保持启用 自定义载荷模板 不设置,使用平台默认 JSON 当前接口读取 X Gitlab Token ,因此使用 Secret token 字段。不要只配置新版的 Signing token ,当前后端尚未实现其签名格式。 创建或编辑一个真实存在的 Release,并确保资源附件已配置好。 在 Webhook 的 Recent events 中查看请求结果,再按第 7 节检查同步状态。平台的 Test 功能可辅助检查连通性,但模拟 tag 如果不真实存在,后台会报对应版本不存在;应以真实 Release 测试完整同步。 仅处理 Release Hook 的创建和更新,删除不会删除本地版本。官方设置说明: GitLab Webhooks 。 5. Bitbucket Cloud 打开公开仓库 → Repository settings → Webhooks → Add webhook 。 URL 填完整 $callbackUrl ,Secret 填配置接口返回的 secret ,事件选 Repository push ( repo:push ),保持启用。 推送一个新 tag,例如: git tag a v webhook test 1 m "Webhook test" git push origin v webhook test 1 在仓库 Webhook 的投递记录中查看 HTTP 200,并检查站内出现对应 tag 的版本。 后端只处理 tag,普通分支推送和删除不会建立任务。Bitbucket 的 Downloads 与 tag 没有自动对应关系,所以这里创建的是空附件版本,不要以是否下载 Downloads 判断测试是否成功。官方设置说明: Bitbucket 管理 Webhook 。 6. CNB、CODING、AtomGit 这三个平台当前使用 发布脚本通知 。获取配置后会看到 mode: "pipeline" 、 events: [] ;不是在平台原生 Webhook 页面只填一个地址就完成。 先在本机验证 继续使用第 2 节的 PowerShell 变量,替换仓库地址与真实存在的 Release tag: $deliveryId = [guid]::NewGuid().ToString() $notification = @{ repositoryUrl = 'https://cnb.cool/你的组织/你的仓库' tag = 'v1.0.0' deliveryId = $deliveryId } | ConvertTo Json Compress Invoke RestMethod Method Post Uri $callbackUrl Headers @{ 'X Repository Token' = $hook.secret } ContentType 'application/json; charset=utf 8' Body ([System.Text.Encoding]::UTF8.GetBytes($notification)) repositoryUrl 必须是该帖绑定的公开仓库。CODING 示例为 https://e.coding.net/team/project/repo ;AtomGit 示例为 https://atomgit.com/owner/repo 。 如需重试同一次通知,直接重发已经生成的 $notification ,不要重新生成 $deliveryId 。一次新的发布或编辑才使用新 ID。 再加入发布流水线 把通知任务放在“创建/更新 Release”和“所有附件上传成功”之后运行。将 URL、Secret 放入构建平台的变量/密钥配置;下例需要 curl 和 jq 。 变量 值 REPOSITORY WEBHOOK URL 本帖的完整回调地址 REPOSITORY WEBHOOK SECRET 本帖的回调 Secret,作为密钥变量 REPOSITORY URL 该帖绑定的仓库地址 RELEASE TAG 本次发布的 tag RELEASE DELIVERY ID 本次发布任务的唯一 ID,重试必须保持相同;新一轮发布/编辑使用新 ID set eu : "${REPOSITORY WEBHOOK URL:?Missing callback URL}" : "${REPOSITORY WEBHOOK SECRET:?Missing callback secret}" : "${REPOSITORY URL:?Missing repository URL}" : "${RELEASE TAG:?Missing release tag}" : "${RELEASE DELIVERY ID:?Missing delivery ID}" payload=$(jq n \ arg repo "$REPOSITORY URL" \ arg tag "$RELEASE TAG" \ arg delivery "$RELEASE DELIVERY ID" \ '{repositoryUrl: $repo, tag: $tag, deliveryId: $delivery}') curl fail with body silent show error \ X POST "$REPOSITORY WEBHOOK URL" \ H 'Content Type: application/json' \ H "X Repository Token: $REPOSITORY WEBHOOK SECRET" \ data binary "$payload" 不要把 CODING 项目协同的 RELEASE CREATED / RELEASE UPDATED 事件当作 Git 代码发行版回调。未加脚本通知时,仍然每小时检查新增 Release。 7. 检查有没有同步成功 继续使用第 2 节变量: $syncResult = Invoke RestMethod Method Get Uri "$apiBase/git repository/$postId/status" Headers $authHeaders $syncResult.data | Format List 检查项 预期结果 回调 HTTP 状态 200 data.accepted true ,表示验证并接收成功 data.queued 新事件为 true ;重复事件、GitHub ping、被忽略事件为 false 同步 status 后台任务完成后为 synced lastSyncAt 已推进到本次处理时间 nextSyncAt 约为本次完成时间的一小时后 帖子版本 新 tag 创建版本;已有版本更新说明和附件关联 importedReleaseCount 新 tag 增加;编辑已有版本时保持不变 回调 HTTP 200 只代表任务已接收。文件下载、转存和版本更新在后台执行,通常稍后完成;仓库正在同步时会排队。接收后失败会记录 lastError ,5 分钟后重试该 tag,不会因此立即扫描全部历史版本。 测试推送时先不要点击手动同步,否则容易混淆是 Webhook 生效还是手动扫描导入了版本。 8. 排查与维护 现象 优先检查 配置接口 401 站内登录 Token 是否有效 配置接口 403 是否使用了被限制的登录密钥方式 配置接口提示无权限或未绑定仓库 当前账号是否为该帖作者,帖子是否通过 Git 仓库方式发布 回调 404 是否已部署新代码、帖子 ID 是否正确、 /api 是否多写或漏写 回调 401 Secret 是否一致;GitLab 是否填在 Secret token;发布脚本是否发送 X Repository Token ;代理是否改变了原生签名请求的 JSON 内容 回调提示仓库不一致 推送来源或 repositoryUrl 是否对应这个帖子的绑定仓库 HTTP 200 但 queued: false 是否为 ping、重复投递、草稿、删除或非支持事件 status: failed 查看 lastError ,常见原因有 API 凭据、配额、网络、附件大小、存储配额、模组解析或版本不存在 附件测试没有变化 确保通知发送前附件已经上传完成;仅上传附件不一定产生 Release 编辑推送,完整测试可再编辑并保存发行说明 重置回调 Secret: $hookResult = Invoke RestMethod Method Post Uri "$apiBase/git repository/$postId/webhook/reset" Headers $authHeaders $hook = $hookResult.data $hook | Format List 重置后旧 Secret 立即失效,需要同时修改平台 Webhook 或流水线密钥。重新调用普通配置接口只会取回当前 Secret,不会自动重置。 关闭回调: Invoke RestMethod Method Delete Uri "$apiBase/git repository/$postId/webhook" Headers $authHeaders 关闭后不再接受新回调,待处理任务取消;已经运行的任务可能完成。每小时同步继续。需要重新启用时,再调用第 2 节配置接口并更新平台 Secret。 Gitee 目前不用配置回调,每小时同步;Codeup 当前不开放导入,不能通过配置 Webhook 绕过公开仓库校验。