Skip to content

Commit f03b990

Browse files
committed
ci: address migration review feedback
Signed-off-by: Ralf W. Grosse-Kunstleve <rgrossekunst@nvidia.com>
1 parent 398229b commit f03b990

15 files changed

Lines changed: 115 additions & 119 deletions

File tree

‎.github/workflows/ci-nightly.yml‎

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,13 +61,12 @@ jobs:
6161
- name: Set up Python
6262
uses: ./.github/actions/setup-hardened-python
6363
with:
64-
python-version: "3.12"
64+
python-version: "3.11"
6565

6666
- name: Run CI tools unit tests
6767
run: |
68-
python -m pip install pytest pyyaml==6.0.3
69-
# Standalone CI tool tests; skip repo-root conftest.py (imports cuda.pathfinder).
70-
python -m pytest -v --noconftest ci/tools/tests
68+
python -m pip install -e './ci[test]'
69+
python -m pytest -v ci/tools/tests
7170
7271
find-wheels:
7372
if: ${{ github.repository_owner == 'nvidia' && !inputs.documentation-links-only }}

‎AGENTS.md‎

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -64,20 +64,10 @@ For each package tag namespace and target release `X.Y.Z`:
6464
existing history.
6565
- Treat pushed tags as immutable. Correct an unsuitable tagged state with a
6666
new versioned milestone rather than moving or replacing the existing tag.
67-
- Reserve a new preview target from the next globally unused release number,
68-
checking canonical tags and coordinating releases on every maintenance or
69-
stabilization branch. A release on another branch consumes that number even
70-
when its tag is not reachable from `main`. Update `scm-bootstrap-release`
71-
before another build if such a release consumes its target; do not bump the
72-
field per PR or use it to override suitable reachable tags.
73-
- Moving a package's SCM selector to a new toolkit minor also needs a matching
74-
reachable milestone. Updating the selector alone can produce an incorrect
75-
placeholder version. Validate previews with local tags in an independent
76-
disposable clone until the release history supplies the right milestone.
77-
- For a newly integrated maintenance root, create its first retained internal
78-
milestone only after the integration group has landed and been validated on
79-
`main`. Retained tag creation requires an explicit maintainer decision;
80-
preparation of a PR stack does not authorize creating or pushing it.
67+
- Before setting or changing `scm-bootstrap-release`, check canonical tags
68+
and coordinate with release maintainers. Use an unused release number,
69+
including releases tagged on other branches; keep the same target across
70+
builds until release coordination requires a change.
8171

8272
Use the package's established tag namespace, such as `vX.Y.Z...` for
8373
`cuda-bindings` and `cuda-python`, `cuda-core-vX.Y.Z...` for `cuda-core`, and

‎ci/README.md‎

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -241,8 +241,8 @@ record declares an exact toolkit build/test pin and a `release_status` of
241241
`current` or `maintenance`. Release routing uses the tag's CUDA major/minor
242242
and the toolkit pin to select a root. Bindings and metapackage builds use
243243
setuptools-scm's default tag parser. Each root's `git_describe_command`
244-
selects its tag series for source builds; update its `--match` pattern when
245-
the root moves to a new toolkit minor.
244+
selects its CUDA ABI major for source builds (`v12.*` or `v13.*`),
245+
independently of the toolkit minor used to build it.
246246

247247
The Python helpers share registry parsing and package consistency checks. The small,
248248
repository-private `cuda-python-ci-tools` package installs their common
@@ -268,7 +268,7 @@ Install the test extra to run the CI-tool tests:
268268

269269
```console
270270
python -m pip install -e './ci[test]'
271-
python -m pytest --noconftest ci/tools/tests
271+
python -m pytest ci/tools/tests
272272
```
273273

274274
The public wheel builder requires one `current` package root and one
@@ -311,18 +311,13 @@ or replace such a tag to reuse its name on main. Keep the same target across
311311
PRs and builds until release coordination calls for a change.
312312

313313
Temporary bootstrap tags must stay local to an independent disposable clone;
314-
worktrees share tags. For a newly integrated maintenance root, wait until the
315-
validated integration group is merged on `main` before creating its first
316-
retained internal `X.Y.Za0` milestone, by explicit maintainer decision. Once that
317-
milestone is reachable, remove the temporary bootstrap machinery and its
318-
workflow calls as a follow-up; ordinary SCM history governs subsequent builds.
319-
This guidance does not create or publish a milestone.
320-
321-
A toolkit minor rollover also changes the bindings root's `--match` selector
322-
and the metapackage selector table. Before relying on builds from that new
323-
series, arrange an appropriate reachable milestone, such as `v13.5.0a0` for a
324-
validated CUDA 13.5 line. A selector change without matching history can yield
325-
a plausible but wrong `0.1.dev...` version. The maintenance bootstrap does not
326-
automatically establish milestones for the current-major root. Use the same
327-
local-preview safeguards while preparing the new source and confirm the
328-
resolved version and `git describe` output before retaining its milestone.
314+
worktrees share tags. After CUDA 13 tag isolation lands on `main`, maintainers
315+
can establish the retained CUDA 12 milestone on that validated state. Rebase
316+
remaining migration work onto the tagged commit before removing the temporary
317+
bootstrap machinery and its workflow calls. Ordinary SCM history then governs
318+
subsequent builds. Creating or publishing a milestone requires an explicit
319+
maintainer decision.
320+
321+
A toolkit minor rollover does not change the major-specific SCM selectors.
322+
Let reachable tags govern preview versions; release tags establish the
323+
intended release number.

‎ci/pyproject.toml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ requires-python = ">=3.11"
1515
dependencies = [
1616
"packaging==26.0",
1717
"PyYAML==6.0.3",
18-
"setuptools-scm>=8,!=10.1",
18+
"setuptools-scm[simple]>=8,!=10.1",
1919
]
2020

2121
[project.optional-dependencies]

‎ci/tools/bindings_config.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,10 +200,10 @@ def check_package_metadata(config: BindingsConfig, repo_root: Path) -> None:
200200
if command.count("--match") != 1:
201201
raise ValueError(f"{path} must specify one git_describe_command --match selector")
202202
selector = command[command.index("--match") + 1]
203-
expected_selector = f"v{package.ctk_target}.*"
203+
expected_selector = f"v{package.cuda_major}.*"
204204
if selector != expected_selector:
205205
raise ValueError(
206-
f"{path} --match must select registered CUDA {package.ctk_target} "
206+
f"{path} --match must select registered CUDA major {package.cuda_major} "
207207
f"using {expected_selector!r} for the {package.release_status} root, got {selector!r}"
208208
)
209209
selectors[package.cuda_major] = selector

‎ci/tools/tests/test_bindings_config.py‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,13 @@ def _write_package_metadata(root):
4040
path.parent.mkdir(parents=True)
4141
path.write_text(
4242
'[tool.setuptools_scm]\ngit_describe_command = ["git", "describe", "--match", '
43-
f'"v{package.ctk_target}.*"]\n',
43+
f'"v{package.cuda_major}.*"]\n',
4444
encoding="utf-8",
4545
)
4646
meta = root / "cuda_python" / "pyproject.toml"
4747
meta.parent.mkdir()
4848
meta.write_text(
49-
'[tool.cuda-python.scm-describe-match-by-major]\n"12" = "v12.9.*"\n"13" = "v13.4.*"\n',
49+
'[tool.cuda-python.scm-describe-match-by-major]\n"12" = "v12.*"\n"13" = "v13.*"\n',
5050
encoding="utf-8",
5151
)
5252
core = root / "cuda_core"
@@ -80,12 +80,12 @@ def test_release_tags_select_only_the_matching_bindings_line(tag, expected):
8080
),
8181
)
8282
@pytest.mark.agent_authored(model="gpt-6.1-sol")
83-
def test_metadata_check_catches_selectors_drifting_from_the_registered_line(tmp_path, changed_paths):
83+
def test_metadata_check_catches_selectors_drifting_from_the_registered_major(tmp_path, changed_paths):
8484
config = _write_package_metadata(tmp_path)
8585
check_package_metadata(config, tmp_path)
8686
for relative in changed_paths:
8787
path = tmp_path / relative
88-
path.write_text(path.read_text().replace("v13.4.*", "v13.5.*"), encoding="utf-8")
88+
path.write_text(path.read_text().replace("v13.*", "v14.*"), encoding="utf-8")
8989

9090
with pytest.raises(ValueError):
9191
check_package_metadata(config, tmp_path)
Lines changed: 57 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,71 @@
11
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
22
# SPDX-License-Identifier: Apache-2.0
33

4-
import runpy
4+
import os
55
import shutil
6+
import subprocess
7+
import sys
8+
import tarfile
9+
from email import message_from_bytes
610
from pathlib import Path
7-
from unittest.mock import Mock
11+
from zipfile import ZipFile
812

913
import pytest
10-
import setuptools
11-
import setuptools_scm
1214
from packaging.requirements import Requirement
13-
from packaging.version import Version
1415

1516

16-
@pytest.fixture
17-
def standalone_source(tmp_path, monkeypatch):
18-
package = Path(__file__).resolve().parents[3] / "cuda_python"
19-
for name in ("setup.py", "pyproject.toml"):
20-
shutil.copyfile(package / name, tmp_path / name)
21-
monkeypatch.chdir(tmp_path)
22-
return tmp_path
17+
@pytest.mark.agent_authored(model="gpt-6")
18+
def test_tagged_maintenance_sdist_keeps_version_and_dependencies_without_selector(tmp_path):
19+
source = Path(__file__).resolve().parents[3] / "cuda_python"
20+
checkout = tmp_path / "checkout"
21+
package = checkout / "cuda_python"
22+
package.mkdir(parents=True)
23+
for filename in ("setup.py", "pyproject.toml", "DESCRIPTION.rst", "LICENSE"):
24+
shutil.copyfile(source / filename, package / filename)
2325

26+
env = os.environ.copy()
27+
env.pop("CUDA_PYTHON_BUILD_MAJOR", None)
28+
for args in (("init", "--quiet"), ("add", "."), ("commit", "--quiet", "-m", "Release"), ("tag", "v12.9.11")):
29+
subprocess.run( # noqa: S603
30+
[ # noqa: S607
31+
"git",
32+
"-c",
33+
"user.name=CI test",
34+
"-c",
35+
"user.email=ci-test@example.invalid",
36+
"-c",
37+
"commit.gpgsign=false",
38+
"-c",
39+
"tag.gpgsign=false",
40+
"-c",
41+
"core.hooksPath=/dev/null",
42+
*args,
43+
],
44+
cwd=checkout,
45+
env=env,
46+
check=True,
47+
capture_output=True,
48+
)
2449

25-
@pytest.mark.parametrize(("requested_major", "expected_major"), ((None, 13), ("12", 12)))
26-
@pytest.mark.agent_authored(model="gpt-6.1-sol")
27-
def test_source_build_selects_bindings_and_major_specific_dependencies(
28-
standalone_source, monkeypatch, requested_major, expected_major
29-
):
30-
if requested_major is None:
31-
monkeypatch.delenv("CUDA_PYTHON_BUILD_MAJOR", raising=False)
32-
else:
33-
monkeypatch.setenv("CUDA_PYTHON_BUILD_MAJOR", requested_major)
34-
setup = Mock()
35-
monkeypatch.setattr(setuptools, "setup", setup)
36-
monkeypatch.setattr(
37-
setuptools_scm,
38-
"get_version",
39-
lambda **options: options["git_describe_command"][-1].removeprefix("v").replace("*", "0"),
50+
subprocess.run(
51+
[sys.executable, "-c", "from setuptools.build_meta import build_sdist; build_sdist('dist')"],
52+
cwd=package,
53+
env=env,
54+
check=True,
4055
)
41-
42-
runpy.run_path(str(standalone_source / "setup.py"))
43-
44-
metadata = setup.call_args.kwargs
45-
assert Version(metadata["version"]).major == expected_major
46-
dependencies = {req.name: req for req in map(Requirement, metadata["install_requires"])}
47-
expected = {"cuda-bindings", "cuda-core", "cuda-pathfinder"} if expected_major >= 13 else {"cuda-bindings"}
48-
assert dependencies.keys() == expected
49-
assert metadata["version"] in dependencies["cuda-bindings"].specifier
50-
51-
52-
@pytest.mark.agent_authored(model="gpt-6.1-sol")
53-
def test_maintenance_sdist_keeps_its_dependencies_without_a_build_selector(standalone_source, monkeypatch):
54-
(standalone_source / "PKG-INFO").write_text(
55-
"Metadata-Version: 2.4\nName: cuda-python\nVersion: 12.9.11\n", encoding="utf-8"
56+
unpacked = tmp_path / "unpacked"
57+
with tarfile.open(next((package / "dist").glob("*.tar.gz"))) as archive:
58+
archive.extractall(unpacked, filter="data")
59+
standalone = next(unpacked.iterdir())
60+
subprocess.run(
61+
[sys.executable, "-c", "from setuptools.build_meta import build_wheel; build_wheel('dist')"],
62+
cwd=standalone,
63+
env=env,
64+
check=True,
5665
)
57-
monkeypatch.delenv("CUDA_PYTHON_BUILD_MAJOR", raising=False)
58-
setup = Mock()
59-
monkeypatch.setattr(setuptools, "setup", setup)
60-
61-
runpy.run_path(str(standalone_source / "setup.py"))
62-
63-
metadata = setup.call_args.kwargs
64-
assert Version(metadata["version"]).major == 12
65-
assert {Requirement(value).name for value in metadata["install_requires"]} == {"cuda-bindings"}
66+
with ZipFile(next((standalone / "dist").glob("*.whl"))) as wheel:
67+
metadata = message_from_bytes(
68+
wheel.read(next(name for name in wheel.namelist() if name.endswith(".dist-info/METADATA")))
69+
)
70+
assert metadata["Version"] == "12.9.11"
71+
assert {Requirement(value).name for value in metadata.get_all("Requires-Dist", [])} == {"cuda-bindings"}

‎cuda_bindings_12/README.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ This subpackage adheres to the developing practices described in the parent meta
1616
## Testing
1717

1818
Run the commands below from `cuda_bindings_12/`, in an environment containing
19-
the CUDA 12 bindings. Install the package and its `test` dependency group with
20-
`python -m pip install -v -e . --group test`.
19+
the CUDA 12 bindings. With pip 25.1 or newer, install the package and its
20+
`test` dependency group with `python -m pip install -v -e . --group test`.
2121

2222
Multiple testing options are available:
2323

‎cuda_bindings_12/docs/source/release/12.X.Y-notes.rst‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55

66
.. module:: cuda.bindings
77

8-
``cuda-bindings`` Upcoming CUDA 12 Release Notes
9-
================================================
8+
``cuda-bindings`` 12.X.Y Release notes
9+
======================================
1010

1111
Unreleased
1212

‎cuda_bindings_12/pyproject.toml‎

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -47,14 +47,6 @@ all = [
4747
"nvidia-cufile-cu12; sys_platform == 'linux'",
4848
]
4949

50-
test = [
51-
"cython>=3.2.5,<3.3",
52-
"setuptools>=80.0.0",
53-
"numpy>=1.21.1",
54-
"pytest==9.1.0",
55-
"pytest-benchmark>=3.4.1",
56-
"pyglet>=2.1.9"
57-
]
5850

5951
[dependency-groups]
6052
# Keep build in sync with build-system.requires.
@@ -172,7 +164,7 @@ exclude = ["cuda/bindings/_version.py"]
172164
[tool.setuptools_scm]
173165
root = ".."
174166
version_file = "cuda/bindings/_version.py"
175-
git_describe_command = ["git", "describe", "--dirty", "--tags", "--long", "--match", "v12.9.*"]
167+
git_describe_command = ["git", "describe", "--dirty", "--tags", "--long", "--match", "v12.*"]
176168

177169
[tool.cuda-python]
178170
scm-bootstrap-release = "12.9.11"

0 commit comments

Comments
 (0)