From a204cf618ef1686a9187cf87286a1b4bf3bfbba7 Mon Sep 17 00:00:00 2001 From: EmmaQiaoCh Date: Thu, 20 Aug 2026 05:51:00 +0300 Subject: [PATCH 1/4] Move check test list Signed-off-by: EmmaQiaoCh --- jenkins/L0_MergeRequest.groovy | 14 +++++++++++ scripts/check_test_list.py | 37 ++++++++++++++++++++++-------- tests/integration/defs/conftest.py | 16 +++++++++++-- 3 files changed, 56 insertions(+), 11 deletions(-) diff --git a/jenkins/L0_MergeRequest.groovy b/jenkins/L0_MergeRequest.groovy index 996ac079314e..904c2c7b7c0c 100644 --- a/jenkins/L0_MergeRequest.groovy +++ b/jenkins/L0_MergeRequest.groovy @@ -451,6 +451,17 @@ def mergeWaiveList(pipeline, globalVars) } } +def checkTestList(pipeline) +{ + sh "git config --global --add safe.directory \"*\"" + // --no-install-wheel installs only requirements-check-test-list.txt (torch + // CPU build + pytest plugins) and trt-test-db — no GPU or trtllm wheel + // needed. conftest.py stubs out tensorrt_llm.bindings when absent so + // pytest --co succeeds in this CPU-only pod. + sh "NVIDIA_TRITON_SERVER_VERSION=26.05 LLM_ROOT=${LLM_ROOT} LLM_BACKEND_ROOT=${LLM_ROOT}/triton_backend " + + "python3 ${LLM_ROOT}/scripts/check_test_list.py --l0 --qa --waive --no-install-wheel" +} + def preparation(pipeline, testFilter, globalVars) { image = "urm.nvidia.com/docker/buildpack-deps:trixie-scm" @@ -459,6 +470,9 @@ def preparation(pipeline, testFilter, globalVars) stage("Setup Environment") { setupPipelineEnvironment(pipeline, testFilter, globalVars) } + stage("Check Test List") { + checkTestList(pipeline) + } stage("Merge Test Waive List") { mergeWaiveList(pipeline, globalVars) } diff --git a/scripts/check_test_list.py b/scripts/check_test_list.py index 97bb4332c1d9..79d329ca488d 100755 --- a/scripts/check_test_list.py +++ b/scripts/check_test_list.py @@ -527,14 +527,23 @@ def validate_test_lists(test_lists_dir: str, test_base_dir: str): # ============================================================================= -def install_python_dependencies(llm_src): - subprocess.run(f"cd {llm_src} && pip3 install -r requirements-dev.txt", - shell=True, - check=True) - subprocess.run( - f"pip3 install --force-reinstall --no-deps {llm_src}/../tensorrt_llm-*.whl", - shell=True, - check=True) +def install_python_dependencies(llm_src, install_wheel=True): + if install_wheel: + subprocess.run(f"cd {llm_src} && pip3 install -r requirements-dev.txt", + shell=True, + check=True) + subprocess.run( + f"pip3 install --force-reinstall --no-deps {llm_src}/../tensorrt_llm-*.whl", + shell=True, + check=True) + else: + # Minimal deps for pytest --collect-only without a trtllm wheel. + # requirements-check-test-list.txt covers only the packages imported at + # module scope during collection (torch CPU build, pytest plugins, etc.). + subprocess.run( + f"pip3 install -r {llm_src}/requirements-check-test-list.txt", + shell=True, + check=True) subprocess.run( "pip3 install --extra-index-url https://urm.nvidia.com/artifactory/api/pypi/sw-tensorrt-pypi/simple " "--ignore-installed trt-test-db==1.8.5+bc6df7", @@ -761,13 +770,23 @@ def main(): help= f"Base directory for test source files for --validate (default: {_DEFAULT_TEST_BASE_DIR})", ) + parser.add_argument( + "--no-install-wheel", + action="store_true", + help= + ("Skip installing the tensorrt_llm wheel when running --l0/--qa/--waive. " + "Use this on CPU-only nodes where no wheel is available; pytest collection " + "works via stub fallbacks in conftest.py (no GPU or trtllm build needed)." + ), + ) args = parser.parse_args() script_dir = os.path.dirname(os.path.realpath(__file__)) llm_src = os.path.abspath(os.path.join(script_dir, "../")) # Only skip installing dependencies if ONLY --check-duplicates or --validate is used if args.l0 or args.qa or args.waive: - install_python_dependencies(llm_src) + install_python_dependencies(llm_src, + install_wheel=not args.no_install_wheel) pass_flag = True # Verify L0 test lists diff --git a/tests/integration/defs/conftest.py b/tests/integration/defs/conftest.py index c63d15ff0759..2b465ffa8af3 100644 --- a/tests/integration/defs/conftest.py +++ b/tests/integration/defs/conftest.py @@ -48,8 +48,20 @@ # is harmless. from test_common import session_prefetcher_hooks as _prefetch_hooks -from tensorrt_llm.bindings import ipc_nvls_supported -from tensorrt_llm.llmapi.mpi_session import get_mpi_world_size +try: + from tensorrt_llm.bindings import ipc_nvls_supported + from tensorrt_llm.llmapi.mpi_session import get_mpi_world_size +except (ImportError, ModuleNotFoundError): + # tensorrt_llm is not installed (e.g. pytest --collect-only from a source + # checkout without a built wheel). Provide no-op stubs so collection + # succeeds; these functions are only called during test execution, not + # during collection. + def ipc_nvls_supported(): + return False + + def get_mpi_world_size(): + return 1 + from .perf.gpu_clock_lock import GPUClockLock from .perf.session_data_writer import SessionDataWriter From f7d3d753d3d8063d9be5ea9870f0f4fecf0347b3 Mon Sep 17 00:00:00 2001 From: EmmaQiaoCh Date: Thu, 20 Aug 2026 06:20:41 +0300 Subject: [PATCH 2/4] [None][ci] install pip3 before running check_test_list in CPU pod The buildpack-deps:trixie-scm image does not ship pip3. Add apt-get install python3-pip (with break-system-packages config) to checkTestList(), matching the existing pattern in launchReleaseCheck(). Signed-off-by: EmmaQiaoCh --- jenkins/L0_MergeRequest.groovy | 2 ++ 1 file changed, 2 insertions(+) diff --git a/jenkins/L0_MergeRequest.groovy b/jenkins/L0_MergeRequest.groovy index 904c2c7b7c0c..31e61c408808 100644 --- a/jenkins/L0_MergeRequest.groovy +++ b/jenkins/L0_MergeRequest.groovy @@ -454,6 +454,8 @@ def mergeWaiveList(pipeline, globalVars) def checkTestList(pipeline) { sh "git config --global --add safe.directory \"*\"" + trtllm_utils.llmExecStepWithRetry(pipeline, script: "apt-get update && apt-get install -y python3-pip") + sh "pip3 config set global.break-system-packages true" // --no-install-wheel installs only requirements-check-test-list.txt (torch // CPU build + pytest plugins) and trt-test-db — no GPU or trtllm wheel // needed. conftest.py stubs out tensorrt_llm.bindings when absent so From a60cab87e5952db4d76213c5ccd23bf6a59f516e Mon Sep 17 00:00:00 2001 From: EmmaQiaoCh Date: Thu, 20 Aug 2026 07:32:30 +0300 Subject: [PATCH 3/4] [None][ci] move requirements-check-test-list.txt to jenkins/ Co-locate the minimal collection dependencies with the Jenkins scripts that use them. Update the path reference in check_test_list.py and the comment in L0_MergeRequest.groovy accordingly. Signed-off-by: EmmaQiaoCh --- jenkins/L0_MergeRequest.groovy | 2 +- jenkins/requirements-check-test-list.txt | 29 ++++++++++++++++++++++++ scripts/check_test_list.py | 4 ++-- 3 files changed, 32 insertions(+), 3 deletions(-) create mode 100644 jenkins/requirements-check-test-list.txt diff --git a/jenkins/L0_MergeRequest.groovy b/jenkins/L0_MergeRequest.groovy index 31e61c408808..1c884b911424 100644 --- a/jenkins/L0_MergeRequest.groovy +++ b/jenkins/L0_MergeRequest.groovy @@ -456,7 +456,7 @@ def checkTestList(pipeline) sh "git config --global --add safe.directory \"*\"" trtllm_utils.llmExecStepWithRetry(pipeline, script: "apt-get update && apt-get install -y python3-pip") sh "pip3 config set global.break-system-packages true" - // --no-install-wheel installs only requirements-check-test-list.txt (torch + // --no-install-wheel installs only jenkins/requirements-check-test-list.txt (torch // CPU build + pytest plugins) and trt-test-db — no GPU or trtllm wheel // needed. conftest.py stubs out tensorrt_llm.bindings when absent so // pytest --co succeeds in this CPU-only pod. diff --git a/jenkins/requirements-check-test-list.txt b/jenkins/requirements-check-test-list.txt new file mode 100644 index 000000000000..941139768c2d --- /dev/null +++ b/jenkins/requirements-check-test-list.txt @@ -0,0 +1,29 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Minimal dependencies for pytest --collect-only used by check_test_list.py +# --no-install-wheel mode (CPU-only, no trtllm wheel needed). +# +# These are the packages imported at module scope during pytest collection in +# tests/integration/defs/conftest.py and its transitive imports. Runtime-only +# deps (GPU kernels, trtllm bindings, etc.) are intentionally excluded. +# +# torch: conftest.py imports it at module scope; the CPU wheel is sufficient +# for collection and avoids the ~2 GB CUDA download. +--extra-index-url https://download.pytorch.org/whl/cpu +torch>=2.12.0 + +psutil +tqdm +PyYAML +mako +oyaml +# pynvml: gpu_clock_lock.py imports pynvml at module scope (nvmlInit() is +# called only inside methods, so the import itself works without a GPU driver) +nvidia-ml-py + +# pytest and the plugins declared in tests/integration/defs/pytest.ini +pytest<9.1 +pytest-asyncio +pytest-threadleak +pytest-unused-fixtures diff --git a/scripts/check_test_list.py b/scripts/check_test_list.py index 79d329ca488d..8c9611081b47 100755 --- a/scripts/check_test_list.py +++ b/scripts/check_test_list.py @@ -538,10 +538,10 @@ def install_python_dependencies(llm_src, install_wheel=True): check=True) else: # Minimal deps for pytest --collect-only without a trtllm wheel. - # requirements-check-test-list.txt covers only the packages imported at + # jenkins/requirements-check-test-list.txt covers only the packages imported at # module scope during collection (torch CPU build, pytest plugins, etc.). subprocess.run( - f"pip3 install -r {llm_src}/requirements-check-test-list.txt", + f"pip3 install -r {llm_src}/jenkins/requirements-check-test-list.txt", shell=True, check=True) subprocess.run( From ac9762edf4ff69e5bc969bb03243df606c26794f Mon Sep 17 00:00:00 2001 From: EmmaQiaoCh Date: Thu, 20 Aug 2026 08:24:06 +0300 Subject: [PATCH 4/4] [None][ci] tolerate collection errors in check_test_list when wheel is absent Add --continue-on-collection-errors to all three pytest --co invocations so that ImportError in test files requiring the trtllm wheel (or other heavy GPU deps) does not abort the entire collection. Accept exit code 2 (collection warnings) alongside 0; any other non-zero code is still a hard failure. Tests in non-importable files fall through to the GPU-stage launchTestListCheck for full validation. Signed-off-by: EmmaQiaoCh --- scripts/check_test_list.py | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/scripts/check_test_list.py b/scripts/check_test_list.py index 8c9611081b47..208c1cdb305e 100755 --- a/scripts/check_test_list.py +++ b/scripts/check_test_list.py @@ -600,11 +600,16 @@ def verify_l0_test_lists(llm_src): with open(test_list, "w") as f: f.writelines(f"{line}\n" for line in sorted(cleaned_lines)) - subprocess.run( + # Exit code 2 means pytest encountered collection errors (ImportError in some + # test files that need the trtllm wheel) but continued with --continue-on- + # collection-errors. Treat 0 and 2 as success; anything else is a real error. + result = subprocess.run( f"cd {llm_src}/tests/integration/defs && " - f"pytest --test-list={test_list} --output-dir={llm_src} -s --co -q", - shell=True, - check=True) + f"pytest --test-list={test_list} --output-dir={llm_src} -s --co -q" + f" --continue-on-collection-errors", + shell=True) + if result.returncode not in (0, 2): + result.check_returncode() def verify_qa_test_lists(llm_src): @@ -614,11 +619,13 @@ def verify_qa_test_lists(llm_src): test_def_files = subprocess.check_output( f"ls -d {test_qa_path}/*.txt", shell=True).decode().strip().split('\n') for test_def_file in test_def_files: - subprocess.run( + result = subprocess.run( f"cd {llm_src}/tests/integration/defs && " - f"pytest --test-list={test_def_file} --output-dir={llm_src} -s --co -q", - shell=True, - check=True) + f"pytest --test-list={test_def_file} --output-dir={llm_src} -s --co -q" + f" --continue-on-collection-errors", + shell=True) + if result.returncode not in (0, 2): + result.check_returncode() # append all the test_def_file to qa_test.txt with open(f"{llm_src}/qa_test.txt", "a") as f: with open(test_def_file, "r") as test_file: @@ -729,11 +736,13 @@ def verify_waive_list(llm_src, args): with open(tmp_waives_file, "w") as f: f.writelines(f"{line}\n" for line in sorted(processed_lines)) - subprocess.run( + result = subprocess.run( f"cd {llm_src}/tests/integration/defs && " - f"pytest --test-list={tmp_waives_file} --output-dir={llm_src} -s --co -q", - shell=True, - check=True) + f"pytest --test-list={tmp_waives_file} --output-dir={llm_src} -s --co -q" + f" --continue-on-collection-errors", + shell=True) + if result.returncode not in (0, 2): + result.check_returncode() def main():