From cb433f111462caf2ce9d23b7d08a125a5b4748d6 Mon Sep 17 00:00:00 2001 From: Jinfeng Date: Mon, 6 Jul 2026 21:30:11 +0000 Subject: [PATCH 01/10] Got initial version to address issue 2183. Let pre-commit check covers pixi cuda version pins to ci/versions.yml --- .pre-commit-config.yaml | 8 ++++ ci/tools/check_pixi_cuda_version.py | 61 +++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 ci/tools/check_pixi_cuda_version.py diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1ac6754ae10..1e49cf1cbea 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -43,6 +43,14 @@ repos: exclude: '(.*pixi\.lock)|(\.git_archival\.txt)|(.*\.patch$)|(^cuda_core/cuda/core/_vendored/)' args: ["--fix"] + - id: check-pixi-cuda-version + name: Check pixi cuda-version pins track ci/versions.yml + entry: python ./ci/tools/check_pixi_cuda_version.py + language: python + additional_dependencies: [pyyaml] + files: '^(ci/versions\.yml|cuda_bindings/pixi\.toml|cuda_core/pixi\.toml)$' + pass_filenames: false + - id: no-markdown-in-docs-source name: Prevent markdown files in docs/source directories entry: bash -c diff --git a/ci/tools/check_pixi_cuda_version.py b/ci/tools/check_pixi_cuda_version.py new file mode 100644 index 00000000000..b18c6c50c57 --- /dev/null +++ b/ci/tools/check_pixi_cuda_version.py @@ -0,0 +1,61 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +"""Check pixi cu13 cuda-version pins track ci/versions.yml (cuda.build.version).""" + +from __future__ import annotations + +import sys +import tomllib +from pathlib import Path + +import yaml + +ROOT = Path(__file__).resolve().parents[2] +VERSIONS = ROOT / "ci" / "versions.yml" +PIXI_FILES = [ROOT / d / "pixi.toml" for d in ("cuda_bindings", "cuda_core")] + + +def main() -> int: + if not VERSIONS.is_file(): + print(f"error: {VERSIONS} not found", file=sys.stderr) + return 2 + try: + build_version = yaml.safe_load(VERSIONS.read_text(encoding="utf-8"))["cuda"]["build"]["version"] + except (KeyError, TypeError): + print(f"error: cuda.build.version not found in {VERSIONS}", file=sys.stderr) + return 2 + + major, minor, *_ = build_version.split(".") + expected = f"{major}.{minor}.*" + errors: list[str] = [] + for path in PIXI_FILES: + if not path.is_file(): + print(f"error: {path} not found", file=sys.stderr) + return 2 + with path.open("rb") as f: + data = tomllib.load(f) + rel = path.relative_to(ROOT) + try: + variants = data["workspace"]["build-variants"]["cuda-version"] + cu13 = data["feature"]["cu13"]["dependencies"]["cuda-version"] + except KeyError as exc: + print(f"error: {rel} missing cuda-version key: {exc}", file=sys.stderr) + return 2 + if expected not in variants: + errors.append(f"{rel}: build-variants missing {expected!r} (has {variants})") + if cu13 != expected: + errors.append(f"{rel}: cu13 pin is {cu13!r}, expected {expected!r}") + + if errors: + print(f"error: pixi cuda-version pins out of sync (expected {expected!r}):", file=sys.stderr) + for err in errors: + print(f" - {err}", file=sys.stderr) + return 1 + + print(f"OK: pixi cuda-version pins match ci/versions.yml ({expected!r})") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) From e327415ec84d81f003aacb53fe459bc179e35bf3 Mon Sep 17 00:00:00 2001 From: Jinfeng Date: Mon, 6 Jul 2026 21:49:47 +0000 Subject: [PATCH 02/10] rename to be more accurate --- ci/tools/check_pixi_cuda_version.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ci/tools/check_pixi_cuda_version.py b/ci/tools/check_pixi_cuda_version.py index b18c6c50c57..97603b142be 100644 --- a/ci/tools/check_pixi_cuda_version.py +++ b/ci/tools/check_pixi_cuda_version.py @@ -12,18 +12,18 @@ import yaml ROOT = Path(__file__).resolve().parents[2] -VERSIONS = ROOT / "ci" / "versions.yml" +VERSIONS_FILE_PATH = ROOT / "ci" / "versions.yml" PIXI_FILES = [ROOT / d / "pixi.toml" for d in ("cuda_bindings", "cuda_core")] def main() -> int: - if not VERSIONS.is_file(): - print(f"error: {VERSIONS} not found", file=sys.stderr) + if not VERSIONS_FILE_PATH.is_file(): + print(f"error: {VERSIONS_FILE_PATH} not found", file=sys.stderr) return 2 try: - build_version = yaml.safe_load(VERSIONS.read_text(encoding="utf-8"))["cuda"]["build"]["version"] + build_version = yaml.safe_load(VERSIONS_FILE_PATH.read_text(encoding="utf-8"))["cuda"]["build"]["version"] except (KeyError, TypeError): - print(f"error: cuda.build.version not found in {VERSIONS}", file=sys.stderr) + print(f"error: cuda.build.version not found in {VERSIONS_FILE_PATH}", file=sys.stderr) return 2 major, minor, *_ = build_version.split(".") From 2e54594989d0d07df0651ea8b39fff6223215839 Mon Sep 17 00:00:00 2001 From: Jinfeng Date: Mon, 6 Jul 2026 21:53:42 +0000 Subject: [PATCH 03/10] make error message more readable and accurate --- ci/tools/check_pixi_cuda_version.py | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/ci/tools/check_pixi_cuda_version.py b/ci/tools/check_pixi_cuda_version.py index 97603b142be..16dc05a0077 100644 --- a/ci/tools/check_pixi_cuda_version.py +++ b/ci/tools/check_pixi_cuda_version.py @@ -43,12 +43,25 @@ def main() -> int: print(f"error: {rel} missing cuda-version key: {exc}", file=sys.stderr) return 2 if expected not in variants: - errors.append(f"{rel}: build-variants missing {expected!r} (has {variants})") + errors.append( + f"{rel}: [workspace.build-variants] cuda-version={variants!r} " + f"does not include {expected!r} " + f"(from ci/versions.yml cuda.build.version={build_version!r})" + ) if cu13 != expected: - errors.append(f"{rel}: cu13 pin is {cu13!r}, expected {expected!r}") + errors.append( + f"{rel}: [feature.cu13.dependencies] cuda-version={cu13!r} " + f"!= {expected!r} " + f"(from ci/versions.yml cuda.build.version={build_version!r})" + ) if errors: - print(f"error: pixi cuda-version pins out of sync (expected {expected!r}):", file=sys.stderr) + print( + f"error: pixi cuda-version pins out of sync with " + f"ci/versions.yml cuda.build.version={build_version!r} " + f"(expected pin {expected!r}):", + file=sys.stderr, + ) for err in errors: print(f" - {err}", file=sys.stderr) return 1 From 32cdff34df1660fa29c41599869fdce472a2b938 Mon Sep 17 00:00:00 2001 From: Jinfeng Date: Mon, 6 Jul 2026 21:55:50 +0000 Subject: [PATCH 04/10] put cuda_bindings / cuda_core to error message to be best accurate --- ci/tools/check_pixi_cuda_version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/tools/check_pixi_cuda_version.py b/ci/tools/check_pixi_cuda_version.py index 16dc05a0077..7af3088d526 100644 --- a/ci/tools/check_pixi_cuda_version.py +++ b/ci/tools/check_pixi_cuda_version.py @@ -57,7 +57,7 @@ def main() -> int: if errors: print( - f"error: pixi cuda-version pins out of sync with " + f"error: cuda_bindings/cuda_core pixi cuda-version pins out of sync with " f"ci/versions.yml cuda.build.version={build_version!r} " f"(expected pin {expected!r}):", file=sys.stderr, From 2a5148cd746b09e7e1fb5b6a74107f919f4a86a8 Mon Sep 17 00:00:00 2001 From: Jinfeng Date: Mon, 6 Jul 2026 21:57:16 +0000 Subject: [PATCH 05/10] add docstring --- ci/tools/check_pixi_cuda_version.py | 1 + 1 file changed, 1 insertion(+) diff --git a/ci/tools/check_pixi_cuda_version.py b/ci/tools/check_pixi_cuda_version.py index 7af3088d526..ff04233827f 100644 --- a/ci/tools/check_pixi_cuda_version.py +++ b/ci/tools/check_pixi_cuda_version.py @@ -17,6 +17,7 @@ def main() -> int: + """Verify cuda_bindings/cuda_core pixi cu13 pins match ci/versions.yml.""" if not VERSIONS_FILE_PATH.is_file(): print(f"error: {VERSIONS_FILE_PATH} not found", file=sys.stderr) return 2 From 5fc01486a3243b80d9981afb76bb3ad163155244 Mon Sep 17 00:00:00 2001 From: Jinfeng Date: Mon, 6 Jul 2026 22:04:14 +0000 Subject: [PATCH 06/10] rename cuda_feature from cu13 to cu{major} to support bumping major version, e.g. 13.x.x to 14.x.x --- ci/tools/check_pixi_cuda_version.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/ci/tools/check_pixi_cuda_version.py b/ci/tools/check_pixi_cuda_version.py index ff04233827f..f135376d324 100644 --- a/ci/tools/check_pixi_cuda_version.py +++ b/ci/tools/check_pixi_cuda_version.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: Apache-2.0 -"""Check pixi cu13 cuda-version pins track ci/versions.yml (cuda.build.version).""" +"""Check pixi cuda-version pins track ci/versions.yml (cuda.build.version).""" from __future__ import annotations @@ -17,7 +17,7 @@ def main() -> int: - """Verify cuda_bindings/cuda_core pixi cu13 pins match ci/versions.yml.""" + """Verify cuda_bindings/cuda_core pixi pins match ci/versions.yml.""" if not VERSIONS_FILE_PATH.is_file(): print(f"error: {VERSIONS_FILE_PATH} not found", file=sys.stderr) return 2 @@ -29,6 +29,8 @@ def main() -> int: major, minor, *_ = build_version.split(".") expected = f"{major}.{minor}.*" + cuda_feature = f"cu{major}" + errors: list[str] = [] for path in PIXI_FILES: if not path.is_file(): @@ -39,7 +41,7 @@ def main() -> int: rel = path.relative_to(ROOT) try: variants = data["workspace"]["build-variants"]["cuda-version"] - cu13 = data["feature"]["cu13"]["dependencies"]["cuda-version"] + cuda_pin = data["feature"][cuda_feature]["dependencies"]["cuda-version"] except KeyError as exc: print(f"error: {rel} missing cuda-version key: {exc}", file=sys.stderr) return 2 @@ -49,9 +51,9 @@ def main() -> int: f"does not include {expected!r} " f"(from ci/versions.yml cuda.build.version={build_version!r})" ) - if cu13 != expected: + if cuda_pin != expected: errors.append( - f"{rel}: [feature.cu13.dependencies] cuda-version={cu13!r} " + f"{rel}: [feature.{cuda_feature}.dependencies] cuda-version={cuda_pin!r} " f"!= {expected!r} " f"(from ci/versions.yml cuda.build.version={build_version!r})" ) From 42287cf2c135e366f9cf7d00ea0fc45759028322 Mon Sep 17 00:00:00 2001 From: Jinfeng Date: Mon, 6 Jul 2026 22:14:33 +0000 Subject: [PATCH 07/10] add extracted line from pixi files to shown when check OK --- ci/tools/check_pixi_cuda_version.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/ci/tools/check_pixi_cuda_version.py b/ci/tools/check_pixi_cuda_version.py index f135376d324..8ba315b1ced 100644 --- a/ci/tools/check_pixi_cuda_version.py +++ b/ci/tools/check_pixi_cuda_version.py @@ -32,6 +32,7 @@ def main() -> int: cuda_feature = f"cu{major}" errors: list[str] = [] + checked: list[str] = [] for path in PIXI_FILES: if not path.is_file(): print(f"error: {path} not found", file=sys.stderr) @@ -58,6 +59,11 @@ def main() -> int: f"(from ci/versions.yml cuda.build.version={build_version!r})" ) + checked.append( + f"{rel} (build-variants.cuda-version={variants!r}, " + f"feature.{cuda_feature}.dependencies.cuda-version={cuda_pin!r})" + ) + if errors: print( f"error: cuda_bindings/cuda_core pixi cuda-version pins out of sync with " @@ -69,7 +75,9 @@ def main() -> int: print(f" - {err}", file=sys.stderr) return 1 - print(f"OK: pixi cuda-version pins match ci/versions.yml ({expected!r})") + print(f"OK: pixi cuda-version pins match ci/versions.yml ({expected!r}):") + for item in checked: + print(f" - {item}") return 0 From 51a7b746acd1ba7b7c435b95c9f476c199bc614d Mon Sep 17 00:00:00 2001 From: Jinfeng Date: Mon, 6 Jul 2026 22:17:10 +0000 Subject: [PATCH 08/10] add concrete build version alon side with expected version --- ci/tools/check_pixi_cuda_version.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ci/tools/check_pixi_cuda_version.py b/ci/tools/check_pixi_cuda_version.py index 8ba315b1ced..ddeeeaab58f 100644 --- a/ci/tools/check_pixi_cuda_version.py +++ b/ci/tools/check_pixi_cuda_version.py @@ -60,7 +60,7 @@ def main() -> int: ) checked.append( - f"{rel} (build-variants.cuda-version={variants!r}, " + f"{rel} (workspace.build-variants.cuda-version={variants!r}, " f"feature.{cuda_feature}.dependencies.cuda-version={cuda_pin!r})" ) @@ -75,7 +75,10 @@ def main() -> int: print(f" - {err}", file=sys.stderr) return 1 - print(f"OK: pixi cuda-version pins match ci/versions.yml ({expected!r}):") + print( + f"OK: pixi cuda-version pins match ci/versions.yml " + f"cuda.build.version={build_version!r} (expected pin {expected!r}):" + ) for item in checked: print(f" - {item}") return 0 From c9325e094ab584b3889472f1d90e4470d120330d Mon Sep 17 00:00:00 2001 From: Jinfeng Date: Mon, 6 Jul 2026 22:22:00 +0000 Subject: [PATCH 09/10] polish to fix cosmetic --- ci/tools/check_pixi_cuda_version.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/ci/tools/check_pixi_cuda_version.py b/ci/tools/check_pixi_cuda_version.py index ddeeeaab58f..aa9be85341c 100644 --- a/ci/tools/check_pixi_cuda_version.py +++ b/ci/tools/check_pixi_cuda_version.py @@ -44,17 +44,20 @@ def main() -> int: variants = data["workspace"]["build-variants"]["cuda-version"] cuda_pin = data["feature"][cuda_feature]["dependencies"]["cuda-version"] except KeyError as exc: - print(f"error: {rel} missing cuda-version key: {exc}", file=sys.stderr) + print( + f"error: {rel} missing feature {cuda_feature!r} or cuda-version key: {exc}", + file=sys.stderr, + ) return 2 if expected not in variants: errors.append( - f"{rel}: [workspace.build-variants] cuda-version={variants!r} " + f"{rel}: workspace.build-variants.cuda-version={variants!r} " f"does not include {expected!r} " f"(from ci/versions.yml cuda.build.version={build_version!r})" ) if cuda_pin != expected: errors.append( - f"{rel}: [feature.{cuda_feature}.dependencies] cuda-version={cuda_pin!r} " + f"{rel}: feature.{cuda_feature}.dependencies.cuda-version={cuda_pin!r} " f"!= {expected!r} " f"(from ci/versions.yml cuda.build.version={build_version!r})" ) From 2c60ab0c668d6689a315eb78fe923e3d5cf818f7 Mon Sep 17 00:00:00 2001 From: Jinfeng Date: Tue, 7 Jul 2026 00:17:29 +0000 Subject: [PATCH 10/10] address pre commit check --- ci/tools/check_pixi_cuda_version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/tools/check_pixi_cuda_version.py b/ci/tools/check_pixi_cuda_version.py index aa9be85341c..1ca931b9b48 100644 --- a/ci/tools/check_pixi_cuda_version.py +++ b/ci/tools/check_pixi_cuda_version.py @@ -6,9 +6,9 @@ from __future__ import annotations import sys -import tomllib from pathlib import Path +import tomllib import yaml ROOT = Path(__file__).resolve().parents[2]