[CI] Enforce modern stage=/runner_config= form for dispatchable test suites (#28108)
This commit is contained in:
@@ -93,7 +93,7 @@ repos:
|
|||||||
files: ^\.github/workflows/.*\.yml$
|
files: ^\.github/workflows/.*\.yml$
|
||||||
pass_filenames: false
|
pass_filenames: false
|
||||||
- id: check-registered-tests
|
- 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
|
entry: python3 scripts/ci/check_registered_tests.py
|
||||||
language: system
|
language: system
|
||||||
files: ^test/registered/.*\.py$
|
files: ^test/registered/.*\.py$
|
||||||
|
|||||||
@@ -1,7 +1,16 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""
|
"""
|
||||||
Pre-commit hook: validate that all Python test files under test/registered/
|
Pre-commit hook: validate CI registry calls under test/registered/.
|
||||||
contain a CI registry call (register_cuda_ci, register_amd_ci, etc.).
|
|
||||||
|
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)
|
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().
|
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 glob
|
||||||
import importlib.util
|
import importlib.util
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
import sys
|
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:
|
def main() -> int:
|
||||||
# Import ci_register directly to avoid pulling in all of sglang
|
# 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)
|
ci_register = importlib.util.module_from_spec(spec)
|
||||||
spec.loader.exec_module(ci_register)
|
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
|
# Same filter as run_suite.py: skip conftest.py, __init__.py, and utils.py
|
||||||
files = sorted(
|
files = sorted(
|
||||||
@@ -31,25 +47,55 @@ def main() -> int:
|
|||||||
if not files:
|
if not files:
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
errors = []
|
missing = []
|
||||||
|
legacy_shape = [] # (file, suite, stage, runner_config)
|
||||||
for f in files:
|
for f in files:
|
||||||
try:
|
try:
|
||||||
registries, _has_main_entry = ci_register.ut_parse_one_file(f)
|
registries, _has_main_entry = ci_register.ut_parse_one_file(f)
|
||||||
if len(registries) == 0:
|
|
||||||
errors.append(f)
|
|
||||||
except Exception:
|
except Exception:
|
||||||
# Skip files that can't be parsed (syntax errors, etc.)
|
# 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("ERROR: Files in test/registered/ missing CI registry call:")
|
||||||
print(" Move manual-only tests to test/manual/.\n")
|
print(" Move manual-only tests to test/manual/.\n")
|
||||||
for f in errors:
|
for f in missing:
|
||||||
print(f" {f}")
|
print(f" {f}")
|
||||||
print()
|
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__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ from sglang.test.test_utils import (
|
|||||||
write_github_step_summary,
|
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")
|
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.ci.ci_register import register_cuda_ci
|
||||||
from sglang.test.test_utils import CustomTestCase
|
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()
|
DEVICE = get_device()
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ from sglang.test.test_utils import (
|
|||||||
popen_launch_server,
|
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():
|
def _data_uri():
|
||||||
|
|||||||
Reference in New Issue
Block a user