You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[no-ci] ci: use same-run CUDA 12 bindings for Core and metapackages - #3318
Layer 4 of 7 of the staged "CUDA 12 bindings on main" stack. Previous: #3317. Next: #3319. Stack map at the bottom.
What this PR does
Cuts the last dependency on the 12.9.x branch inside PR CI. Everything that needs CUDA 12 bindings during a main run now takes the wheel built in the same run.
cuda.core's cu12 half is built against the same-run CUDA 12 wheel. The lookup-run-id --branch 12.9.x artifact download disappears from build-wheel.yml.
Core's cu12 Cython test extensions are built and uploaded (<core artifact>-cu12-tests), with stale-output cleanup between the two ABI builds.
A CUDA 12 metapackage wheel is built (CUDA_PYTHON_BUILD_MAJOR=12) next to the CUDA 13 one.
The temporary Maintenance bindings jobs from [no-ci] ci: build and test local CUDA 12 bindings #3317 go away. Instead the regular test matrices annotate each row from the registry (BINDINGS_ROOT, BINDINGS_SOURCE, artifact names): 12.9.1 rows test bindings, Core, and metapackage from this run's wheels; 13.0.x / 12.6.x rows keep testing Core against published floor bindings.
sdist checks run once per package root (matrix over the registry).
cuda_python/setup.py + pyproject.toml: a selector table {"12": "v12.*", "13": "v13.*"}; an unambiguous exact CUDA 12 tag selects CUDA 12; otherwise CUDA 13 is the default. CUDA_PYTHON_BUILD_MAJOR explicitly selects either line; dependencies follow the resolved version, so a CUDA 12 sdist rebuilt outside Git keeps CUDA 12 dependencies. The CUDA 12 metapackage depends on bindings only; CUDA 13 also on Core and Pathfinder. Covered by test_cuda_python_setup.py.
Rows match the registry by toolkit major/minor (ctk_target), while artifact names retain the registry's full build-toolkit version. One real tagged-source → sdist → wheel metadata test replaces the mocked metapackage setup tests.
.github/workflows/build-wheel.yml: "Constrain maintenance cuda.core to the same-run cuda.bindings wheel" and "Build maintenance cuda.core Cython tests".
.github/workflows/build-wheel.yml: same-run CUDA 12 constraint for Core, maintenance metapackage wheel, maintenance Core Cython tests, removal of the prior-branch lookup.
.github/workflows/ci.yml: removal of the three temporary jobs; sdist jobs matrixed over package_roots; bindings-config passed to all test jobs.
.github/workflows/test-sdist-linux.yml, test-sdist-windows.yml: bindings-package input replaces cuda-version; per-root build, Pathfinder sdist only for the current root.
Full CI passed at the pre-rebase head 2f2eb43e (run 41188280375).
Local validation at 2f970418c6a33272fc2b1729e0d0627dba8d3cf4: 317 CI-tool tests and configured workflow lint passed. Full-stack CI on #3322 passed at 126ed74fb5bbfbc91a04e50557cf936efef4da7f (105 successful jobs; one expected skip).
adopts the schema-2 registry, removes backport automation, adds metadata checks and maintenance docs; 12.9.x is frozen
Layers #3314 and #3315 have merged. The remaining five migration PRs (#3317, #3318, #3319, #3321 and #3322) will land together using GitHub’s atomic stack merge, with full CI on #3322 as described in the landing plan. #3434 follows separately, after a successful post-migration main CI run supplies complete artifacts for both CUDA majors.
The reason will be displayed to describe this comment to others. Learn more.
In addition to my comments below, my bot had this to say:
🤖 Registry join can silently disable bindings tests (medium): matrix rows are matched to the registry by exact CUDA_VER == toolkit_version. If versions.yml goes from 13.4.2 to 13.4.3 and the matrix rows aren't updated, those rows silently become floor and skip the bindings and Cython tests with no error. The old logic compared major and minor only. The fix is to join on ctk_target.
The reason will be displayed to describe this comment to others. Learn more.
This should be a single entry in the workplan JSON and computed from compute_ci_plan.py (so we don't have this logic reimplemented in JS and scattered in the .yml files).
The reason will be displayed to describe this comment to others. Learn more.
— codex GPT-6 on behalf of Ralf —
The expression is transitional: #3321 replaces it with per-root decisions computed by compute_ci_plan.py. The final workflow consumes those planner flags. planner; consumer.
The reason will be displayed to describe this comment to others. Learn more.
— codex GPT-6 on behalf of Ralf —
Agreed that sharing this implementation would improve maintainability. I propose doing the extraction after migration, preserving toolkit switching, stale-output cleanup, wheel reuse and merging order. This remains open pending agreement on that sequencing; it is not implemented here.
The reason will be displayed to describe this comment to others. Learn more.
Do we have an issue filed to not forget to come back to this? This is exactly the kind of thing where they will get unintentionally out-of-sync, creating hard-to-diagnose problems.
The reason will be displayed to describe this comment to others. Learn more.
— codex GPT-6 on behalf of Ralf —
Removed the mocked selector-wiring cases and replaced them with one real tagged-source → sdist → wheel metadata check. The selector-free sdist rebuild is worth retaining: existing sdist CI keeps the selector set, and incorrect extra dependencies could install successfully. implementation.
The reason will be displayed to describe this comment to others. Learn more.
Using an environment variable for this seems like a big foot gun. For example, if I'm making a release on a tag v12.9.10 but forget to set this environment variable, the build will fail in an obscure way. I would expect this to need to be set in the release.yml workflow in order to do the right thing, but I don't see that change in this or any PRs further up the stack.
I think it would be better to implement our own custom version number lookup before importing setuptools_scm. It would look for an exact tag match for v12.X.Z and if so, set SETUPTOOLS_SCM_PRETEND_VERSION to that exact value. Otherwise fallback to setuptools_scm's default behavior with the 13.* pattern. Then this will do the right thing by default.
The reason will be displayed to describe this comment to others. Learn more.
— codex GPT-6 on behalf of Ralf —
Direct builds at an unambiguous exact CUDA 12 tag select CUDA 12 automatically. Explicit selection wins; untagged or dual-tag commits default to CUDA 13. Setuptools-scm derives the version normally. Implementation.
Correction to my earlier reply: the current-line CI wheel build was missing its explicit selector at this prefix. That gap is now fixed in #3319; both wheel builds then select their major explicitly. release.yml consumes the prebuilt artifacts.
The reason will be displayed to describe this comment to others. Learn more.
Explicit selection still wins; untagged or dual-tag commits default to CUDA 13.
So, let's say we tag v12.9.10 and v13.5.4 at the exact same commit. How does CI support releasing both of them? (I'm not saying it doesn't, I'm saying it's non-obvious how one would do it).
The reason will be displayed to describe this comment to others. Learn more.
— codex GPT-6 on behalf of Ralf —
The new dual-tag procedure explains this explicitly: each tag has its own CI run, and each line is released separately with component=cuda-bindings and component=cuda-python. Run lookup matches both tag and SHA; artifact names and validation separate the lines. The missing current-line selector is fixed in #3319's wheel build, so tag creation order cannot select the wrong major. Local backend-wheel builds verified both orders.
The reason will be displayed to describe this comment to others. Learn more.
— codex GPT-6 on behalf of Ralf —
The patch-version mismatch from your review is fixed: registry rows match by ctk_target, while artifact names retain the registry's full build version. The final implementation and regression test cover differing patch pins.
All five inline comments now have direct replies. The mocked metapackage tests were replaced with a real tagged-source → sdist → wheel check, and exact CUDA 12 tags select that namespace automatically. Bootstrap removal is now complete after the retained milestone and restack; shared Core-build extraction remains a proposed post-migration follow-up.
The reason will be displayed to describe this comment to others. Learn more.
I still think we have some decisions to resolve on this one, namely the double-tagging and releasing both cuda_python versions from that branch. This may be answered by something further up the stack (which I haven't read yet). If I'm satisfied with that, I'll come back and approve this.
The reason will be displayed to describe this comment to others. Learn more.
I think this will be really confusing if a commit is tagged with both versions (which is going to be quite common).
cuda_bindings has separate directory trees for each version. cuda_python is trying to mush them together, which creates this confusion. I wonder if following the same pattern for cuda_python as cuda_bindings would be the better choice?
The reason will be displayed to describe this comment to others. Learn more.
— codex GPT-6 on behalf of Ralf —
To make the two layouts concrete for discussion:
Today, cuda_python/ contains one build recipe for both release lines. CI selects the major with CUDA_PYTHON_BUILD_MAJOR; direct builds can infer it from an unambiguous tag, with CUDA 13 as the default otherwise.
The split would give each line its own source directory, mirroring the bindings layout. Using illustrative names:
cuda_python_12/ # v12.* versions and CUDA 12 dependencies
cuda_python_13/ # v13.* versions and CUDA 13 dependencies
Both directories would still produce versions of the same PyPI package, cuda-python. The CUDA 12 metapackage depends on its bindings line; the CUDA 13 metapackage also includes Core and Pathfinder.
The shared layout keeps the recipe in one place and relies on explicit selection in CI. The split makes that selection visible in the directory and removes the environment/tag-default choice from each recipe, at the cost of maintaining two build roots and keeping their common packaging metadata aligned.
This records the alternatives as a basis for deciding which layout is clearer to maintain.
No actionable comments were generated in the recent review.
Summary
Summary by CodeRabbit
New Features
The CUDA Python metapackage supports CUDA 12 and CUDA 13 builds, selecting the matching CUDA Bindings dependency. CUDA 13 builds also include CUDA Core and CUDA Pathfinder.
CUDA Python source distributions can build wheels with version-matched dependencies, including CUDA 12 builds.
Documentation
Nightly CUDA Core installation instructions include Python 3.15 and free-threaded Python 3.15 examples.
Clarified which package documentation is built together and how to build CUDA 12 documentation separately.
cuda-python packaging now selects CUDA-major tags and dependencies. CI workflows use configured bindings-package metadata for wheel and sdist builds and tests, including maintenance package artifacts.
cuda-python selects CUDA 12 or CUDA 13 SCM tags and dependencies based on the build major or checkout tags. A test covers a CUDA 12 sdist-to-wheel build. Packaging guidance and documentation describe package roots and build behavior.
The workflow builds maintenance cuda-python and cuda.bindings wheels under the configured conditions. It also builds cuda.core Cython tests using maintenance bindings and a selected core wheel.
Wheel-test matrices use registry metadata to select build versions and artifacts. CI removes maintenance-bindings job checks. Environment exports and nightly-wheel documentation are updated.
Possibly related issues
NVIDIA/cuda-python#3402 — The issue describes same-run bindings constraints and toolkit switching in build-wheel.yml, which this PR changes.
NVIDIA/cuda-python#3432 — This PR removes prior-branch artifact lookup paths as part of the artifact-source changes tracked by the issue.
Possibly related PRs
NVIDIA/cuda-python#3317 — Both PRs change maintenance bindings inputs and build outputs in the same workflows.
NVIDIA/cuda-python#3322 — This PR consumes the bindings registry contract and configuration introduced by that PR.
NVIDIA/cuda-python#3319 — The maintenance CUDA 12 artifacts built here are inputs to the release artifact selection in that PR.
Suggested reviewers:mdboom, leofang
Change: Other
Merge Risk: Minimal · up to 1d4a0
This change builds and tests CUDA 12 packages from same-run artifacts and selects the CUDA major in cuda-python packaging. No concrete merge-blocking risk is identified in the supplied evidence.
Security architecture risk: Low · up to 1d4a0
The reviewed changes retain existing CI permissions and continue gating the replacement test jobs. No introduced security defect was confirmed. Repository access controls and behavior during interrupted runs or reruns remain unverified.
Retained concerns
No architecture-level concerns identified.
Security review details
Security Blast Radius
observed — The inspected execution boundary includes repository wheel outputs and Linux and Windows GPU runners. Linux custom-driver rows already support privileged containers with host PID access. This is consequential existing CI authority, not a newly added container privilege in this PR.
Trust Boundaries and Controls
observed — Normal wheel-test downloads explicitly select the current workflow run unless a reusable-workflow caller supplies another run ID. Therefore SHA-based artifact names alone do not establish a cross-run collision vulnerability. The inspected CI callers do not supply an alternate run ID.
Resilience and Maintainability Implications
observed — The artifact-download wrapper retries failures while preserving the same name, destination, run, and token inputs. Its final attempt is not marked continue-on-error. Missing maintenance wheel or test-extension uploads are configured as errors, supporting failure containment rather than silent omission.
- [ ] Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Reviewing files that changed from the base of the PR and between 357aca4 and 1d4a047.
Files selected for processing: 2
.github/workflows/build-wheel.yml
.github/workflows/test-wheel-linux.yml
Included review availability: This review used your included allowance. Your plan provides up to 12 included reviews per hour; 10 remain after this review.
The reason will be displayed to describe this comment to others. Learn more.
Nitpick comments: 1
cuda_python/setup.py: 1
26-30: Trivial · Maintainability & Code Quality · Low value
suggestion: The static-analysis command-injection hints do not apply here. The command is a fixed argument list. cwd derives from __file__. No external input reaches the call. Keep the code as is.
One reliability note: git tag raises CalledProcessError or FileNotFoundError if git is missing or the checkout is unusable. This can happen with safe.directory ownership errors in containers. The build then fails instead of defaulting to CUDA 13. Consider catching (subprocess.CalledProcessError, OSError) and keeping the CUDA 13 default.
Reviewing files that changed from the base of the PR and between 8728407 and cdebef2.
Files selected for processing: 14
.github/workflows/build-wheel.yml
.github/workflows/ci.yml
.github/workflows/test-sdist-linux.yml
.github/workflows/test-sdist-windows.yml
.github/workflows/test-wheel-linux.yml
.github/workflows/test-wheel-windows.yml
ci/tools/env-vars
ci/tools/tests/test_bindings_config.py
ci/tools/tests/test_cuda_python_setup.py
cuda_core/docs/source/install.rst
cuda_python/AGENTS.md
cuda_python/docs/README.md
cuda_python/pyproject.toml
cuda_python/setup.py
Included review availability: This review used your included allowance. Your plan provides up to 12 included reviews per hour; 9 remain after this review.
Following up on the Git-error fallback suggestion in this review: keeping the explicit failure here is intentional. Standalone sdists already skip this Git query. In a real checkout, silently defaulting to CUDA 13 could conceal failed CUDA 12 tag detection, and the subsequent SCM version lookup may still fail.
The summary's optional Cython-cache note is also acknowledged. CI does not enable that cache; extending its cross-major handling is deferred from this migration.
rwgk
changed the title
ci: use same-run CUDA 12 bindings for Core and metapackages
[no-ci] ci: use same-run CUDA 12 bindings for Core and metapackages
Nov 12, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
CI/CDCI/CD infrastructurecuda.bindingsEverything related to the cuda.bindings modulecuda.coreEverything related to the cuda.core moduleenhancementAny code-related improvements
2 participants
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
— codex GPT-6 on behalf of Ralf —
Layer 4 of 7 of the staged "CUDA 12 bindings on
main" stack. Previous: #3317. Next: #3319. Stack map at the bottom.What this PR does
Cuts the last dependency on the
12.9.xbranch inside PR CI. Everything that needs CUDA 12 bindings during amainrun now takes the wheel built in the same run.cuda.core's cu12 half is built against the same-run CUDA 12 wheel. Thelookup-run-id --branch 12.9.xartifact download disappears frombuild-wheel.yml.<core artifact>-cu12-tests), with stale-output cleanup between the two ABI builds.CUDA_PYTHON_BUILD_MAJOR=12) next to the CUDA 13 one.Maintenance bindingsjobs from [no-ci] ci: build and test local CUDA 12 bindings #3317 go away. Instead the regular test matrices annotate each row from the registry (BINDINGS_ROOT,BINDINGS_SOURCE, artifact names): 12.9.1 rows test bindings, Core, and metapackage from this run's wheels; 13.0.x / 12.6.x rows keep testing Core against published floor bindings.cuda_python/setup.py+pyproject.toml: a selector table{"12": "v12.*", "13": "v13.*"}; an unambiguous exact CUDA 12 tag selects CUDA 12; otherwise CUDA 13 is the default.CUDA_PYTHON_BUILD_MAJORexplicitly selects either line; dependencies follow the resolved version, so a CUDA 12 sdist rebuilt outside Git keeps CUDA 12 dependencies. The CUDA 12 metapackage depends on bindings only; CUDA 13 also on Core and Pathfinder. Covered bytest_cuda_python_setup.py.Rows match the registry by toolkit major/minor (
ctk_target), while artifact names retain the registry's full build-toolkit version. One real tagged-source → sdist → wheel metadata test replaces the mocked metapackage setup tests.After this merges
12.9.xbranch any more except nightly for older artifact sources (handled in ci: retire legacy branch-based bindings maintenance #3322).mainas today, CUDA 12 still from12.9.xtooling until [no-ci] ci: release CUDA 12 bindings from main #3319.Where to look
.github/workflows/build-wheel.yml: "Constrain maintenance cuda.core to the same-run cuda.bindings wheel" and "Build maintenance cuda.core Cython tests"..github/workflows/test-wheel-linux.yml: the jq block that annotates matrix rows (mirrored in the Windows file).cuda_python/setup.py: line selection and version-derived dependencies.All changes (14 files, +350 / -237)
.github/workflows/build-wheel.yml: same-run CUDA 12 constraint for Core, maintenance metapackage wheel, maintenance Core Cython tests, removal of the prior-branch lookup..github/workflows/ci.yml: removal of the three temporary jobs; sdist jobs matrixed overpackage_roots;bindings-configpassed to all test jobs..github/workflows/test-sdist-linux.yml,test-sdist-windows.yml:bindings-packageinput replacescuda-version; per-root build, Pathfinder sdist only for the current root..github/workflows/test-wheel-linux.yml,test-wheel-windows.yml: registry-driven row annotation;maintenance-bindingsinput removed.ci/tools/env-vars:MAINTENANCE_CUDA_MAJOR, registry-driven test routing, Core Cython artifact suffix, metapackage artifact name.cuda_python/setup.py,cuda_python/pyproject.toml,ci/tools/tests/test_cuda_python_setup.py(new).cuda_python/AGENTS.md,cuda_python/docs/README.md,cuda_core/docs/source/install.rst.Validation
2f2eb43e(run 41188280375).2f970418c6a33272fc2b1729e0d0627dba8d3cf4: 317 CI-tool tests and configured workflow lint passed. Full-stack CI on #3322 passed at126ed74fb5bbfbc91a04e50557cf936efef4da7f(105 successful jobs; one expected skip).Stack map: cumulative capabilities by layer
v12.*tagcuda_bindings_12/; the PR-time CPU source-build smoke covers both roots; three CUDA 12 runtime fixes are incuda.coreand the metapackage still consume12.9.xartifacts12.9.xbranchv12.9.Ntag onmain; CUDA 13 releases are unchanged12.9.xis frozenLayers #3314 and #3315 have merged. The remaining five migration PRs (#3317, #3318, #3319, #3321 and #3322) will land together using GitHub’s atomic stack merge, with full CI on #3322 as described in the landing plan. #3434 follows separately, after a successful post-migration
mainCI run supplies complete artifacts for both CUDA majors.