Prhub

#37618 [CI] Add /rerun-test --changed to rerun every test file a PR modifies

原始 PR 作者 alphabetc1 合并时间 2026-09-05 13:38 文件变更 3 提交数 7 评论 20 代码增减 +199 / -19

执行摘要

为 /rerun-test 命令新增 --changed 标志,自动重运行 PR 中变更过的测试文件。

现有 /rerun-test 命令虽然支持多路径,但当 PR 涉及多个测试文件时,作者仍需手动复制所有路径。本 PR 通过添加 --changed 标志,实现一条命令即可重运行所有变更测试文件,提升 CI 调试效率。该需求源于 PR #37058 等多文件修改场景。

此 PR 设计清晰,解决了实际痛点,测试和文档完备。建议团队成员认真阅读 changed_test_files 和 _move_changes_dispatch 的实现,理解其对测试选择的精确控制。对于未来 CI 工具的增强,可考虑将此模式(查询 PR 变更文件并过滤)推广到其他命令。

讨论亮点

核心讨论集中在两个方面:

  1. 移动(rename)文件的处理策略:Reviewer alisonshao 指出,纯移动文件(changes=0)不应全部纳入重运行,否则会像 commit ba214ef 那样导致 63 个文件被选中。作者回应称移动可能包含代码变更,应运行测试。最终结论是:仅当移动改变了文件的调度路径(如进入 CI 根目录、跨越多模态边界)时才纳入。
  2. 多模态辅助文件的过滤:alisonshao 指出 python/sglang/multimodal_gen/test/test_utils.py 等辅助文件会被错误选中,导致 pytest 收集到零测试而退出码 5。解决方案是:对多模态文件额外检查文件内是否定义了 def test_ 或 class Test,并排除 manual/ 目录下的文件。
  3. Fork PR 的已知限制:Codex 机器人指出,在 fork PR 中,若作者无写权限,工作流会 checkout main 而非 PR head,导致新增测试文件不存在于本地,解析时会报错。团队认为这与显式指定新增文件的行为一致,暂不处理。

实现拆解

  1. 引入新标志与解析逻辑:在 scripts/ci/utils/slash_command_handler.py 中定义 CHANGED_TESTS_FLAG(--changed)和 CHANGED_TESTS_SHORT_FLAG(-c),并在 main() 中从命令行参数中剥离它们,将布尔值 include_changed_tests 传递给核心处理函数。
  2. 实现变更测试文件查询:新增 changed_test_files(pr) 函数,通过 PR API 获取文件列表,并使用 _is_rerunnable_test_path 过滤出符合条件的测试文件。核心筛选逻辑包括:
    • 文件状态非 removed;
    • 路径以 test_ 开头且在测试根目录下;
    • 对于多模态测试文件,额外检查文件内是否定义了可收集的测试(_collects_pytest_tests)并排除 manual/ 目录。
  3. 处理移动(rename)边界情况:新增 _move_changes_dispatch 函数,判断一个纯重命名是否改变了测试的调度路径(例如从非 CI 根目录移入,或跨越多模态测试边界)。纯移动且不影响调度的将被过滤掉。
  4. 集成与错误处理:在 handle_rerun_test 中,当 include_changed_tests 为真时,调用 changed_test_files 并将结果追加到 test_specs 列表。若最终列表为空且无其他明确规格,则返回明确的错误提示。
  5. 测试与文档配套:在 test/registered/unit/tools/test_slash_command_handler.py 中新增 TestChangedTestFiles 测试类,通过模拟 PR 对象覆盖多种文件状态组合(修改、删除、移动、多模态等),验证过滤逻辑。同时更新 docs/docs/developer_guide/contribution_guide.mdx 文档,说明新标志用法。
文件 模块 状态 重要度
scripts/ci/utils/slash_command_handler.py CI 脚本 modified 7.24
test/registered/unit/tools/test_slash_command_handler.py 测试脚本 modified 6.77
docs/docs/developer_guide/contribution_guide.mdx 贡献指南 modified 2.54

关键符号

changed_test_files _is_rerunnable_test_path _collects_pytest_tests _move_changes_dispatch

关键源码片段

scripts/ci/utils/slash_command_handler.py infrastructure

核心变更文件,实现了 --changed 标志的解析、变更测试文件查询和集成逻辑。

# 定义新增标志常量
CHANGED_TESTS_FLAG = "--changed"
CHANGED_TESTS_SHORT_FLAG = "-c"
​
def _is_rerunnable_test_path(path):
    """判断一个仓库相对路径是否是一个可重运行的测试文件。"""
    # 检查是否在测试根目录下(test/registered/ 或多模态测试目录)
    under_test_root = path.startswith("test/registered/") or path.startswith(
        MULTIMODAL_TEST_DIR + "/"
    )
    # 基础条件:在测试根目录下、以 test_ 开头、以 .py 结尾
    if (
        not under_test_root
        or not os.path.basename(path).startswith("test_")
        or not path.endswith(".py")
    ):
        return False
    # 对于非多模态测试文件,满足基础条件即可
    if not path.startswith(MULTIMODAL_TEST_DIR + "/"):
        return True
    # 对于多模态测试文件,额外排除 manual/ 目录并检查文件内是否定义了测试
    return "manual" not in path.split("/") and _collects_pytest_tests(path)
​
def changed_test_files(pr):
    """返回 PR 中新增或修改的、可重运行的测试文件列表。"""
    return sorted(
        f.filename
        for f in pr.get_files()
        if f.status != "removed" # 跳过已删除文件
        and _is_rerunnable_test_path(f.filename) # 路径过滤
        and (
            f.changes > 0 # 有内容变更
            or ( # 或者是影响调度的纯移动
                f.status == "renamed"
                and _move_changes_dispatch(f.previous_filename, f.filename)
            )
        )
    )

评论区精华

移动(rename)文件的处理策略 设计

alisonshao 指出纯移动文件(changes=0)不应全部纳入,否则会像 ba214ef 那样选择 63 个文件。作者回应移动可能包含代码变更。

结论:最终方案:仅当移动改变了文件的调度路径(如进入 CI 根目录、跨越多模态边界、在多模态子目录间移动)时才纳入重运行。 · 已解决

多模态辅助文件的过滤 正确性

alisonshao 指出 test_utils.py 等辅助文件会被选中,导致 pytest 收集到零测试而失败。

结论:对多模态文件额外检查文件内是否定义了 def test_ 或 class Test,并排除 manual/ 目录下的文件。 · 已解决

Fork PR 中新增文件的处理限制 question

Codex 机器人指出,在 fork PR 中,新增测试文件因 checkout main 而不存在于本地,导致解析失败。

结论:团队认为这与显式指定新增文件的行为一致,属于已知限制,暂不处理。 · 已记录

风险与影响

  1. 回归风险:路径过滤逻辑 _is_rerunnable_test_path 被同时用于 glob 扩展和 --changed 查询,修改可能影响 glob 的现有行为。但本次重构将过滤逻辑提取为公共函数,且测试覆盖了多种边界情况,风险较低。
  2. 功能边界模糊:--changed 仅覆盖测试文件本身被修改的情况,不覆盖因源码修改而“受影响”的测试文件。这是设计范围内的明确限制,但可能需要在文档中进一步强调。
  3. 性能影响:changed_test_files 需要遍历 PR 所有文件并读取多模态文件内容进行检查,对于超大 PR(数千文件)可能带来轻微延迟,但通常 CI 脚本可接受。

该 PR 显著提升了开发者的 CI 调试体验,尤其对于涉及多个测试文件的 PR。影响范围限于 CI 工具链,不影响核心推理逻辑。团队成员在触发测试重运行时将减少手动操作,节省时间。同时,提取公共路径过滤函数增强了代码可维护性。

CI 工具链变更 边界情况处理 Fork PR 限制

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论