
如何用 REST API 的 Status API 搭建自定义 CI 服务并关联 Pull Request【免费下载链接】docsThe open-source repo for docs.github.com项目地址: https://gitcode.com/GitHub_Trending/do/docs如果你的项目还没有接入现成的 CI 服务或者你想用自己的测试脚本本地流水线、Jenkins、任何自建服务来标记每次提交的结果可以基于 GitHub REST API 的 Status API 搭一个最小可用的 CI 服务当 Pull Request 打开时服务收到 webhook 事件调用 Status API 把 commit 状态置为pending测试跑完后再把状态更新为success或failure这些状态会直接显示在 Pull Request 页面上。本文基于 Building a CI server 指南和 REST API endpoints for commit statuses 端点文档整理。指南中的示例服务用 Ruby Sinatra 编写默认监听4567端口配合隧道工具把本地服务暴露给公网让 GitHub 能把 webhook 事件推送到你机器上。准备条件开始前需要准备好以下四项都是指南明确要求的一个可以随意实验的仓库并且你有权在该仓库下创建和管理 webhook。指南建议用一个测试仓库例如 Fork 一个公开仓库来做。一个个人访问令牌PAT用于服务端调用 GitHub API。管理方式见 Managing your personal access tokens。关于权限范围Status API 文档说明repo:statusOAuth scope 只授予状态访问权限而不会连带授予仓库代码访问权reposcope 则同时包含代码和状态权限。如果只想让 CI 服务标记状态用repo:status就够。一个本地运行的服务。指南示例是 Sinatra 应用默认端口4567。把本地端口暴露到公网的手段。指南默认方案是下载并配置 ngrok隧道工具用于把本地应用暴露到互联网。作为替代路径文档注明也可以使用 webhook forwarding 在本地环境接收 webhook具体见 Using the GitHub CLI to forward webhooks for testing。先写一个最小服务验证连通性先用一个只回显的服务证明本地链路是通的再谈业务逻辑。指南给出的第一步代码require sinatra require json post /event_handler do payload JSON.parse(params[:payload]) Well, it worked! end启动这个服务然后把隧道工具指向 Sinatra 的4567端口。接下来在测试仓库里创建 webhookWebhook 的 URL 填隧道工具给出的公网地址本例对应http://你的隧道地址/event_handler你的隧道地址替换为你实际获得的隧道地址Content type 选择application/x-www-form-urlencoded点击Update webhook。判断标准webhook 测试的 body 响应应该出现Well, it worked!这是文档给出的示例响应。出现即说明 GitHub 到本地服务的链路已打通。然后回到 webhook 配置点击Let me select individual events勾选两个事件StatusPull Request这两个事件就是本场景下 GitHub 会推送到你的服务器的全部内容。处理 Pull Request 打开事件链路通了之后把服务更新为只处理 PR 打开的场景。指南的核心逻辑是GitHub 发出的每个事件都带一个X-GitHub-EventHTTP 头先按这个头区分事件类型再从 payload 里取action字段判断是不是openedpost /event_handler do payload JSON.parse(params[:payload]) case request.env[HTTP_X_GITHUB_EVENT] when pull_request if payload[action] opened process_pull_request(payload[pull_request]) end end end helpers do def process_pull_request(pull_request) puts Its #{pull_request[title]} end end验证方式在测试仓库的某个分支上做一些改动然后打开一个 Pull Request服务端终端应该打印出Its PR 标题。调试阶段有一个指南明确提到的省时技巧每次更新服务代码后不需要每次都新开一个 PR直接在 webhook 投递记录里点击Redeliver就会把同一个 payload 再发一遍。用 Status API 给 commit 写入 CI 状态这一步是整个 CI 服务的核心。先明确 Status API 的能力边界来自 commit statuses 端点文档Status API 允许外部服务把 commit 标记为error、failure、pending或success四种状态涉及该 commit 的 Pull Request 中会反映这个状态状态可以带可选的description和target_url文档强烈建议提供这两项例如 CI 场景下target_url指向构建输出的完整 URLdescription是构建结果的一句话摘要状态可以带context字段用来标明状态来自哪个服务。比如 CI 服务推ci上下文、安全审计工具推security上下文之后可以用 REST API 的 Get the combined status for a specific reference 接口取回一个 commit 的完整状态。服务端调用 API 前先按指南的方式配置 Octokit 客户端令牌从环境变量读取# !!! DO NOT EVER USE HARD-CODED VALUES IN A REAL APP !!! # Instead, set and test environment variables, like below ACCESS_TOKEN ENV[MY_PERSONAL_TOKEN] before do client || Octokit::Client.new(:access_token ACCESS_TOKEN) endMY_PERSONAL_TOKEN是环境变量名指向你创建好的 PAT启动服务前必须先设置该环境变量。指南同时明确警告真实应用里不要硬编码令牌值。然后修改process_pull_request在收到 PR 打开事件时立即把 commit 状态置为pending让 PR 页面显示CI 进行中def process_pull_request(pull_request) puts Processing pull request... client.create_status(pull_request[base][repo][full_name], pull_request[head][sha], pending) end这一行做了三件事取出仓库的full_name、取出 PR 头部的最后一个 commit SHA、把该 commit 的状态设为pending。之后你在本地执行真正的测试流程——把代码交给 Jenkins、调另一个测试服务的 API或者跑任何脚本文档没有规定具体实现。测试结束后再调一次状态写入。指南的示例用sleep 2模拟耗时的测试过程然后写入successdef process_pull_request(pull_request) client.create_status(pull_request[base][repo][full_name], pull_request[head][sha], pending) sleep 2 # do busy work... client.create_status(pull_request[base][repo][full_name], pull_request[head][sha], success) puts Pull request processed! end把sleep 2替换成你真实的测试调用即可测试失败时按 Status API 文档把状态写成failure或error。结果验证按以下顺序确认整条链路工作正常webhook 连通性创建 webhook 时的测试投递body 响应为Well, it worked!文档示例。事件处理新开一个 Pull Request服务端打印Its PR 标题与Processing pull request...。状态落库PR 页面上该 commit 的状态先显示pending测试结束后变为success。Status API 文档确认这些状态会反映在涉及该 commit 的 Pull Request 中。限制与注意事项上面的示例只处理action opened。指南明确指出理想情况下服务应该关注每次 PR 更新而不只是打开这样才能保证每次新 push 都重新过 CI 测试。要覆盖这个场景需要在事件处理里追加对 PR 更新事件的分支。令牌不要硬编码走环境变量权限范围按最小原则选择只写状态时用repo:status。如果你在开发 GitHub App 且需要比状态更详细的信息文档建议改用 Checks API见 REST API endpoints for checks。如果你不需要自建这套服务也可以直接使用现有 CI 集成本文搭建的只是接收事件 写状态的通信层测试执行本身可以指向任何外部系统。下一步需要在一个 commit 上聚合多个服务CI、安全扫描等的状态时使用 Status API 文档中的 Get the combined status for a specific reference 接口见 REST API endpoints for commit statuses。完整走查流程与示例代码见 Building a CI server。【免费下载链接】docsThe open-source repo for docs.github.com项目地址: https://gitcode.com/GitHub_Trending/do/docs创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考