[CI] Enforce modern stage=/runner_config= form for dispatchable test suites (#28108)

This commit is contained in:
Liangsheng Yin
2026-06-12 17:32:54 -07:00
committed by GitHub
parent 335a9c7837
commit 5f315c74da
5 changed files with 60 additions and 14 deletions
+1 -1
View File
@@ -93,7 +93,7 @@ repos:
files: ^\.github/workflows/.*\.yml$
pass_filenames: false
- id: check-registered-tests
name: check registered tests have CI registry
name: validate registered test CI registries
entry: python3 scripts/ci/check_registered_tests.py
language: system
files: ^test/registered/.*\.py$
+56 -10
View File
@@ -1,7 +1,16 @@
#!/usr/bin/env python3
"""
Pre-commit hook: validate that all Python test files under test/registered/
contain a CI registry call (register_cuda_ci, register_amd_ci, etc.).
Pre-commit hook: validate CI registry calls under test/registered/.
1. Every test file must contain a CI registry call (register_cuda_ci,
register_amd_ci, etc.).
2. A CUDA test must not register a `{stage}-test-{runner_config}`-shaped suite
via the legacy single-string `suite=`: that form is not dispatchable via
/rerun-test. Use the modern `stage=`/`runner_config=` form instead -- it
resolves to the identical suite (CIRegistry.effective_suite is
f"{stage}-test-{runner_config}"), so same stage and same runner, just
/rerun-test-able. Legacy `suite=` stays valid for nightly/stress/weekly +
AMD/CPU/NPU suites whose names don't follow that shape.
Reuses ut_parse_one_file() from ci_register.py (AST-based parsing)
to match the same logic used by run_suite.py's collect_tests().
@@ -10,8 +19,14 @@ to match the same logic used by run_suite.py's collect_tests().
import glob
import importlib.util
import os
import re
import sys
# Suite names of the form `{stage}-test-{runner_config}` are exactly what the
# modern stage=/runner_config= form produces, so a legacy suite= carrying this
# shape is always expressible (and should be expressed) the modern way.
_MODERN_SHAPE = re.compile(r"^(.+)-test-(.+)$")
def main() -> int:
# Import ci_register directly to avoid pulling in all of sglang
@@ -21,6 +36,7 @@ def main() -> int:
)
ci_register = importlib.util.module_from_spec(spec)
spec.loader.exec_module(ci_register)
cuda = ci_register.HWBackend.CUDA
# Same filter as run_suite.py: skip conftest.py, __init__.py, and utils.py
files = sorted(
@@ -31,25 +47,55 @@ def main() -> int:
if not files:
return 0
errors = []
missing = []
legacy_shape = [] # (file, suite, stage, runner_config)
for f in files:
try:
registries, _has_main_entry = ci_register.ut_parse_one_file(f)
if len(registries) == 0:
errors.append(f)
except Exception:
# Skip files that can't be parsed (syntax errors, etc.)
pass
continue
if len(registries) == 0:
missing.append(f)
continue
for r in registries:
# Pure legacy form on a CUDA registry: suite set, stage/runner unset.
if not (
r.backend == cuda
and r.suite is not None
and r.stage is None
and r.runner_config is None
):
continue
m = _MODERN_SHAPE.match(r.suite)
if m:
legacy_shape.append((f, r.suite, m.group(1), m.group(2)))
if errors:
exit_code = 0
if missing:
print("ERROR: Files in test/registered/ missing CI registry call:")
print(" Move manual-only tests to test/manual/.\n")
for f in errors:
for f in missing:
print(f" {f}")
print()
return 1
exit_code = 1
if legacy_shape:
print(
"ERROR: CUDA test(s) register a `{stage}-test-{runner_config}`-shaped "
'suite via the legacy `suite="..."` form, which is not dispatchable '
"via /rerun-test. Switch to the modern `stage=`/`runner_config=` form "
"(same stage, same runner):\n"
)
for f, suite, stage, runner_config in legacy_shape:
print(
f" {f}\n"
f' suite="{suite}"'
f' -> stage="{stage}", runner_config="{runner_config}"'
)
print()
exit_code = 1
return 0
return exit_code
if __name__ == "__main__":
@@ -17,7 +17,7 @@ from sglang.test.test_utils import (
write_github_step_summary,
)
register_cuda_ci(est_time=211, suite="base-b-test-1-gpu-large")
register_cuda_ci(est_time=211, stage="base-b", runner_config="1-gpu-large")
register_amd_ci(est_time=345, suite="stage-b-test-1-gpu-small-amd")
@@ -19,7 +19,7 @@ from sglang.srt.utils import get_device
from sglang.test.ci.ci_register import register_cuda_ci
from sglang.test.test_utils import CustomTestCase
register_cuda_ci(est_time=20, suite="base-b-test-1-gpu-small")
register_cuda_ci(est_time=20, stage="base-b", runner_config="1-gpu-small")
DEVICE = get_device()
@@ -35,7 +35,7 @@ from sglang.test.test_utils import (
popen_launch_server,
)
register_cuda_ci(est_time=300, suite="base-b-test-1-gpu-large")
register_cuda_ci(est_time=300, stage="base-b", runner_config="1-gpu-large")
def _data_uri():