# PR #25392 完整报告

- 仓库：`sgl-project/sglang`
- 标题：pr-states: fix fork-PR token + add run-ci label awareness
- 合并时间：2026-05-15 19:09
- 原文链接：http://prhub.com.cn/sgl-project/sglang/pull/25392

---

# 执行摘要

- 一句话：修复 fork PR token 与 run-ci 标签感知
- 推荐动作：可快速合入，提升 fork PR 贡献者体验；拉取 review 时重点确认触发器改动和标签逻辑正确性。

# 功能与动机

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

# 实现拆解

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 工作流；类别 infra；类型 infrastructure；符号 peRun）: 核心变更文件：触发器从 pull_request 改为 pull_request_target，并新增 run-ci 标签感知逻辑，是 CI 状态展示功能的主入口。
- `scripts/ci/utils/slash_command_handler.py`（模块 CI 工具；类别 infra；类型 infrastructure）: 次要清理：删除关于 /rerun-stage 废弃原因的冗余代码注释。

关键符号：findRunWithRetry

## 关键源码片段

### `.github/workflows/pr-states.yml`

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

```yaml
# .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
            // ...

```

# 评论区精华

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

- 暂无高价值评论线程

# 风险与影响

- 风险：pull_request_target 虽不会 checkout 代码，但若未来工作流被修改为执行任意代码（例如新增 checkout 和运行脚本），则可能被 fork PR 利用。当前变更安全，但需确保后续维护者不破坏这一假设。
- 影响：影响所有 fork 和内部 PR 的 CI 状态展示：fork PR 的 pr-states 将正确运行并更新 PR body；非 fork PR 行为不变。新增的 run-ci 标签红叉提示使贡献者能立即发现缺失标签。
- 风险标记：核心路径变更

# 关联脉络

- PR #25387 pr-states: add run-ci-extra awareness: 本 PR 是对 #25387 的跟进，增加了 run-ci 标签的感知，并修复了其引入的 fork PR token 问题。
- PR #25322 Deprecate /rerun-stage; scrub CUDA target_stage infra: 本 PR 中删除的 /rerun-stage 注释与之相关，该 PR 废弃了 /rerun-stage 命令。