Prhub

#24180 Re-land #23109: rebase-required mode + fix for grep-no-match abort

原始 PR 作者 alisonshao 合并时间 2026-05-09 06:28 文件变更 3 提交数 8 评论 13 代码增减 +278 / -28

执行摘要

重新实施 rebase-required 模式并修复 grep 无匹配 bug

PR #23109 引入了 rebase-required 模式,但因为 check-maintenance action 的 MIN_BASE_SHA 解析器通过 grep 管道,当 issue body 中没有指令时 grep 返回 1,结合默认的 bash -eo pipefail 设置导致整个脚本异常退出,阻塞所有 PR CI。此 PR 修复了该问题并重新实施该功能。

此 PR 值得精读,特别是 pipefail 问题的调试过程、fail-open 设计模式以及在 CI 中处理不同运行器环境的一致性方法。对于 CI 基础设施维护者,这是很好的实践参考。

讨论亮点

在 PR 的 issue 评论中,作者进行了多次测试。最初作者发现预检逻辑在 PR CI 中工作,但在 /rerun-stage 中未生效(评论:'works on pr ci but NOT on /rerun-stage logic (currently always pass)')。后续通过添加预检函数修复,在后续的 /rerun-stage 请求中,GitHub Actions bot 正确输出了 'Rebase Required' 错误信息。此外,作者还记录了 API rate limit 的情况,但未影响最终功能。

实现拆解

  1. 修复 grep 无匹配 bug:在 .github/actions/check-maintenance/action.yml 中,将原始的单行管道替换为 brace group 加 || true,确保 grep 无匹配时不会触发 pipefail。
  2. 替换 gh CLI 为 curl+jq:原 action 依赖 gh CLI,但自托管 GPU 运行器未安装 gh,导致 action 在这些运行器上静默失败(始终放行)。改用 curl + jq 获取 issue 数据,确保所有运行器行为一致。
  3. 新增 Rebase-Required 模式:在 action 中添加 MIN_BASE_SHA 解析逻辑:读取 issue body 中第一个 MIN_BASE_SHA: <sha> 指令,通过 GitHub Compare API 检查 PR 是否包含该 commit(状态 ahead/identical 放行,behind/diverged 拦截)。此模式不依赖 issue 状态(open 或 close 均生效)。
  4. 预检逻辑:在 scripts/ci/utils/slash_command_handler.py 中新增 _check_rebase_gate 函数,在 /rerun-stage/rerun-test 命令调度前执行与 action 相同的检查。避免已经不符合 rebase 条件的 PR 触发工作流运行(浪费 runner 时间)。
  5. 文档更新:在 .github/MAINTAINER.md 中详细说明 Rebase-Required 模式的使用方法、行为矩阵和注意事项(如避免在代码块中粘贴指令)。
文件 模块 状态 重要度
scripts/ci/utils/slash_command_handler.py CI 脚本 modified 6.32
.github/actions/check-maintenance/action.yml CI Action modified 5.71
.github/MAINTAINER.md 文档 modified 2.83

关键符号

_check_rebase_gate

关键源码片段

scripts/ci/utils/slash_command_handler.py infrastructure

新增预检函数 _check_rebase_gate,避免不符合条件的调度触发工作流

def _check_rebase_gate(gh_repo, pr, token):
    # Fail-open: issue fetch error 时允许继续
    try:
        issue_resp = requests.get(
            f'https://api.github.com/repos/{repo_full_name}/issues/{MAINTENANCE_ISSUE_NUMBER}',
            timeout=15)
        if issue_resp.status_code != 200:
            return True, None
        issue_data = issue_resp.json()
    except Exception:
        return True, None
​
    # 解析 MIN_BASE_SHA
    for line in issue_body.splitlines():
        if 'MIN_BASE_SHA:' in line:
            parts = line.split(':')
            if len(parts) >= 2:
                sha = parts[1].strip().strip('`')
                if 7 <= len(sha) <= 40:
                    min_base_sha = sha
                    break
​
    gate_active = (issue_state == 'open') or bool(min_base_sha)
    if not gate_active:
        return True, None
    ...

评论区精华

rebase gate 在 /rerun-stage 中的行为 正确性

作者发现预检逻辑在 PR CI 中工作,但在 /rerun-stage 中最初总是通过。后续在 action 中添加预检后,/rerun-stage 也正确显示了 'Rebase Required' 错误。

结论:已通过部署 slashed command handler 的预检逻辑修复,现在 rerun 命令也遵循 rebase 门控。 · 已解决

风险与影响

  • 使用 curl+jq 替代 gh CLI 可能引入 token 泄露风险(但 token 已通过环境变量 $GH_TOKEN 传递,且仅用于 API 请求)。
  • 预检逻辑增加了对 GitHub API 的依赖,可能在高并发场景下触发限流(但已有 fail-open 容错)。
  • 新的 rebase 检查可能因 issue body 解析错误(如指令在代码块中)而误判,但文档已明确警告。
  • 整体风险较低,关键路径有 fail-open 保护。

维护者现在可以通过简单的 issue body 编辑强制所有 PR 必须 rebase 才能运行 CI,而不需要进入全暂停模式。贡献者在 rerun 时会收到明确的错误引导,减少困惑。CI 基础设施的健壮性得到提升(避免了之前因 grep 导致全部 CI 阻塞的情况)。影响范围:所有使用 CI 的 PR 和维护者。影响程度:中等。

gh CLI 依赖移除 API 限流风险 预检未覆盖场景

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论