Prhub

#25812 pr-states: dispatch from pr-test* notify job (fix rerun status)

原始 PR 作者 hnyls2002 合并时间 2026-05-20 06:57 文件变更 3 提交数 4 评论 1 代码增减 +130 / -12

执行摘要

修复 CI 重跑后 PR 状态不刷新

PR body 指出 'Fix pr-states.yml not refreshing after a rerun (UI or slash command). Root cause: GitHub does NOT re-fire workflow_run.completed for rerun attempts'。因此需要让 pr-states 在重跑后也能更新状态。

对于维护 CI/CD 基础设施的工程师,本 PR 有较高的参考价值——展示了如何利用 workflow_dispatch 绕过 workflow_run 在重跑时的限制,以及 fork PR 兼容性考虑。可精读 pr-states.yml 中的 JavaScript 逻辑和 notify job 的设计。

讨论亮点

未产生 review 讨论,PR 合并者为作者本人,表明改动已充分自验证。

实现拆解

  1. 新增 notify job:在 pr-test.ymlpr-test-extra.yml 末尾分别添加 notify-pr-states job。当 CI 运行完成(无论成功失败)且是自仓库的原生 PR 时,通过 gh workflow run 命令向 pr-states.yml 发送 workflow_dispatch 事件,传递 PR 编号。该 job 依赖聚合器 job(pr-test-finish / pr-test-extra-finish),聚合器检查所有下游 job 是否有失败。

  2. 调整 pr-states 触发器:在 pr-states.ymlon 中添加 workflow_dispatch 输入参数 pr_number,并保留 pull_request_targetworkflow_run 作为备用(尤其是 fork PR 场景)。调整并发组 key 以兼容三种事件源,防止 body PATCH 竞态。

  3. 更新渲染脚本:在 actions/github-script 步骤中增加对 workflow_dispatch 事件的处理分支,通过 context.payload.inputs.pr_number 获取 PR 编号。同时优化注释和逻辑,明确各事件源的分支。

这些变更确保每次 CI 运行(包括重跑)完成后,pr-states 都能被触发去更新 PR body 中的状态区块。fork PR 不受 notify job 的影响(token 只读),依赖原有的 workflow_run 订阅实现初始更新。

文件 模块 状态 重要度
.github/workflows/pr-states.yml CI 工作流 modified 5.3
.github/workflows/pr-test-extra.yml CI 工作流 modified 4.99
.github/workflows/pr-test.yml CI 工作流 modified 4.31

关键源码片段

.github/workflows/pr-states.yml infrastructure

触发事件重构,新增 workflow_dispatch 支持,更新 JavaScript 逻辑,是修复的核心文件

# .github/workflows/pr-states.yml 事件触发器
on:
  pull_request_target:
    types: [opened, synchronize, reopened, labeled, unlabeled]
  workflow_run:
    workflows: ["PR Test Base", "PR Test Extra"]
    types: [requested, completed]
  workflow_dispatch: # 新增:用于接收通知 job 的调度
    inputs:
      pr_number:
        description: 'PR number to refresh'
        required: true
        type: string
// 根据事件源获取 PR 编号
let prNumber;
if (context.payload.pull_request) {
  // pull_request_target: 直接从 payload 获取
  prNumber = context.payload.pull_request.number;
} else if (context.eventName === 'workflow_run') {
  // workflow_run: 尝试从 workflow_run 对象的 pull_requests 中获取
  const wr = context.payload.workflow_run;
  if (wr.pull_requests && wr.pull_requests.length > 0) {
    prNumber = wr.pull_requests[0].number;
  } else {
    // fork PR 的分支不在 default branch,需要按 head 引用反向查找
    const [owner, branch] = wr.head_branch.split(':');
    // ... 反向查找逻辑(省略)
  }
} else if (context.eventName === 'workflow_dispatch') {
  // workflow_dispatch: 由输入参数直接传入
  prNumber = context.payload.inputs.pr_number;
}
// 之后使用 prNumber 调用 GitHub API 更新 PR body 中的 CI 状态块

评论区精华

没有提炼出高价值讨论线程

当前评论区没有形成足够清晰的争议点或结论,后续有更多讨论时会体现在这里。

风险与影响

主要风险包括:(1)fork PR 兼容性:notify-pr-states job 会排除 fork PR,依赖 workflow_run 订阅可能在某些边界下延迟更新。PR 已保留 workflow_run 并作为备用,风险可控。(2)workflow_dispatch 速率限制:GitHub 对 gh workflow run 有速率限制,但 PR 中 notify job 只触发一次,影响小。(3)并发竞态:concurrency 组基于 PR 编号或 SHA 去重,可防止同时多个事件覆盖 body。整体风险较低。

影响范围:所有使用 CI 状态显示功能的 PR(包括 fork PR)的刷新行为。对用户而言,重跑后 PR 状态块会正确更新,提升开发体验。对系统无明显性能影响。对团队:CI 工作流架构增强了对 GitHub 事件限制的理解。

CI 基础设施变更 workflow_dispatch 速率限制 fork PR 兼容性

关联 Issue

未识别关联 Issue

当前没有检测到明确关联的 Issue 链接,后续同步到相关引用后会出现在这里。

完整报告

参与讨论