diff --git a/.github/RELEASE-bindings.md b/.github/RELEASE-bindings.md new file mode 100644 index 00000000000..5834e773aa6 --- /dev/null +++ b/.github/RELEASE-bindings.md @@ -0,0 +1,95 @@ + + +# Releasing CUDA bindings + +## Choose the release scope and source + +Develop the current and maintenance CUDA major lines together on `main`, in +the two package roots listed in [`ci/versions.yml`](../ci/versions.yml). +Release each line independently. A bindings release also needs its matching +`cuda-python` metapackage release; it does not require a release of the other +CUDA major, `cuda-core`, or `cuda-pathfinder`. + +Major-line maintenance may include selected API, Python, platform, or other +compatibility changes. Decide those changes explicitly and describe them in +the release notes. Once a patch release is frozen, admit only its approved +fixes and release prerequisites. Do not infer patch-release scope solely +from the registry's `maintenance` role. + +For an ordinary release, select a tested commit on `main`. If stabilization +must continue while development advances, create a short release branch such +as `release/bindings-12.9.11` from the chosen commit. For an emergency after a +release, start from its exact tag, provided that tag contains the new package +layout. For the first release after this transition, use a validated commit +containing both roots. Keep routine development on `main`; the historical +`12.9.x` branch stays frozen except for emergency fixes using compatible +historical tooling. Reconcile those fixes into the main-tree maintenance +root. Keep the package layout and release tooling together on new release branches. + +Record the source commit, intended tag, selected package root, release owner, +and accepted changes in the release checklist. A branch is a temporary scope +boundary, not a separate long-term home for shared infrastructure. + +## Move fixes between integration and release branches + +Prefer a reviewed fix on `main`, then backport it to the selected release +branch. Run **CI: Backport a merged PR to a release branch** from the Actions +tab on `main`, supplying the merged PR number and one existing target branch. +The workflow opens a PR; it does not merge or release the result. Inspect the +diff, request CI using the normal PR approval procedure, and review it before +merging. Workflow-file changes require a manual backport with appropriate +credentials. Conflicts and toolkit-specific generated changes require an +explicitly reviewed adaptation. + +If urgency requires a fix on the release branch first, link a follow-up PR +reconciling the fix back into `main` before closing the release checklist. In either +direction, assess both bindings roots and record why a change applies to one +or both. Regenerate affected generated files from the intended toolkit and +cybind inputs instead of blindly copying generated output between majors. +See the [shared maintenance policy](../ci/README.md#maintaining-both-bindings-roots). + +## Validate and publish the selected line + +1. Finalize the bindings and metapackage release notes, dependency constraints, + and selected toolkit pin in the release source tree. The registry and + packaging metadata must agree. Run the CI-tool suite and pre-commit checks. +2. Test the candidate through a reviewed PR or manual CI dispatch on its + branch. Normal development CI includes dependent packages and may cover + both majors. Resolve failures in affected code before selecting the tag. +3. Create the approved immutable `vX.Y.Z` tag at the selected source commit. + The tag-triggered CI selects that line's bindings and metapackage, validates + them with the published Pathfinder dependency, and builds release artifacts. + The tag does not have to be on `main`. Wait for this exact tag's CI to pass. +4. Run **CI: Release** with `release-action=dry-run`, the tag, and + `component=cuda-bindings`; repeat for `cuda-python`. Leave `run-id` blank + to exercise automatic lookup, and leave `dry-run-docs-branch` blank to avoid + deploying docs. The workflow verifies a successful tag-triggered CI run + with the exact source SHA, validates artifacts, and builds docs. +5. Review the dry runs, then separately approve and run `full-release` for + each component under the team's release procedure. A successful candidate + rehearsal or ordinary branch CI is not a substitute for exact-tag CI. +6. Finish post-release QA and announcements, return every applicable fix to + `main`, and close the stabilization effort. Retain immutable tags and the + branch history needed for diagnosis. + +The workflow revision used for a release is its **control revision**; the +tagged commit is its **source revision**. Record both and the artifact CI run +ID. Release routing uses the package layout and toolkit settings in +`ci/versions.yml` at the release tag. The current tooling requires a valid +schema-2 registry in that source, for both dry runs and publication, including +Core and Pathfinder releases. Tags from before this registry was introduced +require compatible historical tooling; the current workflow configuration +cannot supply missing tagged configuration. Published releases remain unchanged. + +In **CI: Release**, normal releases require each component's exact-version, +nonempty release notes in the tagged source. The `cuda-python` metapackage requires its own notes. +Notes from the workflow control revision or a different component cannot fill +a gap. Preserve the existing exemption for `.postN` releases, which do not +require new notes. + +Local synthetic tags used in publication-incapable rehearsals must remain local; +they do not authorize publishing a package, creating a remote tag, or moving +an existing tag. diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 72fe9d76db7..e01e22e6ec4 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -52,23 +52,3 @@ updates: time: "09:00" timezone: "America/Los_Angeles" open-pull-requests-limit: 1 - - # GitHub Actions updates targeting the 12.9.x branch - - package-ecosystem: github-actions - directory: / - target-branch: "12.9.x" # keep in sync with backport_branch in ci/versions.yml - schedule: - interval: "monthly" - time: "09:00" - timezone: "America/Los_Angeles" - - # Keep churn down: only one open PR from this ecosystem at a time - open-pull-requests-limit: 1 - - groups: - actions-monthly: - applies-to: version-updates - patterns: ["*"] - update-types: ["major", "minor", "patch"] - - labels: [CI/CD, dependencies] diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml index cb64af94faf..304d368b971 100644 --- a/.github/workflows/backport.yml +++ b/.github/workflows/backport.yml @@ -2,75 +2,84 @@ # # SPDX-License-Identifier: Apache-2.0 -name: "CI: Backport the merged PR" +name: "CI: Backport a merged PR to a release branch" on: - pull_request_target: - types: [closed, labeled] - branches: - - main workflow_dispatch: inputs: backport-branch: - description: "Branch to backport commits onto" - required: false + description: "Existing release branch to receive the fix" + required: true type: string pull-request: - description: "PR to backport" + description: "Merged PR to backport" required: true type: number - permissions: - contents: write # so it can comment - pull-requests: write # so it can create pull requests + contents: write + pull-requests: write + +concurrency: + group: backport-${{ inputs.pull-request }}-${{ inputs.backport-branch }} + cancel-in-progress: false jobs: - backport-from-pr: - name: Backport directly from a pull request - if: ${{ github.repository_owner == 'nvidia' && - github.event.pull_request.merged == true && - contains( github.event.pull_request.labels.*.name, 'to-be-backported') - }} + backport: + if: github.repository == 'NVIDIA/cuda-python' runs-on: ubuntu-latest steps: - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - name: Checkout workflow source + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + ref: ${{ github.sha }} - - name: Load branch name - id: get-branch + - name: Validate source PR and target branch + env: + GH_TOKEN: ${{ github.token }} + GH_REPO: ${{ github.repository }} + DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} + BACKPORT_BRANCH: ${{ inputs.backport-branch }} + PR_NUMBER: ${{ inputs.pull-request }} run: | - OLD_BRANCH=$(yq '.backport_branch' ci/versions.yml) - echo "OLD_BRANCH=${OLD_BRANCH}" >> $GITHUB_ENV + set -euo pipefail + if [[ ! "$PR_NUMBER" =~ ^[1-9][0-9]*$ ]]; then + echo "::error::The source PR must be a positive integer." + exit 1 + fi + if ! git check-ref-format "refs/heads/$BACKPORT_BRANCH"; then + echo "::error::Provide one exact target branch name." + exit 1 + fi + if [[ "$BACKPORT_BRANCH" == "$DEFAULT_BRANCH" ]]; then + echo "::error::Choose a release branch, not the default branch." + exit 1 + fi + if ! git ls-remote --exit-code --heads origin "refs/heads/$BACKPORT_BRANCH"; then + echo "::error::The target branch must already exist in this repository." + exit 1 + fi + if [[ "$(gh pr view "$PR_NUMBER" --repo "$GH_REPO" --json state --jq .state)" != MERGED ]]; then + echo "::error::The source PR must already be merged in this repository." + exit 1 + fi - - name: Create backport pull requests + # Workflow-file changes need a manual backport because GITHUB_TOKEN + # cannot push them. Generated changes need target-specific regeneration. + - name: Create backport pull request + id: backport uses: korthout/backport-action@8560fb503c275d433c56f05a2f64850093baa9f7 # v4.7.0 with: + source_pr_number: ${{ inputs.pull-request }} + target_branches: ${{ inputs.backport-branch }} + # The explicit target must not be combined with source PR labels. + label_pattern: '' copy_assignees: true - copy_labels_pattern: true + copy_labels_pattern: '^(?!to-be-backported$|backport ).*' copy_requested_reviewers: true - target_branches: ${{ env.OLD_BRANCH }} - backport-to-branch: - name: Backport a specific PR against a specific branch - if: github.repository_owner == 'nvidia' && github.event_name == 'workflow_dispatch' - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - - name: Load branch from environment name - if: inputs.backport-branch == null + - name: Require successful backport + if: steps.backport.outputs.was_successful != 'true' run: | - BACKPORT_BRANCH=$(yq '.backport_branch' ci/versions.yml) - echo "BACKPORT_BRANCH=${BRANCH}" >> $GITHUB_ENV - - - name: Load branch name from input - if: inputs.backport-branch != null - run: echo "BACKPORT_BRANCH=${{ inputs.backport-branch }}" >> $GITHUB_ENV - - - name: Create backport pull requests - uses: korthout/backport-action@8560fb503c275d433c56f05a2f64850093baa9f7 # v4.7.0 - with: - copy_assignees: true - copy_labels_pattern: true - copy_requested_reviewers: true - target_branches: ${{ env.BACKPORT_BRANCH }} - source_pr_number: ${{ inputs.pull-request }} + echo "::error::Backport failed; resolve the conflict or prepare the target-specific fix manually." + exit 1 diff --git a/AGENTS.md b/AGENTS.md index b50bd9e1ca3..ecd79544487 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -8,10 +8,34 @@ guide for package-specific conventions and workflows. ## Package map - `cuda_pathfinder/`: Pure-Python library discovery and loading utilities. -- `cuda_bindings_13/`: Low-level CUDA host API bindings (Cython-heavy). +- `cuda_bindings_13/`: Current low-level CUDA host API bindings (Cython-heavy). +- `cuda_bindings_12/`: CUDA 12 maintenance bindings release line. - `cuda_core/`: High-level Pythonic CUDA APIs built on top of bindings. - `cuda_python/`: Metapackage and docs aggregation. +## Synchronized code blocks + +Use matching `BEGIN SYNCED ` and `END SYNCED ` comments for +deliberately duplicated snippets whose contents must remain byte-for-byte +identical. The group name identifies all copies; the boundaries define the +shared snippet, not the surrounding file. + +- Before editing a marked block, search from the repository root for its exact + `BEGIN SYNCED ` marker, for example with `rg -n -F`. Read every copy + and update them together, including copies outside the current package. +- Compare the complete marked blocks after editing. Also check required + imports and surrounding assumptions, such as relative directory depth, + which may live outside the markers. +- During review, identify groups touched by the diff and compare every copy, + including files absent from the diff. Use the base revision too when markers + were removed or renamed. Report drift, missing boundaries, and newly copied + snippets that omit the markers as review findings. +- Preserve both markers when copying a snippet. If a copy must diverge, + explain why and explicitly revise the group membership; do not remove or + rename a marker merely to conceal drift. +- In the work or review summary, name the groups and files compared, or state + why verification could not be completed. + # Git-derived version lifecycle Package versions are derived from reachable Git tags by `setuptools-scm`. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index dbb93955aa0..17207f00ebc 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -34,11 +34,8 @@ Thank you for your interest in contributing to CUDA Python! Based on the type of - [Developer Certificate of Origin (DCO)](#developer-certificate-of-origin-dco) - [CI infrastructure overview](#ci-infrastructure-overview) - [CI Pipeline Flow](#ci-pipeline-flow) - - [Pipeline Execution Details](#pipeline-execution-details) - - [Branch-specific Artifact Flow](#branch-specific-artifact-flow) - - [Main Branch](#main-branch) - - [Backport Branches](#backport-branches) - - [Key Infrastructure Details](#key-infrastructure-details) + - [CUDA-major Artifact Flow](#cuda-major-artifact-flow) + - [Release Branches](#release-branches) - [Code coverage](#code-coverage) @@ -374,36 +371,37 @@ The CUDA Python project uses a comprehensive CI pipeline that builds, tests, and The CI pipeline diagram is maintained as Mermaid source in [`ci/ci-pipeline.mmd`](ci/ci-pipeline.mmd). -### Pipeline Execution Details - -**Parallel Execution**: The CI pipeline leverages parallel execution to optimize build and test times: -- **Build Stage**: Different architectures/operating systems (linux-64, linux-aarch64, win-64) are built in parallel across their respective runners -- **Test Stage**: Different architectures/operating systems/CUDA versions are tested in parallel; documentation preview is also built in parallel with testing - -### Branch-specific Artifact Flow - -#### Main Branch -- **Build** → **Test** → **Documentation** → **Potential Release** -- Artifacts stored as `{component}-python{version}-{platform}-{sha}` -- Full test coverage across all platforms and CUDA versions -- **Artifact flow out**: `cuda-pathfinder` artifacts → backport branches - -#### Backport Branches -- **Build** → **Test** → **Backport PR Creation** -- Artifacts used for validation before creating backport pull requests -- Maintains compatibility with older CUDA versions -- **Artifact flow in**: `cuda-pathfinder` artifacts ← main branch -- **Artifact flow out**: older `cuda-bindings` artifacts → main branch - -### Key Infrastructure Details - -- **Self-hosted runners**: Used for Linux builds and GPU testing (more resources, faster builds) -- **GitHub-hosted runners**: Used for Windows builds and general tasks -- **Artifact retention**: 30 days for GitHub Artifacts (wheels, docs, tests) -- **Cache retention**: GitHub Cache for build dependencies and environments -- **Security**: All commits must be signed, untrusted code blocked -- **Parallel execution**: Matrix builds across Python versions and platforms -- **Component isolation**: Each component (core, bindings, pathfinder, python) can be built/released independently +The [CI workflow](.github/workflows/ci.yml) defines the supported platform, +Python, and CUDA matrices. Build and test jobs run in parallel across their +configured runners. Package selection and artifact validation are shared +through the [CI tools](ci/README.md). + +### CUDA-major Artifact Flow + +- CUDA 12.9 bindings live in `cuda_bindings_12/`; CUDA 13 bindings live in + `cuda_bindings_13/`. The registry assigns their maintenance and current roles. +- Development CI builds changed roots and affected dependents, reusing a + validated baseline for unaffected roots. Shared changes and scheduled runs + cover both CUDA majors. +- A bindings tag selects one line's bindings and metapackage. Its release + validation uses published Pathfinder and does not require a CUDA Core or + other-major release. +- Artifacts identify their Python version, toolkit, platform, and source SHA + where applicable. Release workflows require the exact tag's successful CI. + +### Release Branches + +`main` integrates changes for both supported majors. Short release branches +can stabilize a selected release or carry urgent fixes while development +continues. Return applicable fixes to `main` and assess both source roots. +The historical `12.9.x` branch stays frozen except for emergency fixes, +which must be reconciled into `main`. New main CI and releases do not fetch +package artifacts from that branch. + +The [bindings release guide](.github/RELEASE-bindings.md) covers release scope, +manual backport automation, source and control revisions, and validation. +The [CUDA 12 maintenance guide](cuda_bindings_12/MAINTENANCE.md) links the +shared regeneration and cross-root review policy. ## Code coverage diff --git a/ci/README.md b/ci/README.md index 772726cda6e..56c776f4c46 100644 --- a/ci/README.md +++ b/ci/README.md @@ -229,3 +229,128 @@ The canonical `NVIDIA/cuda-python` repository does not need this variable because its standard workflow behavior is enabled directly. Before enabling a customization elsewhere, document the repository-specific prerequisites and verification procedure in that repository's own documentation. + +## CUDA Bindings Package-Root Registry + +`ci/versions.yml` is the authoritative public registry for CUDA bindings +package roots. Each mapping key is a repository-relative package root; its +record declares an exact toolkit build/test pin and a `release_status` of +`current` or `maintenance`. Release routing uses the tag's CUDA major/minor +and the toolkit pin to select a root. Bindings and metapackage builds use +setuptools-scm's default tag parser. Each root's `git_describe_command` +selects its tag series for source builds; update its `--match` pattern when +the root moves to a new toolkit minor. + +The Python helpers share registry parsing and validation. The small, +repository-private `cuda-python-ci-tools` package installs their common +dependencies and makes those helpers importable from each build environment; +it is not part of a CUDA Python wheel. Release jobs check it out under +`.ci-control/ci` so the workflow can use its own tooling while inspecting a +different tagged source tree. Install it locally from the repository root: + +```console +python -m pip install -e ./ci +``` + +Use `ci.tools.bindings_config` instead of reading the YAML directly. It +validates the registry and emits normalized JSON with the configured values +plus the derived CTK target and CUDA ABI major/variant: + +```console +python -m ci.tools.bindings_config +python -m ci.tools.bindings_config --package-roots +python -m ci.tools.bindings_config --release-status current +``` + +Install the test extra to run the CI-tool tests: + +```console +python -m pip install -e './ci[test]' +python -m pytest --noconftest ci/tools/tests +``` + +The public wheel builder requires one `current` package root and one +`maintenance` package root with different CUDA ABI majors. +This is deliberately a two-line policy. The mapping keeps package paths out of +workflow conditionals; it does not promise arbitrary numbers of supported +lines. `cuda_bindings_12` names a stable ABI-major source tree, while `current` +and `maintenance` describe release roles that can change at the next major. + +The standalone `cuda-python` source distribution contains its own small tag +selector map because it cannot import repository CI tooling. The pre-commit +metadata check keeps those selectors, bindings packaging, and the maintenance +preview target aligned with the registry. Copying maintenance files does not +make their old branch an ancestor of `main`, so its later release tags are not +necessarily reachable. Until an appropriate tag is reachable, CI uses +`ci.tools.bindings_scm_version` to create a local preview tag in its disposable +checkout, then lets setuptools-scm derive the version normally. Existing +appropriate tags take precedence. The helper never pushes or moves tags; +local preview builds should use an independent clone so their temporary tags +do not affect other worktrees. Run the metadata check explicitly with: + +```console +python -m ci.tools.bindings_config --check-package-metadata +``` + +## Maintaining Both Bindings Roots + +`main` is the integration branch for both bindings release lines. The old +`12.9.x` branch stays frozen except for emergency fixes using compatible +historical tooling; reconcile any such fix into `cuda_bindings_12/` on `main`. +Routine CUDA 12 development belongs in that main-tree root. Short release +branches may stabilize a selected version or carry urgent fixes while `main` advances. +The [bindings release guide](../.github/RELEASE-bindings.md) describes branch +creation, backport automation, independent release validation, and returning +fixes to `main`. The +[CUDA 12 maintenance guide](../cuda_bindings_12/MAINTENANCE.md) identifies the +maintenance root. + +For generated bindings, change cybind first and regenerate each affected +package root against its intended toolkit inputs. Review the generated diff, +record the cybind revision, toolkit inputs, and command in the pull request, +and check modified files with +`python toolshed/check_generated_file_seals.py `. The seal verifies +the content of an individual generated file; it does not identify the cybind +revision or prove that the two roots should have identical output. Generated +output may legitimately differ across toolkit targets. + +For a handwritten bindings fix, inspect the corresponding code in the other +root. In the pull request, identify the matching change or explain concretely +why the fix does not apply there. A reviewer must verify that judgment: there +is no general deterministic check for semantic equivalence of handwritten +code across the two roots. Where files are intentionally identical, a narrowly +scoped byte-for-byte check can be added after establishing that invariant. + +Major-line maintenance can include deliberately selected compatibility work +such as a new Python version or a new API supported by that toolkit. A frozen +patch release has a narrower scope: fixes and release prerequisites approved +for that release. State which policy applies in the release checklist and +notes; a maintenance label alone does not promise a fixes-only release. + +Keep generator development and continuous toolkit qualification independent +of this source layout. A cybind change should be exercised against both +supported consumers before its generated output is imported. Record the +generator revision and toolkit inputs for each import, including any manual +post-generation adjustment. File seals establish content integrity, not +generation provenance. Moving QA directories or redesigning cybind asset +storage is not required to maintain both roots here. + +## Changing Supported Release Lines + +When support moves from CUDA 12/13 to CUDA 13/14, retain `cuda_bindings_13/` +as the maintenance source and introduce a distinct CUDA 14 root. Then: + +1. Update `ci/versions.yml`: remove the retired CUDA 12 root, mark the CUDA + 13 root `maintenance`, mark the CUDA 14 root `current`, and set each exact + toolkit build/test version. +2. Align each root's `pyproject.toml` `git_describe_command --match` selector + and any preview bootstrap target with its release family. Update per-root packaging, + pixi environments, documentation, and dependent package constraints for the + supported lines. +3. Build and test both roots and their dependent packages on the supported + platforms. Validate release selection and run publication-incapable dry + runs for tags from each line before releasing from the new layout. + +The same branch policy applies after the rollover: `main` integrates the +current and maintenance roots, short release branches stabilize releases, +and retired release branches are retained for history. diff --git a/ci/tools/bindings_config.py b/ci/tools/bindings_config.py index 12adfb32f64..f67c3067ed4 100644 --- a/ci/tools/bindings_config.py +++ b/ci/tools/bindings_config.py @@ -190,6 +190,8 @@ def _validate_release_statuses(packages: tuple[BindingsPackage, ...]) -> None: def validate_config(raw: Any) -> BindingsConfig: root = _mapping(raw, "versions configuration") root_keys = {"schema_version", "cuda", "python"} + # Earlier schema-2 release tags retain this field; keep reading their + # registries after the active backport workflow stops using it. if "backport_branch" in root: root_keys.add("backport_branch") _mapping(root, "versions configuration", root_keys) diff --git a/ci/tools/tests/test_bindings_config.py b/ci/tools/tests/test_bindings_config.py index 3c854d6d42d..8877574550b 100644 --- a/ci/tools/tests/test_bindings_config.py +++ b/ci/tools/tests/test_bindings_config.py @@ -299,6 +299,46 @@ def test_bindings_release_uses_registry_from_its_tag_tree( } +@pytest.mark.parametrize( + ("tag", "package_root", "toolkit_version", "release_version"), + ( + ("v12.9.8", "tag-maintenance", "12.9.1", "12.9.8"), + ("v13.4.2rc1", "tag-current", "13.4.1", "13.4.2rc1"), + ("cuda-core-v1.2.0", "tag-current", "13.4.1", None), + ("cuda-pathfinder-v1.1.0", "tag-current", "13.4.1", None), + ), +) +@pytest.mark.agent_authored(model="gpt-6.1-sol") +def test_release_cli_accepts_tagged_schema_two_registry_with_legacy_backport_branch( + tmp_path, capsys, tag, package_root, toolkit_version, release_version +): + release_root = tmp_path / "release" + registry = _registry("tag-maintenance", "tag-current") + registry["backport_branch"] = "12.9.x" + _write_config(release_root, registry) + control_root = tmp_path / "control" + _write_config(control_root, _registry("control-maintenance", "control-current")) + + assert ( + main( + [ + "--config", + str(control_root / "ci" / "versions.yml"), + "--release-tag", + tag, + "--release-source-root", + str(release_root), + ] + ) + == 0 + ) + + expected = {"package_root": package_root, "toolkit_version": toolkit_version} + if release_version is not None: + expected["release_version"] = release_version + assert json.loads(capsys.readouterr().out) == expected + + @pytest.mark.parametrize("tag", ("cuda-core-v1.2.0", "cuda-pathfinder-v1.1.0")) @pytest.mark.agent_authored(model="gpt-6-sol") def test_component_release_uses_current_bindings_from_its_tag_tree(tmp_path, tag): diff --git a/ci/versions.yml b/ci/versions.yml index c4df0886e71..83872f62b08 100644 --- a/ci/versions.yml +++ b/ci/versions.yml @@ -3,9 +3,6 @@ schema_version: 2 -# Retain until the legacy release and backport workflows stop reading this field. -backport_branch: "12.9.x" # keep in sync with target-branch in .github/dependabot.yml - cuda: bindings: package_roots: diff --git a/cuda_bindings_12/AGENTS.md b/cuda_bindings_12/AGENTS.md new file mode 100644 index 00000000000..f6c24d9e349 --- /dev/null +++ b/cuda_bindings_12/AGENTS.md @@ -0,0 +1,21 @@ +# CUDA 12 maintenance bindings + +This root maintains the CUDA 12.9 release line. Follow the repository-wide +instructions and [maintenance guide](MAINTENANCE.md). + +- Preserve the CUDA 12 generated source, build-time header parser, `.in` + templates, legacy APIs, and namespace redirector. The CUDA 13 source layout + and runtime extension list are different and must not replace these. +- Do not hand-edit generated bindings. Change cybind and regenerate against + the intended CUDA 12.9 inputs, recording provenance as described in + `../ci/README.md`. +- Source builds require CUDA 12.9 headers. `build_hooks.py` checks the first + `cuda.h` found through `CUDA_HOME` or `CUDA_PATH` before generating files. + Split toolkit installations remain supported through the existing path list. +- The shared toolchain and Cython cache helpers live in `_build_shared.py`, + linked to the current bindings root. Keep each package-local helper a symlink + or byte-for-byte copy. +- Assess handwritten fixes and build changes for both supported roots. + Preserve intentional differences in generated APIs and packaging. +- Use the package's `test` dependency group for Python tests. Build Cython tests + with `tests/cython/build_tests.sh` or `build_tests.bat` before running them. diff --git a/cuda_bindings_12/MAINTENANCE.md b/cuda_bindings_12/MAINTENANCE.md new file mode 100644 index 00000000000..dc565132e8e --- /dev/null +++ b/cuda_bindings_12/MAINTENANCE.md @@ -0,0 +1,23 @@ + + +# Maintaining the CUDA 12 bindings line + +`cuda_bindings_12/` is the CUDA 12.9 maintenance package root. The current +CUDA 13 bindings live in `cuda_bindings_13/`. The package roots and their release +statuses are configured in [`ci/versions.yml`](../ci/versions.yml). + +Integrate both release lines on `main`. The former `12.9.x` branch stays +frozen except for emergency fixes using compatible historical tooling; +reconcile those fixes into `cuda_bindings_12/`. Routine CUDA 12 fixes, tests, +and documentation belong in this main-tree root. Short release branches may +stabilize a release or carry an urgent fix; reconcile such fixes into `main` +and assess the CUDA 13 root too. + +Follow the [bindings release guide](../.github/RELEASE-bindings.md) for branch +selection, patch-release scope, backports, and release validation. + +Follow the [shared regeneration and review policy](../ci/README.md#maintaining-both-bindings-roots) +when changing implementation in either package root. diff --git a/cuda_core/AGENTS.md b/cuda_core/AGENTS.md index 63c6ce8dafa..b0e44ac1dd0 100644 --- a/cuda_core/AGENTS.md +++ b/cuda_core/AGENTS.md @@ -26,8 +26,8 @@ This file describes `cuda_core`, the high-level Pythonic CUDA subpackage in the dependency wiring. Logic shared with `cuda-bindings` (toolchain selection, the compiler flag set, the Cython cache helpers and the rebuild stamps) lives in `_build_shared.py`. `cuda_bindings_13/_build_shared.py` is canonical; - `cuda_core/_build_shared.py` must be either a symlink to it or a byte-for-byte - identical copy. + each package-local `_build_shared.py` must be a symlink to it or a byte-for-byte + identical copy, including maintenance bindings roots. ## Build and version coupling @@ -59,8 +59,9 @@ a bump. To bump: 1. Edit the `cuda-bindings` pin in the `cu12` or `cu13` extra in `pyproject.toml`. That is the only version to type. -2. Check `ci/versions.yml`. The `build` pin is the current major and the - `prev_build` pin is the prior major. Neither toolkit pin may sit below its +2. Check `ci/versions.yml`. Each entry under `cuda.bindings.package_roots` + declares its `toolkit_version` and `current` or `maintenance` release role. + Neither toolkit pin may sit below its floor's major.minor, or CI builds a configuration that the build rejects. A toolkit ahead of the floor is the bump window described below. The pre-commit hook `check-cuda-core-bindings-floor` diff --git a/cuda_python/AGENTS.md b/cuda_python/AGENTS.md index e4038dc5824..5b2c9858978 100644 --- a/cuda_python/AGENTS.md +++ b/cuda_python/AGENTS.md @@ -23,11 +23,12 @@ monorepo. ## Release coupling -- `setup.py` pins `cuda-core` to a minor series (`cuda-core~=X.Y.0`). Every - `cuda-core` release must bump that pin, and a `cuda-python` release should - follow right after, so that `pip install cuda-python` resolves to the new - `cuda-core`. The `cuda-core` release checklist (`.github/RELEASE-core.md`) - has this step. +- The current-major metapackage in `setup.py` pins `cuda-core` to a minor + series (`cuda-core~=X.Y.0`). The CUDA 12 metapackage depends only on bindings. + Every `cuda-core` release must bump that pin, and a `cuda-python` release + for the current major should follow right after, so that + `pip install cuda-python` resolves to the new `cuda-core`. The `cuda-core` + release checklist (`.github/RELEASE-core.md`) has this step. - Users should pin `cuda-python` alone. A separate `cuda-core` pin next to it can make the install unresolvable after a `cuda-core` release. - If you update docs structure, ensure `docs/build_all_docs.sh` still collects