Prhub

#25392 pr-states: fix fork-PR token + add run-ci label awareness

原始 PR 作者 hnyls2002 合并时间 2026-05-15 19:09 文件变更 2 提交数 7 评论 2 代码增减 +22 / -13

执行摘要

修复 fork PR token 与 run-ci 标签感知

PR body 中提到,pull_request 事件下 fork PR 的 GITHUB_TOKEN 为只读,导致 pr-states 工作流在更新 PR body 时返回 403。100% 的 fork PR 会显示红色失败检查,混淆外部贡献者。此外,缺少 run-ci 标签时,CI 实际被 gate 但状态栏仍显示链接,具有误导性。

可快速合入,提升 fork PR 贡献者体验;拉取 review 时重点确认触发器改动和标签逻辑正确性。

讨论亮点

无 review 讨论,作者自行合并。仅有一条 Gemini 的自动消息声明无法审查。

实现拆解

  1. 修改 pr-states.yml 触发器:将 on: pull_request 更改为 pull_request_target,使工作流在 base 分支上下文中运行,获得写权限 token;同时添加注释说明安全性(不 checkout PR 代码)。
  2. 增加 run-ci 标签感知:在 JavaScript 脚本中读取 run-ci 标签,并据此决定是否查询 pr-test.yml 的运行;缺失时显示红叉 :x: Missing run-ci label,而不是链接。
  3. 联动 extra 状态:pr-test-extra 需要同时有 run-ci 和 run-ci-extra 标签才运行;现在当 run-ci 缺失时,extra 状态显示为 :x: Blocked — run-ci is required first.
  4. 清理冗余注释:在 scripts/ci/utils/slash_command_handler.py 中删除了 4 行关于 /rerun-stage 废弃原因的代码注释,因为下方已有的打印消息已说明相同内容。
文件 模块 状态 重要度
.github/workflows/pr-states.yml CI 工作流 modified 6.11
scripts/ci/utils/slash_command_handler.py CI 工具 modified 2.56

关键符号

findRunWithRetry

关键源码片段

.github/workflows/pr-states.yml infrastructure

核心变更文件:触发器从 pull_request 改为 pull_request_target,并新增 run-ci 标签感知逻辑,是 CI 状态展示功能的主入口。

# .github/workflows/pr-states.yml ( 关键片段 )
name: PR States
# 使用 pull_request_target 使 fork PR 获得写权限 token
# 安全:工作流从不 checkout PR head 代码,仅通过 API 读取元数据
on:
  pull_request_target:
    types: [opened, synchronize, reopened, labeled, unlabeled]
permissions:
  pull-requests: write
  # ... 其他权限保持不变jobs:
  update-pr-body:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/github-script@v7
        with:
          script: |
            const sha = context.payload.pull_request.head.sha;
            const labels = context.payload.pull_request.labels.map(l => l.name);
            const hasCI = labels.includes('run-ci');         # 新增:检查 run-ci 标签
            const hasExtra = labels.includes('run-ci-extra');
            // ... 辅助函数 findRunWithRetry 省略
            // 只有具有 run-ci 标签时才查询 pr-test.yml 的运行记录
            const ptRun = hasCI ? await findRunWithRetry('pr-test.yml') : null;
            // pr-test-extra 需要同时有 run-ci 和 run-ci-extra
            const peRun = (hasCI && hasExtra) ? await findRunWithRetry('pr-test-extra.yml') : null;
            // 定义各类状态文本
            const missingCIText = ':x: **Missing `run-ci` label** — add it to run CI tests.';
            const peBlockedByCIText = ':x: **Blocked** — `run-ci` is required first.';
            // 根据标签情况选择显示文本
            const ptText = !hasCI
              ? missingCIText
              : (isReal(ptRun) ? `[Run #${ptRun.id}](${ptRun.html_url})` : '_Not run yet_');
            const peText = !hasCI
              ? peBlockedByCIText
              : !hasExtra
                ? notExtraEnabledText
                : (isReal(peRun) ? `[Run #${peRun.id}](${peRun.html_url})` : stalePushText);
            // 构造最终状态块并更新 PR body
            // ...

评论区精华

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

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

风险与影响

pull_request_target 虽不会 checkout 代码,但若未来工作流被修改为执行任意代码(例如新增 checkout 和运行脚本),则可能被 fork PR 利用。当前变更安全,但需确保后续维护者不破坏这一假设。

影响所有 fork 和内部 PR 的 CI 状态展示:fork PR 的 pr-states 将正确运行并更新 PR body;非 fork PR 行为不变。新增的 run-ci 标签红叉提示使贡献者能立即发现缺失标签。

核心路径变更

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论