From fe26e2ca7ee1f813394bffd7d839549b9a671836 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Fri, 30 Oct 2026 22:33:27 -0700 Subject: [PATCH 1/2] ci: release CUDA 12 bindings from main Signed-off-by: Ralf W. Grosse-Kunstleve --- .github/ISSUE_TEMPLATE/release_checklist.yml | 11 +- .github/RELEASE-bindings.md | 105 ++ .github/RELEASE-core.md | 46 +- .github/workflows/build-docs.yml | 158 +- .github/workflows/build-wheel.yml | 10 +- .github/workflows/ci.yml | 3 + .github/workflows/release-upload.yml | 61 +- .github/workflows/release.yml | 211 ++- .github/workflows/test-sdist-linux.yml | 2 +- .github/workflows/test-sdist-windows.yml | 2 +- .github/workflows/test-wheel-linux.yml | 4 +- .github/workflows/test-wheel-windows.yml | 4 +- .pre-commit-config.yaml | 2 +- ci/tools/bindings_config.py | 205 ++- ci/tools/check_release_notes.py | 287 ++- ci/tools/download-wheels | 131 +- ci/tools/env-vars | 2 +- ci/tools/lookup-run-id | 62 +- .../tests/test_bindings_release_compat.py | 129 ++ ci/tools/tests/test_check_release_notes.py | 476 ++--- ci/tools/tests/test_download_wheels.py | 135 ++ .../tests/test_validate_release_wheels.py | 218 +++ ci/tools/validate-release-wheels | 138 -- ci/tools/validate_release_wheels.py | 280 +++ cuda_bindings_13/docs/build_docs.sh | 9 +- cuda_bindings_13/pixi.lock | 1630 ++++++++++++----- cuda_bindings_13/pixi.toml | 3 +- cuda_python/docs/environment-docs.yml | 2 + toolshed/setup-docs-env.sh | 1 + 29 files changed, 3075 insertions(+), 1252 deletions(-) create mode 100644 .github/RELEASE-bindings.md create mode 100644 ci/tools/tests/test_bindings_release_compat.py create mode 100644 ci/tools/tests/test_download_wheels.py create mode 100644 ci/tools/tests/test_validate_release_wheels.py delete mode 100755 ci/tools/validate-release-wheels create mode 100644 ci/tools/validate_release_wheels.py diff --git a/.github/ISSUE_TEMPLATE/release_checklist.yml b/.github/ISSUE_TEMPLATE/release_checklist.yml index 12dad6fb716..8ed2df60e24 100644 --- a/.github/ISSUE_TEMPLATE/release_checklist.yml +++ b/.github/ISSUE_TEMPLATE/release_checklist.yml @@ -10,7 +10,7 @@ body: - type: markdown attributes: value: | - This checklist is for cuda-core releases as well as cuda-bindings patches. Please go through this checklist and ensure all tasks are completed. See [RELEASE-core.md](../RELEASE-core.md) for detailed guidance on each step (cuda.core). + This checklist is for cuda-core releases as well as cuda-bindings patches. See [RELEASE-core.md](../RELEASE-core.md) for cuda.core and [RELEASE-bindings.md](../RELEASE-bindings.md) for bindings release scope, stabilization branches, and validation. - type: checkboxes id: subpackage-tasks @@ -18,17 +18,18 @@ body: label: Tasks for cuda-core and cuda-bindings patch release options: - label: File an internal nvbug to communicate test plan & release schedule with QA - - label: Ensure all pending PRs are reviewed, tested, and merged + - label: Record the release scope and ensure all PRs selected for this release are reviewed, tested, and merged - label: Check (or update if needed) the dependency requirements - label: Sweep deprecations whose stated removal version has arrived (`grep -rn 'deprecated::' cuda_core/cuda`) and remove any that are due - label: "Finalize the doc update, including release notes (\"Note: Touching docstrings/type annotations in code is OK during code freeze, apply your best judgement!\")" - label: Update the docs for the new version - - label: Create a public release tag - - label: Wait for the tag-triggered CI run to complete, and use that run ID for release workflows (this will upload the release to PyPI) + - label: Record the exact source commit, workflow control revision, and selected package root before creating the approved public release tag + - label: Wait for the exact tag-triggered CI run to pass and complete a release dry run before approving publication - label: Publish the release at https://github.com/NVIDIA/cuda-python/releases (this will trigger the conda package update) - label: Approve the conda-package update PR - label: Post-release QA - label: Finalize the announcement update - label: Send out the announcement internally (on `#swcuda-python`) - label: Send out the announcement externally (GitHub Release -> Announcement) - - label: For a `cuda-bindings` release, make sure MAJOR and MAJOR-1 releases are made, as well as releases of `cuda-python` for MAJOR and MAJOR-1 + - label: For a `cuda-bindings` release, confirm which supported release lines are in scope using `ci/versions.yml`, and release the matching `cuda-python` package for each planned line + - label: For a bindings stabilization or emergency branch, link the PRs returning applicable fixes to `main` and record their applicability to both bindings roots diff --git a/.github/RELEASE-bindings.md b/.github/RELEASE-bindings.md new file mode 100644 index 00000000000..5e3373effb4 --- /dev/null +++ b/.github/RELEASE-bindings.md @@ -0,0 +1,105 @@ + + +# 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 in a separate PR. Inspect the diff, request CI using the normal PR +approval procedure, and review it before merging. 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. + +## 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. + Tag-triggered CI builds both bindings lines and their consumers. The release + workflow selects only the requested line's bindings or metapackage 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. After both component releases succeed, review and publish the shared + `vX.Y.Z` GitHub Release draft. Check its release notes, versioned + documentation links, source archive, checksum, and wheels. These component + workflows leave the draft for the release owner to publish. +7. 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. + +For either bindings line, add the released version to +[`cuda_bindings_13/docs/nv-versions.json`](../cuda_bindings_13/docs/nv-versions.json) +and its matching metapackage version to +[`cuda_python/docs/nv-versions.json`](../cuda_python/docs/nv-versions.json) +on `main`. Documentation deployments from `main` own these shared version +selectors. Release deployments publish versioned pages without replacing the +selectors or shared `latest` pages; updating a selector only on a stabilization +branch will not update the public selector. + +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. Retained CUDA 13 tags also support the +older `cuda.build.version` configuration, the `cuda_bindings` source directory, +and their original build matrix and metapackage artifact name. New CUDA 12 +releases require the local `cuda_bindings_12` root and toolkit-qualified +artifacts. The workflow control revision never supplies missing tagged toolkit +settings or replaces tagged release notes. Older CUDA 12 branch releases use +their compatible historical tooling. + +In **CI: Release**, normal bindings and metapackage releases each require +their own exact-version, nonempty release notes in the tagged source. Notes +from the workflow control revision or a different component cannot fill a gap. +Preserve their 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/RELEASE-core.md b/.github/RELEASE-core.md index 790c79c3e92..6be2c4dd9b2 100644 --- a/.github/RELEASE-core.md +++ b/.github/RELEASE-core.md @@ -3,11 +3,10 @@ # cuda.core Release Process -This document covers the `cuda.core` release process. For other packages: -`cuda-bindings` and `cuda-python` involve a private repository and are not -documented here; `cuda-pathfinder` is largely automated by the -[CI: Release](workflows/release.yml) -workflow. +This document covers the `cuda.core` release process. See the +[bindings release guide](RELEASE-bindings.md) for `cuda-bindings` and +`cuda-python`. The `cuda-pathfinder` release process is largely automated by +the [CI: Release](workflows/release.yml) workflow. To release `cuda-pathfinder`, dispatch **CI: Release** with `component` set to `cuda-pathfinder`, `release-action` set @@ -20,12 +19,13 @@ version, then publishes to PyPI and verifies again before publishing the GitHub Release without marking it as latest. A failed docs build prevents asset uploads, package publication, and finalization. -The release-note checker runs from `git-tag`, not the workflow revision. -For Pathfinder, that tag must contain a version -of `ci/tools/check_release_notes.py` that writes `version=` to -`GITHUB_OUTPUT`. The release-notes job rejects an empty version before -documentation, asset uploads, or package publication can start. Pathfinder -package publication also requires successful draft metadata preparation. +The workflow revision supplies the release tools; release notes and the +package registry (`ci/versions.yml`) come from `git-tag`. Current tooling +uses the toolkit configuration in the tagged source, including retained CUDA 13 +sources that predate the package-root registry. The release-notes job exports +the checked version and rejects an empty version before documentation, asset +uploads, or package publication can start. Pathfinder package publication also +requires successful draft metadata preparation. Existing tags stay immutable. The default `dry-run` action validates preparation, builds docs, and collects release artifacts without creating a GitHub Release or publishing @@ -174,21 +174,29 @@ Pushing the tag triggers a CI run automatically. Monitor it in the ## Upload wheels to PyPI -This is a single `CI: Release` workflow run with two sequential stages: -publish to TestPyPI, then publish the same wheel set to PyPI. +First validate the release with a dry run. After reviewing that result, a +`full-release` run publishes to TestPyPI, then publishes the same wheel set to +PyPI. 1. Go to **Actions > CI: Release** and run the workflow with: - **Component**: `cuda-core` - **The release git tag**: `cuda-core-v0.6.0` + - **What to run**: `dry-run` - The workflow automatically looks up the successful tag-triggered CI run - for the selected release tag. + Leave `run-id` blank to exercise automatic lookup of the successful + tag-triggered CI run. Leave `dry-run-docs-branch` blank to validate the docs + without deploying them. -2. Wait for the workflow to complete. It will: - - publish the selected wheels to TestPyPI - - publish the same wheel set to PyPI +2. Review the completed dry run, then approve publication under the team's + release procedure and run the workflow for the same component and tag with + **What to run** set to `full-release`. -3. After completion, verify the final PyPI upload: +3. Wait for that run to complete. It deploys versioned documentation and uploads + the source archive, checksum, and wheels to the GitHub Release draft. It + publishes the selected wheel set to TestPyPI followed by PyPI. The release + owner publishes the GitHub Release draft in the announcement step. + +4. After completion, verify the final PyPI upload: ```bash pip install cuda-core==0.6.0 diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index b734fdd8c73..75ebd893b15 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -43,6 +43,11 @@ on: required: false default: "gh-pages" type: string + bindings-package: + description: "Resolved CUDA bindings package JSON" + required: false + default: "" + type: string jobs: build: @@ -62,23 +67,50 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: fetch-depth: 1 - ref: ${{ inputs.git-tag }} + persist-credentials: false + ref: ${{ inputs.is-release && format('refs/tags/{0}', inputs.git-tag) || inputs.git-tag }} - - name: Read build CTK version + # Release sources and workflow tools can come from different commits. + # Keep the shared CI helpers at this workflow revision while reading + # package paths and toolkit settings from the checked-out release tag. + - name: Checkout docs control plane + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + ref: ${{ github.sha }} + path: .ci-control + persist-credentials: false + + - name: Set up Python for CI tools + # The release checkout can predate this action; use the workflow revision. + uses: ./.ci-control/.github/actions/setup-hardened-python + with: + python-version: "3.12" + + - name: Install CI tool dependencies + # Keep the hardened interpreter ahead of any login-shell activation. + shell: bash --noprofile --norc -euo pipefail {0} + run: python3 -m pip install -e ./.ci-control/ci + + - name: Resolve CUDA bindings package + shell: bash --noprofile --norc -euo pipefail {0} + env: + BINDINGS_PACKAGE: ${{ inputs.bindings-package }} + IS_RELEASE: ${{ inputs.is-release }} + RELEASE_TAG: ${{ inputs.git-tag }} run: | - if [[ -f ci/versions.yml ]]; then - BUILD_CTK_VER=$(yq '.cuda.build.version' ci/versions.yml) - elif [[ -f ci/versions.json ]]; then - BUILD_CTK_VER=$(jq -r '.cuda.build.version' ci/versions.json) + set -euo pipefail + if [[ -n "$BINDINGS_PACKAGE" ]]; then + resolved_bindings_package="$BINDINGS_PACKAGE" + elif [[ "${IS_RELEASE}" == "true" ]]; then + resolved_bindings_package=$(cd .ci-control && python3 -m ci.tools.bindings_config \ + --release-tag "$RELEASE_TAG" \ + --release-source-root ..) else - echo "error: cannot find ci/versions.yml or ci/versions.json" >&2 - exit 1 + resolved_bindings_package=$(cd .ci-control && python3 -m ci.tools.bindings_config \ + --release-status current) fi - if [[ ! "${BUILD_CTK_VER}" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then - echo "error: derived CTK build version ${BUILD_CTK_VER} does not match MAJOR.MINOR.MICRO" >&2 - exit 1 - fi - echo "BUILD_CTK_VER=${BUILD_CTK_VER}" >> "$GITHUB_ENV" + (cd .ci-control && python3 -m ci.tools.bindings_config \ + write-github-env "$GITHUB_ENV" <<< "$resolved_bindings_package") # TODO: This workflow runs on GH-hosted runner and cannot use the proxy cache @@ -86,7 +118,7 @@ jobs: uses: conda-incubator/setup-miniconda@be893c923ea9cf1cf7cd510fbdde27c7e18cbdcb # v4.1.0 with: activate-environment: cuda-python-docs - environment-file: ./cuda_python/docs/environment-docs.yml + environment-file: ./.ci-control/cuda_python/docs/environment-docs.yml miniforge-version: latest conda-remove-defaults: "true" python-version: 3.12 @@ -106,24 +138,16 @@ jobs: cuda-version: ${{ env.BUILD_CTK_VER }} - name: Set environment variables + env: + IS_RELEASE: ${{ inputs.is-release }} + RELEASE_TAG: ${{ inputs.git-tag }} run: | PYTHON_VERSION_FORMATTED="312" # see above REPO_DIR=$(pwd) - # Release docs may check out tags from before the source-root rename. - if [[ -d cuda_bindings_13 ]]; then - CUDA_BINDINGS_SOURCE_DIR=cuda_bindings_13 - elif [[ -d cuda_bindings ]]; then - CUDA_BINDINGS_SOURCE_DIR=cuda_bindings - else - echo "error: cannot find the cuda.bindings source directory" >&2 - exit 1 - fi - echo "CUDA_BINDINGS_SOURCE_DIR=${CUDA_BINDINGS_SOURCE_DIR}" >> "$GITHUB_ENV" - - if [[ ${{ inputs.is-release }} == "true" ]]; then + if [[ "$IS_RELEASE" == "true" ]]; then FILE_HASH="*" - DOCS_GITHUB_REF="${{ inputs.git-tag }}" + DOCS_GITHUB_REF="$RELEASE_TAG" if [[ -z "${DOCS_GITHUB_REF}" ]]; then DOCS_GITHUB_REF="${GITHUB_REF_NAME}" fi @@ -132,6 +156,8 @@ jobs: DOCS_GITHUB_REF=$(python ci/tools/checkout_source_links.py --github-ref) fi + echo "CUDA_BINDINGS_SOURCE_DIR=${BINDINGS_PACKAGE_ROOT}" >> "$GITHUB_ENV" + # make outputs from the previous job as env vars CUDA_CORE_ARTIFACT_BASENAME="cuda-core-python${PYTHON_VERSION_FORMATTED}-linux-64" echo "CUDA_PYTHON_DOCS_GITHUB_REF=${DOCS_GITHUB_REF}" >> $GITHUB_ENV @@ -141,22 +167,40 @@ jobs: CUDA_BINDINGS_ARTIFACT_BASENAME="cuda-bindings-python${PYTHON_VERSION_FORMATTED}-cuda${BUILD_CTK_VER}-linux-64" echo "CUDA_BINDINGS_ARTIFACT_BASENAME=${CUDA_BINDINGS_ARTIFACT_BASENAME}" >> $GITHUB_ENV echo "CUDA_BINDINGS_ARTIFACT_NAME=${CUDA_BINDINGS_ARTIFACT_BASENAME}-${FILE_HASH}" >> $GITHUB_ENV - echo "CUDA_BINDINGS_ARTIFACTS_DIR=$(realpath "$REPO_DIR/$CUDA_BINDINGS_SOURCE_DIR/dist")" >> $GITHUB_ENV + echo "CUDA_BINDINGS_ARTIFACTS_DIR=$(realpath "$REPO_DIR/${BINDINGS_PACKAGE_ROOT}/dist")" >> $GITHUB_ENV + CUDA_PYTHON_ARTIFACT_NAME="cuda-python-wheel-cuda${BUILD_CTK_VER}" + echo "CUDA_PYTHON_ARTIFACT_NAME=${CUDA_PYTHON_ARTIFACT_NAME}" >> $GITHUB_ENV - name: Download cuda-python build artifacts + if: ${{ !inputs.is-release }} uses: $/.github/actions/download-artifact-retry with: - name: cuda-python-wheel + name: ${{ env.CUDA_PYTHON_ARTIFACT_NAME }} path: . run-id: ${{ inputs.run-id }} github-token: ${{ github.token }} + - name: Download cuda-python release artifacts + if: ${{ inputs.is-release && (inputs.component == 'all' || inputs.component == 'cuda-python') }} + shell: bash --noprofile --norc -euo pipefail {0} + env: + GH_TOKEN: ${{ github.token }} + RELEASE_RUN_ID: ${{ inputs.run-id }} + RELEASE_TAG: ${{ inputs.git-tag }} + RELEASE_REPOSITORY: ${{ github.repository }} + run: | + ./.ci-control/ci/tools/download-wheels \ + "$RELEASE_RUN_ID" cuda-python "$RELEASE_REPOSITORY" . \ + "$RELEASE_TAG" "$RESOLVED_BINDINGS_PACKAGE" + - name: Display structure of downloaded cuda-python artifacts + if: ${{ !inputs.is-release || inputs.component == 'all' || inputs.component == 'cuda-python' }} run: | pwd ls -lahR . - name: Download cuda-pathfinder build artifacts + if: ${{ !inputs.is-release || inputs.component == 'all' || inputs.component == 'cuda-pathfinder' || inputs.component == 'cuda-core' }} uses: $/.github/actions/download-artifact-retry with: name: cuda-pathfinder-wheel @@ -165,6 +209,7 @@ jobs: github-token: ${{ github.token }} - name: Display structure of downloaded cuda-pathfinder artifacts + if: ${{ !inputs.is-release || inputs.component == 'all' || inputs.component == 'cuda-pathfinder' || inputs.component == 'cuda-core' }} run: | pwd ls -lahR cuda_pathfinder @@ -177,7 +222,7 @@ jobs: path: ${{ env.CUDA_BINDINGS_ARTIFACTS_DIR }} - name: Download cuda.bindings build artifacts - if: ${{ inputs.is-release }} + if: ${{ inputs.is-release && (inputs.component == 'all' || inputs.component == 'cuda-bindings' || inputs.component == 'cuda-core') }} uses: $/.github/actions/download-artifact-retry with: pattern: ${{ env.CUDA_BINDINGS_ARTIFACT_NAME }} @@ -187,6 +232,7 @@ jobs: github-token: ${{ github.token }} - name: Display structure of downloaded cuda.bindings artifacts + if: ${{ !inputs.is-release || inputs.component == 'all' || inputs.component == 'cuda-bindings' || inputs.component == 'cuda-core' }} run: | pwd ls -lahR $CUDA_BINDINGS_ARTIFACTS_DIR @@ -199,7 +245,7 @@ jobs: path: ${{ env.CUDA_CORE_ARTIFACTS_DIR }} - name: Download cuda.core build artifacts - if: ${{ inputs.is-release }} + if: ${{ inputs.is-release && (inputs.component == 'all' || inputs.component == 'cuda-core') }} uses: $/.github/actions/download-artifact-retry with: pattern: ${{ env.CUDA_CORE_ARTIFACT_NAME }} @@ -209,26 +255,37 @@ jobs: github-token: ${{ github.token }} - name: Display structure of downloaded cuda.core build artifacts + if: ${{ !inputs.is-release || inputs.component == 'all' || inputs.component == 'cuda-core' }} run: | pwd ls -lahR $CUDA_CORE_ARTIFACTS_DIR - - name: Install all packages + - name: Install cuda-pathfinder + if: ${{ !inputs.is-release || inputs.component == 'all' || inputs.component == 'cuda-pathfinder' || inputs.component == 'cuda-core' }} run: | pushd cuda_pathfinder pip install *.whl popd + - name: Install cuda.bindings + if: ${{ !inputs.is-release || inputs.component == 'all' || inputs.component == 'cuda-bindings' || inputs.component == 'cuda-core' }} + run: | pushd "${CUDA_BINDINGS_ARTIFACTS_DIR}" pip install *.whl popd + - name: Install cuda.core + if: ${{ !inputs.is-release || inputs.component == 'all' || inputs.component == 'cuda-core' }} + run: | pushd "${CUDA_CORE_ARTIFACTS_DIR}" pip install *.whl popd - # Subpackages are already installed from CI artifacts above. - # --no-deps avoids re-resolving cuda-core from PyPI during tag releases. + - name: Install cuda-python + if: ${{ !inputs.is-release || inputs.component == 'all' || inputs.component == 'cuda-python' }} + run: | + # Documentation builds do not exercise runtime dependencies. + # --no-deps also avoids resolving artifacts absent from focused tag runs. pip install --no-deps cuda_python*.whl # PR CI uses pull-request/ refs regardless of the target branch. @@ -252,9 +309,11 @@ jobs: - name: Build all docs if: ${{ inputs.component == 'all' }} + env: + IS_RELEASE: ${{ inputs.is-release }} run: | pushd cuda_python/docs/ - if [[ "${{ inputs.is-release }}" == "false" ]]; then + if [[ "$IS_RELEASE" == "false" ]]; then ./build_all_docs.sh latest-only else ./build_all_docs.sh @@ -271,13 +330,20 @@ jobs: - name: Build component docs if: ${{ inputs.component != 'all' }} + env: + DOCS_COMPONENT: ${{ inputs.component }} + IS_RELEASE: ${{ inputs.is-release }} run: | - COMPONENT=$(echo "${{ inputs.component }}" | tr '-' '_') - if [[ "${{ inputs.component }}" == "cuda-bindings" ]]; then - COMPONENT="${CUDA_BINDINGS_SOURCE_DIR}" + case "$DOCS_COMPONENT" in + cuda-bindings|cuda-core|cuda-pathfinder|cuda-python) ;; + *) echo "error: unsupported docs component: $DOCS_COMPONENT" >&2; exit 1 ;; + esac + COMPONENT="${DOCS_COMPONENT//-/_}" + if [[ "$DOCS_COMPONENT" == "cuda-bindings" ]]; then + COMPONENT="${BINDINGS_PACKAGE_ROOT}" fi - pushd ${COMPONENT}/docs/ - if [[ "${{ inputs.is-release }}" == "false" ]]; then + pushd "${COMPONENT}/docs/" + if [[ "$IS_RELEASE" == "false" ]]; then ./build_docs.sh latest-only else ./build_docs.sh @@ -290,13 +356,13 @@ jobs: fi ls -l build popd - if [[ "${{ inputs.component }}" != "cuda-python" ]]; then - TARGET="${{ inputs.component }}" - mkdir -p artifacts/docs/${TARGET} + if [[ "$DOCS_COMPONENT" != "cuda-python" ]]; then + TARGET="$DOCS_COMPONENT" + mkdir -p "artifacts/docs/${TARGET}" else TARGET="" fi - mv ${COMPONENT}/docs/build/html/* artifacts/docs/${TARGET} + mv "${COMPONENT}"/docs/build/html/* "artifacts/docs/${TARGET}" # Check links and anchors in the rendered HTML built above. # Links in authored Markdown and reST files are checked separately by the @@ -305,7 +371,7 @@ jobs: # interpreter instead of the conda environment used above. - name: Set up Python for link checks if: ${{ !inputs.is-release && startsWith(github.ref_name, 'pull-request/') }} - uses: ./.github/actions/setup-hardened-python + uses: ./.ci-control/.github/actions/setup-hardened-python with: python-version: "3.14" @@ -363,7 +429,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: fetch-depth: 1 - ref: ${{ inputs.git-tag }} + ref: ${{ inputs.is-release && format('refs/tags/{0}', inputs.git-tag) || inputs.git-tag }} - name: Download docs deployment payload uses: $/.github/actions/download-artifact-retry diff --git a/.github/workflows/build-wheel.yml b/.github/workflows/build-wheel.yml index 045cd4612ca..bc6d43a2392 100644 --- a/.github/workflows/build-wheel.yml +++ b/.github/workflows/build-wheel.yml @@ -435,7 +435,7 @@ jobs: if: ${{ !inputs.single-cuda-major && (env.BUILD_PYTHON == 'true' || env.TEST_PYTHON == 'true') && strategy.job-index == 0 && inputs.host-platform == 'linux-64' }} uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 with: - name: maintenance-python-wheel + name: cuda-python-wheel-cuda${{ env.MAINTENANCE_CUDA_VERSION }} path: cuda_python/dist/cu${{ env.MAINTENANCE_CUDA_MAJOR }}/*.whl if-no-files-found: error @@ -468,6 +468,14 @@ jobs: ls -lahR cuda_python - name: Upload cuda-python build artifacts + if: ${{ strategy.job-index == 0 && inputs.host-platform == 'linux-64' }} + uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 + with: + name: cuda-python-wheel-cuda${{ inputs.cuda-version }} + path: cuda_python/*.whl + if-no-files-found: error + + - name: Upload legacy cuda-python artifact alias if: ${{ strategy.job-index == 0 && inputs.host-platform == 'linux-64' }} uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 with: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f9199e77473..e970cd1e95d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -657,6 +657,9 @@ jobs: secrets: inherit uses: ./.github/workflows/build-docs.yml with: + component: ${{ github.ref_type == 'tag' && startsWith(github.ref_name, 'v') && 'cuda-bindings' || 'all' }} + git-tag: ${{ github.ref_type == 'tag' && github.ref_name || '' }} + run-id: ${{ github.run_id }} is-release: ${{ github.ref_type == 'tag' }} deploy-docs: ${{ github.ref_type != 'tag' }} diff --git a/.github/workflows/release-upload.yml b/.github/workflows/release-upload.yml index 6c227d74f77..3518ef16d4f 100644 --- a/.github/workflows/release-upload.yml +++ b/.github/workflows/release-upload.yml @@ -23,6 +23,11 @@ on: type: boolean required: false default: false + bindings-package: + description: "Resolved CUDA bindings package JSON" + type: string + required: false + default: "" concurrency: # Keep upload locks component-specific and separate from the caller's workflow lock. @@ -40,12 +45,30 @@ jobs: runs-on: ubuntu-latest env: ARCHIVE_NAME: ${{ github.event.repository.name }}-${{ inputs.git-tag }} + RELEASE_COMPONENT: ${{ inputs.component }} + RELEASE_GIT_TAG: ${{ inputs.git-tag }} + RELEASE_REPOSITORY: ${{ github.repository }} + RELEASE_RUN_ID: ${{ inputs.run-id }} steps: - - name: Checkout Source + - name: Checkout release control plane uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: fetch-depth: 1 - ref: ${{ inputs.git-tag }} + fetch-tags: true + + - name: Checkout release source + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + ref: refs/tags/${{ inputs.git-tag }} + path: release-source + + - name: Set up Python + uses: ./.github/actions/setup-hardened-python + with: + python-version: "3.12" + + - name: Install CI tool dependencies + run: python -m pip install -e ./ci - name: Create Release Directory run: mkdir -p release @@ -54,15 +77,15 @@ jobs: run: > git archive --format=tar.gz - --prefix="${{ env.ARCHIVE_NAME }}/" - --output="release/${{ env.ARCHIVE_NAME }}.tar.gz" - ${{ inputs.git-tag }} + --prefix="$ARCHIVE_NAME/" + --output="release/$ARCHIVE_NAME.tar.gz" + "refs/tags/$RELEASE_GIT_TAG" - name: Compute Checksum run: > - sha256sum "release/${{ env.ARCHIVE_NAME }}.tar.gz" + sha256sum "release/$ARCHIVE_NAME.tar.gz" | awk '{print $1}' - > "release/${{ env.ARCHIVE_NAME }}.tar.gz.sha256sum" + > "release/$ARCHIVE_NAME.tar.gz.sha256sum" - name: Upload Archive if: ${{ !inputs.dry-run }} @@ -70,19 +93,31 @@ jobs: GH_TOKEN: ${{ github.token }} run: > gh release upload - --clobber "${{ inputs.git-tag }}" - --repo "${{ github.repository }}" + --clobber "$RELEASE_GIT_TAG" + --repo "$RELEASE_REPOSITORY" release/* - name: Download and Validate Wheels env: + BINDINGS_PACKAGE: ${{ inputs.bindings-package }} GH_TOKEN: ${{ github.token }} run: | # Use the shared script to download wheels - ./ci/tools/download-wheels "${{ inputs.run-id }}" "${{ inputs.component }}" "${{ github.repository }}" "release/wheels" + ./ci/tools/download-wheels \ + "$RELEASE_RUN_ID" \ + "$RELEASE_COMPONENT" \ + "$RELEASE_REPOSITORY" \ + "release/wheels" \ + "$RELEASE_GIT_TAG" \ + "$BINDINGS_PACKAGE" # Validate that release wheels match the expected version from tag. - ./ci/tools/validate-release-wheels "${{ inputs.git-tag }}" "${{ inputs.component }}" "release/wheels" + python -m ci.tools.validate_release_wheels \ + "$RELEASE_GIT_TAG" \ + "$RELEASE_COMPONENT" \ + "release/wheels" \ + --bindings-package "$BINDINGS_PACKAGE" \ + --release-source-root release-source - name: Upload Wheels if: ${{ !inputs.dry-run }} @@ -90,8 +125,8 @@ jobs: GH_TOKEN: ${{ github.token }} run: | if [[ -d "release/wheels" && $(ls -A release/wheels 2>/dev/null | wc -l) -gt 0 ]]; then - echo "Uploading wheels to release ${{ inputs.git-tag }}" - gh release upload --clobber "${{ inputs.git-tag }}" --repo "${{ github.repository }}" release/wheels/* + echo "Uploading wheels to release $RELEASE_GIT_TAG" + gh release upload --clobber "$RELEASE_GIT_TAG" --repo "$RELEASE_REPOSITORY" release/wheels/* fi - name: Upload dry-run release artifacts diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index dc466827046..c1bc471ca93 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -10,26 +10,10 @@ name: "CI: Release" # without publishing to external release surfaces. # Pathfinder additionally prepares metadata, verifies both indexes, and publishes its draft. # -# Maintenance note: non-trivial changes to this workflow should be validated -# with dry-run workflow_dispatch runs before merging. Suggested focused matrix: -# - mainline: -# component=cuda-bindings -# git-tag= -# backport-git-tag=not planned -# run-id= -# dry-run-docs-branch=gh-pages-dry-run -# - backport sequence: -# 1. component=cuda-bindings -# git-tag= -# backport-git-tag= -# 2. component=cuda-python -# git-tag= -# backport-git-tag= -# run-id= -# dry-run-docs-branch=gh-pages-dry-run -# Leave run-id blank so determine-run-id is exercised. For exhaustive coverage, -# add a mainline cuda-python dry-run when changes could affect metapackage -# artifact validation, docs routing, or component-specific release behavior. +# Maintenance note: validate non-trivial changes with dry-run workflow_dispatch +# runs for bindings and metapackage tags from both maintenance and current packages. Leave +# run-id blank so automatic tag-run discovery, artifact filtering, and version +# validation are exercised. # Also exercise cuda-core and cuda-pathfinder, including a failed docs build. on: @@ -56,11 +40,6 @@ on: description: "The release git tag" required: true type: string - backport-git-tag: - description: "Mainline cuda-bindings/cuda-python only: planned backport tag, or 'not planned'. Leave blank for backport releases." - required: false - type: string - default: "" run-id: description: "The GHA run ID that generated validated artifacts (optional - auto-detects successful tag-triggered CI run for git-tag)" required: false @@ -82,6 +61,39 @@ defaults: shell: bash --noprofile --norc -xeuo pipefail {0} jobs: + resolve-bindings-package: + if: ${{ github.repository_owner == 'nvidia' }} + runs-on: ubuntu-latest + outputs: + bindings-package: ${{ steps.resolve.outputs.bindings-package }} + steps: + - name: Checkout release control plane + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + + - name: Checkout release source + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + ref: refs/tags/${{ inputs.git-tag }} + path: release-source + + - name: Set up Python + uses: ./.github/actions/setup-hardened-python + with: + python-version: "3.12" + + - name: Install CI tool dependencies + run: python -m pip install -e ./ci + + - name: Resolve bindings release package + id: resolve + env: + RELEASE_TAG: ${{ inputs.git-tag }} + run: | + bindings_package=$(python -m ci.tools.bindings_config \ + --release-tag "$RELEASE_TAG" \ + --release-source-root release-source) + echo "bindings-package=${bindings_package}" >> "$GITHUB_OUTPUT" + determine-run-id: if: ${{ github.repository_owner == 'nvidia' }} runs-on: ubuntu-latest @@ -100,20 +112,24 @@ jobs: env: GH_TOKEN: ${{ github.token }} RELEASE_GIT_TAG: ${{ inputs.git-tag }} - PROVIDED_RUN_ID: ${{ inputs.run-id }} RELEASE_REPOSITORY: ${{ github.repository }} + REQUESTED_RUN_ID: ${{ inputs.run-id }} run: | - if [[ -n "$PROVIDED_RUN_ID" ]]; then - echo "Using provided run ID: $PROVIDED_RUN_ID" - RUN_ID="$PROVIDED_RUN_ID" + if [[ -n "$REQUESTED_RUN_ID" ]]; then + echo "Validating provided run ID: $REQUESTED_RUN_ID" + RUN_ID=$(./ci/tools/lookup-run-id \ + --tag "$RELEASE_GIT_TAG" \ + --run-id "$REQUESTED_RUN_ID" \ + "$RELEASE_REPOSITORY") else echo "Auto-detecting successful tag-triggered run ID for tag: $RELEASE_GIT_TAG" - RUN_ID=$(./ci/tools/lookup-run-id "$RELEASE_GIT_TAG" "$RELEASE_REPOSITORY") + RUN_ID=$(./ci/tools/lookup-run-id --tag "$RELEASE_GIT_TAG" "$RELEASE_REPOSITORY") echo "Auto-detected run ID: $RUN_ID" fi echo "run-id=$RUN_ID" >> "$GITHUB_OUTPUT" check-tag: + needs: resolve-bindings-package if: ${{ github.repository_owner == 'nvidia' }} runs-on: ubuntu-latest steps: @@ -129,6 +145,7 @@ jobs: GH_TOKEN: ${{ github.token }} RELEASE_ACTION: ${{ inputs.release-action }} RELEASE_GIT_TAG: ${{ inputs.git-tag }} + RELEASE_REPOSITORY: ${{ github.repository }} DRY_RUN_DOCS_BRANCH: ${{ inputs.dry-run-docs-branch }} run: | if [[ "$RELEASE_ACTION" == "full-release" && -n "$DRY_RUN_DOCS_BRANCH" ]]; then @@ -139,19 +156,21 @@ jobs: echo "error: dry-run-docs-branch must be a non-production gh-pages-* branch" >&2 exit 1 fi + git check-ref-format "refs/tags/$RELEASE_GIT_TAG" + git rev-parse --verify "refs/tags/${RELEASE_GIT_TAG}^{commit}" + if [[ "$RELEASE_ACTION" == "dry-run" ]]; then - git rev-parse --verify "${RELEASE_GIT_TAG}^{commit}" echo "Dry-run selected; not checking or creating a GitHub release draft." exit 0 fi - mapfile -t tags < <(gh release list -R "${{ github.repository }}" --json tagName --jq '.[] | .tagName') - mapfile -t is_draft < <(gh release list -R "${{ github.repository }}" --json isDraft --jq '.[] | .isDraft') + mapfile -t tags < <(gh release list -R "$RELEASE_REPOSITORY" --json tagName --jq '.[] | .tagName') + mapfile -t is_draft < <(gh release list -R "$RELEASE_REPOSITORY" --json isDraft --jq '.[] | .isDraft') found=0 for idx in "${!tags[@]}"; do - if [[ "${tags[$idx]}" == "${{ inputs.git-tag }}" ]]; then - echo "found existing release for ${{ inputs.git-tag }}" + if [[ "${tags[$idx]}" == "$RELEASE_GIT_TAG" ]]; then + echo "found existing release for $RELEASE_GIT_TAG" found=1 if [[ "${is_draft[$idx]}" != "true" ]]; then echo "the release note is not in draft state" @@ -161,39 +180,51 @@ jobs: fi done if [[ "$found" == 0 ]]; then - echo "no release found for ${{ inputs.git-tag }}, creating draft release" - gh release create "${{ inputs.git-tag }}" --draft --repo "${{ github.repository }}" --title "Release ${{ inputs.git-tag }}" --notes "Release ${{ inputs.git-tag }}" + echo "no release found for $RELEASE_GIT_TAG, creating draft release" + gh release create "$RELEASE_GIT_TAG" \ + --verify-tag \ + --draft \ + --repo "$RELEASE_REPOSITORY" \ + --title "Release $RELEASE_GIT_TAG" \ + --notes "Release $RELEASE_GIT_TAG" fi check-release-notes: if: ${{ github.repository_owner == 'nvidia' }} runs-on: ubuntu-latest + needs: resolve-bindings-package outputs: version: ${{ steps.release-notes.outputs.version }} steps: - - name: Checkout Source + - name: Checkout release control plane + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + + - name: Checkout release source uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: - ref: ${{ inputs.git-tag }} + ref: refs/tags/${{ inputs.git-tag }} + path: release-source - name: Set up Python - # $/ resolves at the workflow's commit. ./ would resolve against the - # release tag checkout, which can predate this action. - uses: $/.github/actions/setup-hardened-python + uses: ./.github/actions/setup-hardened-python with: python-version: "3.12" + - name: Install CI tool dependencies + run: python -m pip install -e ./ci + - name: Check versioned release notes exist id: release-notes env: - RELEASE_GIT_TAG: ${{ inputs.git-tag }} + BINDINGS_PACKAGE: ${{ needs.resolve-bindings-package.outputs.bindings-package }} RELEASE_COMPONENT: ${{ inputs.component }} - BACKPORT_GIT_TAG: ${{ inputs.backport-git-tag }} + RELEASE_TAG: ${{ inputs.git-tag }} run: | - python ci/tools/check_release_notes.py \ - --git-tag "$RELEASE_GIT_TAG" \ + python -m ci.tools.check_release_notes \ + --git-tag "$RELEASE_TAG" \ --component "$RELEASE_COMPONENT" \ - --backport-git-tag "$BACKPORT_GIT_TAG" + --repo-root release-source \ + --bindings-package "$BINDINGS_PACKAGE" - name: Require Pathfinder version output if: ${{ inputs.component == 'cuda-pathfinder' }} @@ -201,7 +232,7 @@ jobs: VERSION: ${{ steps.release-notes.outputs.version }} run: | [[ -n "$VERSION" ]] || { - echo "::error::The tagged Pathfinder release-note checker must emit a non-empty version output" + echo "::error::The Pathfinder release-note checker must emit a non-empty version output" exit 1 } @@ -265,6 +296,7 @@ jobs: - check-tag - check-release-notes - determine-run-id + - resolve-bindings-package secrets: inherit uses: ./.github/workflows/build-docs.yml with: @@ -274,6 +306,7 @@ jobs: is-release: true deploy-docs: ${{ inputs.release-action == 'full-release' || inputs.dry-run-docs-branch != '' }} docs-branch: ${{ (inputs.release-action == 'dry-run' && inputs.dry-run-docs-branch) || 'gh-pages' }} + bindings-package: ${{ needs.resolve-bindings-package.outputs.bindings-package }} upload-archive: name: Validate release artifacts @@ -284,6 +317,7 @@ jobs: - check-release-notes - determine-run-id - doc + - resolve-bindings-package secrets: inherit uses: ./.github/workflows/release-upload.yml with: @@ -291,6 +325,7 @@ jobs: run-id: ${{ needs.determine-run-id.outputs.run-id }} component: ${{ inputs.component }} dry-run: ${{ inputs.release-action == 'dry-run' }} + bindings-package: ${{ needs.resolve-bindings-package.outputs.bindings-package }} publish-testpypi: name: Publish wheels to TestPyPI @@ -300,6 +335,7 @@ jobs: needs.check-release-notes.result == 'success' && needs.determine-run-id.result == 'success' && needs.doc.result == 'success' && + needs.resolve-bindings-package.result == 'success' && (inputs.component != 'cuda-pathfinder' || needs.ensure-pathfinder-draft.result == 'success') }} runs-on: ubuntu-latest needs: @@ -308,6 +344,7 @@ jobs: - determine-run-id - doc - ensure-pathfinder-draft + - resolve-bindings-package environment: name: testpypi url: https://test.pypi.org/p/${{ inputs.component }}/ @@ -317,15 +354,49 @@ jobs: - name: Checkout Source uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - name: Checkout release source + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + ref: refs/tags/${{ inputs.git-tag }} + path: release-source + + - name: Set up Python + uses: ./.github/actions/setup-hardened-python + with: + python-version: "3.12" + + - name: Install CI tool dependencies + run: python -m pip install -e ./ci + - name: Download component wheels env: + BINDINGS_PACKAGE: ${{ needs.resolve-bindings-package.outputs.bindings-package }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + RELEASE_COMPONENT: ${{ inputs.component }} + RELEASE_REPOSITORY: ${{ github.repository }} + RELEASE_RUN_ID: ${{ needs.determine-run-id.outputs.run-id }} + RELEASE_TAG: ${{ inputs.git-tag }} run: | - ./ci/tools/download-wheels "${{ needs.determine-run-id.outputs.run-id }}" "${{ inputs.component }}" "${{ github.repository }}" "dist" + ./ci/tools/download-wheels \ + "$RELEASE_RUN_ID" \ + "$RELEASE_COMPONENT" \ + "$RELEASE_REPOSITORY" \ + "dist" \ + "$RELEASE_TAG" \ + "$BINDINGS_PACKAGE" - name: Validate wheel versions for release tag + env: + BINDINGS_PACKAGE: ${{ needs.resolve-bindings-package.outputs.bindings-package }} + RELEASE_COMPONENT: ${{ inputs.component }} + RELEASE_TAG: ${{ inputs.git-tag }} run: | - ./ci/tools/validate-release-wheels "${{ inputs.git-tag }}" "${{ inputs.component }}" "dist" + python -m ci.tools.validate_release_wheels \ + "$RELEASE_TAG" \ + "$RELEASE_COMPONENT" \ + "dist" \ + --bindings-package "$BINDINGS_PACKAGE" \ + --release-source-root release-source - name: Publish package distributions to TestPyPI uses: pypa/gh-action-pypi-publish@7245906fb61fa33a13554f9d5fb856fe61758086 # v1.14.3 @@ -388,12 +459,14 @@ jobs: if: >- ${{ !cancelled() && inputs.release-action == 'full-release' && needs.determine-run-id.result == 'success' && needs.publish-testpypi.result == 'success' && + needs.resolve-bindings-package.result == 'success' && (inputs.component != 'cuda-pathfinder' || needs.verify-testpypi.result == 'success') }} runs-on: ubuntu-latest needs: - determine-run-id - publish-testpypi - verify-testpypi + - resolve-bindings-package environment: name: pypi url: https://pypi.org/p/${{ inputs.component }}/ @@ -403,15 +476,49 @@ jobs: - name: Checkout Source uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - name: Checkout release source + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + ref: refs/tags/${{ inputs.git-tag }} + path: release-source + + - name: Set up Python + uses: ./.github/actions/setup-hardened-python + with: + python-version: "3.12" + + - name: Install CI tool dependencies + run: python -m pip install -e ./ci + - name: Download component wheels env: + BINDINGS_PACKAGE: ${{ needs.resolve-bindings-package.outputs.bindings-package }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + RELEASE_COMPONENT: ${{ inputs.component }} + RELEASE_REPOSITORY: ${{ github.repository }} + RELEASE_RUN_ID: ${{ needs.determine-run-id.outputs.run-id }} + RELEASE_TAG: ${{ inputs.git-tag }} run: | - ./ci/tools/download-wheels "${{ needs.determine-run-id.outputs.run-id }}" "${{ inputs.component }}" "${{ github.repository }}" "dist" + ./ci/tools/download-wheels \ + "$RELEASE_RUN_ID" \ + "$RELEASE_COMPONENT" \ + "$RELEASE_REPOSITORY" \ + "dist" \ + "$RELEASE_TAG" \ + "$BINDINGS_PACKAGE" - name: Validate wheel versions for release tag + env: + BINDINGS_PACKAGE: ${{ needs.resolve-bindings-package.outputs.bindings-package }} + RELEASE_COMPONENT: ${{ inputs.component }} + RELEASE_TAG: ${{ inputs.git-tag }} run: | - ./ci/tools/validate-release-wheels "${{ inputs.git-tag }}" "${{ inputs.component }}" "dist" + python -m ci.tools.validate_release_wheels \ + "$RELEASE_TAG" \ + "$RELEASE_COMPONENT" \ + "dist" \ + --bindings-package "$BINDINGS_PACKAGE" \ + --release-source-root release-source - name: Publish package distributions to PyPI uses: pypa/gh-action-pypi-publish@7245906fb61fa33a13554f9d5fb856fe61758086 # v1.14.3 diff --git a/.github/workflows/test-sdist-linux.yml b/.github/workflows/test-sdist-linux.yml index 1721fbd48f7..fa9966beaa5 100644 --- a/.github/workflows/test-sdist-linux.yml +++ b/.github/workflows/test-sdist-linux.yml @@ -130,7 +130,7 @@ jobs: if: ${{ env.BUILD_BINDINGS != 'true' && env.BUILD_CORE == 'true' }} uses: ./.github/actions/download-artifact-retry with: - name: ${{ fromJSON(inputs.bindings-package).release_status == 'maintenance' && 'maintenance-bindings' || 'cuda-bindings' }}-python312-cuda${{ fromJSON(inputs.bindings-package).toolkit_version }}-${{ inputs.host-platform }}-${{ github.sha }} + name: cuda-bindings-python312-cuda${{ fromJSON(inputs.bindings-package).toolkit_version }}-${{ inputs.host-platform }}-${{ github.sha }} path: ${{ env.BINDINGS_ROOT }}/dist - name: Constrain cuda.core to the local cuda.bindings wheel diff --git a/.github/workflows/test-sdist-windows.yml b/.github/workflows/test-sdist-windows.yml index e73425a5344..93d06df88db 100644 --- a/.github/workflows/test-sdist-windows.yml +++ b/.github/workflows/test-sdist-windows.yml @@ -137,7 +137,7 @@ jobs: if: ${{ env.BUILD_BINDINGS != 'true' && env.BUILD_CORE == 'true' }} uses: ./.github/actions/download-artifact-retry with: - name: ${{ fromJSON(inputs.bindings-package).release_status == 'maintenance' && 'maintenance-bindings' || 'cuda-bindings' }}-python312-cuda${{ fromJSON(inputs.bindings-package).toolkit_version }}-${{ inputs.host-platform }}-${{ github.sha }} + name: cuda-bindings-python312-cuda${{ fromJSON(inputs.bindings-package).toolkit_version }}-${{ inputs.host-platform }}-${{ github.sha }} path: ${{ env.BINDINGS_ROOT }}/dist - name: Constrain cuda.core to the local cuda.bindings wheel diff --git a/.github/workflows/test-wheel-linux.yml b/.github/workflows/test-wheel-linux.yml index d2de86aa3dd..14f6698cd31 100644 --- a/.github/workflows/test-wheel-linux.yml +++ b/.github/workflows/test-wheel-linux.yml @@ -96,9 +96,9 @@ jobs: BINDINGS_ROOT: ($package.package_root // "cuda_bindings_13"), BINDINGS_BUILD_VERSION: ($package.toolkit_version // ""), BINDINGS_SOURCE: (if $package == null then "floor" else "main" end), - BINDINGS_ARTIFACT_PREFIX: (if $package.release_status == "maintenance" then "maintenance-bindings" else "cuda-bindings" end), + BINDINGS_ARTIFACT_PREFIX: "cuda-bindings", CORE_CYTHON_SUFFIX: (if $package.release_status == "maintenance" then "-cu\($package.cuda_major)-tests" else "-tests" end), - PYTHON_ARTIFACT_NAME: (if $package.release_status == "maintenance" then "maintenance-python-wheel" else "cuda-python-wheel" end) + PYTHON_ARTIFACT_NAME: (if $package == null then "" else "cuda-python-wheel-cuda\($package.toolkit_version)" end) }) ' <<< "$TEST_MATRIX") fi diff --git a/.github/workflows/test-wheel-windows.yml b/.github/workflows/test-wheel-windows.yml index 8189a635a9e..541900b3006 100644 --- a/.github/workflows/test-wheel-windows.yml +++ b/.github/workflows/test-wheel-windows.yml @@ -92,9 +92,9 @@ jobs: BINDINGS_ROOT: ($package.package_root // "cuda_bindings_13"), BINDINGS_BUILD_VERSION: ($package.toolkit_version // ""), BINDINGS_SOURCE: (if $package == null then "floor" else "main" end), - BINDINGS_ARTIFACT_PREFIX: (if $package.release_status == "maintenance" then "maintenance-bindings" else "cuda-bindings" end), + BINDINGS_ARTIFACT_PREFIX: "cuda-bindings", CORE_CYTHON_SUFFIX: (if $package.release_status == "maintenance" then "-cu\($package.cuda_major)-tests" else "-tests" end), - PYTHON_ARTIFACT_NAME: (if $package.release_status == "maintenance" then "maintenance-python-wheel" else "cuda-python-wheel" end) + PYTHON_ARTIFACT_NAME: (if $package == null then "" else "cuda-python-wheel-cuda\($package.toolkit_version)" end) }) ' <<< "$TEST_MATRIX") fi diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ce53ac63755..278ad673247 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -82,7 +82,7 @@ repos: name: Check pixi cuda-version pins track ci/versions.yml entry: python -m ci.tools.check_pixi_cuda_version language: python - additional_dependencies: [pyyaml==6.0.3] + additional_dependencies: [packaging==26.0, pyyaml==6.0.3] files: '^(ci/versions\.yml|ci/tools/(bindings_config|check_pixi_cuda_version)\.py|cuda_bindings_(?:12|13)/pixi\.toml|cuda_core/pixi\.toml)$' pass_filenames: false diff --git a/ci/tools/bindings_config.py b/ci/tools/bindings_config.py index a0449b51ada..3e81800cb8d 100644 --- a/ci/tools/bindings_config.py +++ b/ci/tools/bindings_config.py @@ -1,19 +1,28 @@ # SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: Apache-2.0 -"""Read bindings package roots and release roles from the existing toolkit pins.""" +"""Read bindings configuration and resolve releases against their tagged source.""" from __future__ import annotations import argparse import json +import re import sys from dataclasses import dataclass from pathlib import Path +from typing import Any, Mapping import yaml +from packaging.version import InvalidVersion, Version -DEFAULT_CONFIG = Path(__file__).resolve().parents[2] / "ci" / "versions.yml" +REPO_ROOT = Path(__file__).resolve().parents[2] +DEFAULT_CONFIG = REPO_ROOT / "ci" / "versions.yml" +SCHEMA_VERSION = 2 +RELEASE_STATUSES = frozenset({"current", "maintenance"}) +_DEPENDENT_RELEASE_TAG_PREFIXES = ("cuda-core-v", "cuda-pathfinder-v") +_PACKAGE_ROOT_PATTERN = re.compile(r"[A-Za-z0-9._-]+(?:/[A-Za-z0-9._-]+)*") +_TOOLKIT_VERSION_PATTERN = re.compile(r"[1-9][0-9]*\.[0-9]+\.[0-9]+") @dataclass(frozen=True) @@ -38,6 +47,16 @@ def cuda_major(self) -> str: def cuda_variant(self) -> str: return f"cu{self.cuda_major}" + def version_from_tag(self, tag: str) -> Version | None: + """Return a matching release version for this configured package root.""" + version = parse_prefixed_version(tag, "v") + if version is None or version.release[:2] != self.toolkit[:2]: + return None + return version + + def matches_tag(self, tag: str) -> bool: + return self.version_from_tag(tag) is not None + def to_dict(self) -> dict[str, str]: return { "package_root": self.package_root, @@ -63,40 +82,178 @@ def get_package(self, package_root: str) -> BindingsPackage: def package_for_release_status(self, release_status: str) -> BindingsPackage: return next(package for package in self.package_roots if package.release_status == release_status) + def match_tag(self, tag: str) -> BindingsPackage | None: + return next((package for package in self.package_roots if package.matches_tag(tag)), None) -def load_config(path: Path = DEFAULT_CONFIG) -> BindingsConfig: - """Normalize legacy build/prev_build fields without changing their consumers.""" - raw = yaml.safe_load(path.read_text(encoding="utf-8")) + +def parse_config(raw: Mapping[str, Any]) -> BindingsConfig: + """Normalize legacy toolkit pins or the explicit package-root registry.""" packages = [] - for field, release_status in (("build", "current"), ("prev_build", "maintenance")): - major, minor, patch = map(int, raw["cuda"][field]["version"].split(".")) - packages.append(BindingsPackage(f"cuda_bindings_{major}", (major, minor, patch), release_status)) + if "schema_version" in raw: + if raw["schema_version"] != SCHEMA_VERSION: + raise ValueError(f"schema_version must be {SCHEMA_VERSION}") + for package_root, data in raw["cuda"]["bindings"]["package_roots"].items(): + major, minor, patch = map(int, data["toolkit_version"].split(".")) + packages.append(BindingsPackage(package_root, (major, minor, patch), data["release_status"])) + else: + for field, release_status in (("build", "current"), ("prev_build", "maintenance")): + major, minor, patch = map(int, raw["cuda"][field]["version"].split(".")) + packages.append(BindingsPackage(f"cuda_bindings_{major}", (major, minor, patch), release_status)) + if len(packages) != 2 or {package.release_status for package in packages} != RELEASE_STATUSES: + raise ValueError("bindings configuration must contain one current and one maintenance package") + if len({package.toolkit[0] for package in packages}) != len(packages): + raise ValueError("CUDA bindings cuda_major values must be unique") return BindingsConfig(tuple(packages), tuple(raw["python"]["supported"])) +def load_config(path: Path = DEFAULT_CONFIG) -> BindingsConfig: + return parse_config(yaml.safe_load(path.read_text(encoding="utf-8"))) + + +def parse_prefixed_version(tag: str, prefix: str) -> Version | None: + """Parse the PEP 440 version following an exact component tag prefix.""" + if not tag.startswith(prefix): + return None + value = tag.removeprefix(prefix) + try: + version = Version(value) + except InvalidVersion: + return None + if str(version) != value or len(version.release) != 3 or version.epoch != 0 or version.local is not None: + return None + return version + + +def parse_package_root(value: Any, label: str = "package_root") -> str: + """Validate a package path received through the release JSON interface.""" + if ( + not isinstance(value, str) + or _PACKAGE_ROOT_PATTERN.fullmatch(value) is None + or any(part in (".", "..") for part in value.split("/")) + ): + raise ValueError(f"{label} must be a normalized repository-relative POSIX path: {value!r}") + return value + + +def resolve_release_bindings_package( + release_tag: str, + release_source_root: Path, +) -> dict[str, object]: + """Resolve a release from its tagged source, including retained CUDA 13 tags.""" + if not release_source_root.is_dir(): + raise ValueError(f"release source root is not a directory: {release_source_root}") + + config_path = release_source_root / "ci" / "versions.yml" + bindings_version = parse_prefixed_version(release_tag, "v") + is_dependent_release = any( + parse_prefixed_version(release_tag, prefix) is not None for prefix in _DEPENDENT_RELEASE_TAG_PREFIXES + ) + if bindings_version is None and not is_dependent_release: + raise ValueError(f"unsupported release tag: {release_tag!r}") + + try: + raw = yaml.safe_load(config_path.read_text(encoding="utf-8")) + legacy_config = "schema_version" not in raw + if legacy_config: + current_toolkit = raw["cuda"]["build"]["version"] + if _TOOLKIT_VERSION_PATTERN.fullmatch(current_toolkit) is None or not current_toolkit.startswith("13."): + raise ValueError("legacy release compatibility requires a CUDA 13 build toolkit") + current_root = ( + "cuda_bindings_13" if (release_source_root / "cuda_bindings_13").is_dir() else "cuda_bindings" + ) + package = BindingsPackage(current_root, tuple(map(int, current_toolkit.split("."))), "current") + if bindings_version is not None and bindings_version.release[0] == 12: + maintenance_toolkit = raw["cuda"]["prev_build"]["version"] + if _TOOLKIT_VERSION_PATTERN.fullmatch(maintenance_toolkit) is None: + raise ValueError("legacy prev_build toolkit must have major.minor.patch format") + package = BindingsPackage( + "cuda_bindings_12", tuple(map(int, maintenance_toolkit.split("."))), "maintenance" + ) + else: + config = parse_config(raw) + package = ( + config.package_for_release_status("current") if is_dependent_release else config.match_tag(release_tag) + ) + except (OSError, yaml.YAMLError, KeyError, TypeError, ValueError) as error: + raise ValueError(f"could not resolve release source config {config_path}: {error}") from error + if package is None: + raise ValueError( + f"no CUDA bindings package root in tagged config {config_path} matches release tag: {release_tag!r}" + ) + if bindings_version is not None and not package.matches_tag(release_tag): + raise ValueError(f"release tag {release_tag!r} does not match tagged toolkit {package.toolkit_version}") + if legacy_config and not (release_source_root / package.package_root).is_dir(): + raise ValueError(f"tagged source has no bindings root {package.package_root!r}") + + record: dict[str, object] = { + "package_root": package.package_root, + "toolkit_version": package.toolkit_version, + } + if bindings_version is not None: + record["release_version"] = str(bindings_version) + if legacy_config and package.release_status == "current": + record["allow_legacy_python_artifact"] = True + return record + + +def write_github_env(data: Mapping[str, object], path: Path) -> None: + """Append the bindings build environment consumed by documentation jobs.""" + package_root = parse_package_root(data.get("package_root"), "resolved package_root") + toolkit_version = data.get("toolkit_version") + if not isinstance(toolkit_version, str) or _TOOLKIT_VERSION_PATTERN.fullmatch(toolkit_version) is None: + raise ValueError(f"resolved toolkit_version must have major.minor.patch format: {toolkit_version!r}") + with path.open("a", encoding="utf-8") as stream: + stream.write(f"BUILD_CTK_VER={toolkit_version}\n") + stream.write(f"BINDINGS_PACKAGE_ROOT={package_root}\n") + stream.write(f"RESOLVED_BINDINGS_PACKAGE={json.dumps(data, separators=(',', ':'))}\n") + + def main(argv: list[str] | None = None) -> int: parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("--config", type=Path, default=DEFAULT_CONFIG) output = parser.add_mutually_exclusive_group() output.add_argument("--package-roots", action="store_true") - output.add_argument("--release-status", choices=("current", "maintenance")) + output.add_argument("--release-status", choices=sorted(RELEASE_STATUSES)) + output.add_argument("--release-tag", help="resolve a release tag against its source tree") + parser.add_argument("--release-source-root", type=Path) + commands = parser.add_subparsers(dest="command") + write_env = commands.add_parser("write-github-env", help="append package JSON from stdin to GITHUB_ENV") + write_env.add_argument("github_env", type=Path, metavar="GITHUB_ENV") args = parser.parse_args(argv) - config = load_config(args.config) - if args.release_status: - result = config.package_for_release_status(args.release_status).to_dict() - else: - packages = [package.to_dict() for package in config.package_roots] - result = ( - packages - if args.package_roots - else { - "python": {"supported": list(config.python_supported)}, - "package_roots": packages, - } - ) - print(json.dumps(result, separators=(",", ":"), sort_keys=True)) - return 0 + try: + if args.command == "write-github-env": + if args.package_roots or args.release_status or args.release_tag or args.release_source_root is not None: + parser.error("write-github-env does not accept registry selectors") + value = json.load(sys.stdin) + if not isinstance(value, dict): + raise ValueError("stdin for write-github-env must contain a JSON object") + write_github_env(value, args.github_env) + return 0 + if args.release_tag: + if args.release_source_root is None: + parser.error("--release-tag requires --release-source-root") + result: object = resolve_release_bindings_package(args.release_tag, args.release_source_root) + else: + if args.release_source_root is not None: + parser.error("--release-source-root requires --release-tag") + config = load_config(args.config) + if args.release_status: + result = config.package_for_release_status(args.release_status).to_dict() + else: + packages = [package.to_dict() for package in config.package_roots] + result = ( + packages + if args.package_roots + else { + "python": {"supported": list(config.python_supported)}, + "package_roots": packages, + } + ) + print(json.dumps(result, separators=(",", ":"), sort_keys=True)) + return 0 + except ValueError as error: + parser.error(str(error)) if __name__ == "__main__": diff --git a/ci/tools/check_release_notes.py b/ci/tools/check_release_notes.py index 7da330046ba..1739c0a1446 100644 --- a/ci/tools/check_release_notes.py +++ b/ci/tools/check_release_notes.py @@ -4,10 +4,13 @@ """Check that versioned release-notes files exist before releasing. Usage: - python check_release_notes.py --git-tag --component + python -m ci.tools.check_release_notes --git-tag --component -Notes and release configuration come from the working tree. Successful checks -append the parsed version to GITHUB_OUTPUT when it is set. +Each normal release requires nonempty notes for its exact version and component +in the tagged source checkout. Post releases do not require new notes, except +Pathfinder requires a notes file for every release and permits empty files. + +Successful checks append the parsed version to GITHUB_OUTPUT when it is set. Exit codes: 0 — release-notes policy satisfied @@ -18,100 +21,91 @@ from __future__ import annotations import argparse +import json import os -import re import sys from pathlib import Path +from typing import Mapping -COMPONENT_TO_PACKAGE: dict[str, str] = { - "cuda-core": "cuda_core", - "cuda-bindings": "cuda_bindings_13", - "cuda-pathfinder": "cuda_pathfinder", - "cuda-python": "cuda_python", -} +from packaging.version import Version -# Version characters are restricted to digit-prefixed word chars and dots, so -# malformed inputs like "v../evil" or "v1/2/3" cannot flow into the notes path. -_VERSION_PATTERN = r"\d[\w.]*" - -# Each component has exactly one valid tag-prefix form. cuda-bindings and -# cuda-python share the bare "v" namespace (setuptools-scm lookup). -COMPONENT_TO_TAG_RE: dict[str, re.Pattern[str]] = { - "cuda-bindings": re.compile(rf"^v(?P{_VERSION_PATTERN})$"), - "cuda-python": re.compile(rf"^v(?P{_VERSION_PATTERN})$"), - "cuda-core": re.compile(rf"^cuda-core-v(?P{_VERSION_PATTERN})$"), - "cuda-pathfinder": re.compile(rf"^cuda-pathfinder-v(?P{_VERSION_PATTERN})$"), +from . import bindings_config + +COMPONENTS: dict[str, tuple[str, str]] = { + "cuda-core": ("cuda_core", "cuda-core-v"), + "cuda-bindings": ("cuda_bindings_13", "v"), + "cuda-pathfinder": ("cuda_pathfinder", "cuda-pathfinder-v"), + "cuda-python": ("cuda_python", "v"), } -BACKPORT_PLANNING_COMPONENTS = frozenset({"cuda-bindings", "cuda-python"}) -BACKPORT_NOT_PLANNED = "not planned" -BACKPORT_BRANCH_RE = re.compile(r"""^backport_branch:\s*["']?(?P[^"'\s#]+)""") -BACKPORT_BRANCH_NAME_RE = re.compile(r"^\d+\.\d+\.x$") +def _resolved_bindings_target(data: Mapping[str, object], git_tag: str) -> tuple[str, Version]: + """Read the release resolver fields consumed by this script.""" + package_root = bindings_config.parse_package_root(data.get("package_root"), "resolved package_root") + raw_version = data.get("release_version") + if not isinstance(raw_version, str): + raise ValueError("resolved CUDA bindings package has no release_version") + version = Version(raw_version) + tag_version = bindings_config.parse_prefixed_version(git_tag, "v") + if tag_version != version: + raise ValueError(f"resolved CUDA bindings package does not match release tag {git_tag!r}") + return package_root, version -def parse_version_from_tag(git_tag: str, component: str) -> str | None: - """Extract the version string from a tag, given the target component. - Returns None if the tag does not match the component's expected prefix - or contains characters outside the allowed version set. - """ - pattern = COMPONENT_TO_TAG_RE.get(component) - if pattern is None: +def _release_target_from_tag( + git_tag: str, + component: str, + bindings_package: Mapping[str, object] | None = None, +) -> tuple[str, str] | None: + """Return the release version and source tree selected by a component tag.""" + metadata = COMPONENTS.get(component) + if metadata is None: return None - m = pattern.match(git_tag) - return m.group("version") if m else None - + package_dir, prefix = metadata + if component == "cuda-bindings": + if bindings_package is None: + package = bindings_config.load_config().match_tag(git_tag) + if package is None: + return None + package_root = package.package_root + version = package.version_from_tag(git_tag) + else: + package_root, version = _resolved_bindings_target(bindings_package, git_tag) + else: + version = bindings_config.parse_prefixed_version(git_tag, prefix) + if version is None: + return None + return str(version), package_root if component == "cuda-bindings" else package_dir -def is_post_release(version: str) -> bool: - return ".post" in version +def parse_version_from_tag( + git_tag: str, + component: str, + bindings_package: Mapping[str, object] | None = None, +) -> str | None: + """Extract the version string from a tag, given the target component. -def load_backport_branch(repo_root: Path = Path(".")) -> str | None: - path = repo_root / "ci" / "versions.yml" - try: - with open(path, encoding="utf-8") as f: - for line in f: - m = BACKPORT_BRANCH_RE.match(line.strip()) - if m: - return m.group("branch") - except FileNotFoundError: - pass - github_ref_name = os.environ.get("GITHUB_REF_NAME", "") - if BACKPORT_BRANCH_NAME_RE.match(github_ref_name): - return github_ref_name - return None + Returns None if the tag does not match the component's expected prefix, + contains characters outside the allowed version set, or (for bindings) + does not select a configured package root. + """ + target = _release_target_from_tag(git_tag, component, bindings_package) + return target[0] if target is not None else None -def is_backport_version(version: str, backport_branch: str) -> bool: - if backport_branch.endswith(".x"): - return version.startswith(backport_branch[:-1]) - return version == backport_branch +def is_post_release(version: str) -> bool: + return Version(version).post is not None def notes_path(package: str, version: str) -> Path: return Path(package, "docs", "source", "release", f"{version}-notes.rst") -def check_release_notes(git_tag: str, component: str, repo_root: Path = Path(".")) -> list[tuple[str | Path, str]]: - """Return a list of (path, reason) for missing or empty release notes. - - ``path`` is the repo-relative notes path, or a ```` naming the - offending argument when the tag or component itself is the problem. - - Pathfinder requires a notes file, including for .post releases, but allows - an empty file. Other components require non-empty notes and skip .post. - """ - if component not in COMPONENT_TO_PACKAGE: - return [("", f"unknown component '{component}'")] - - version = parse_version_from_tag(git_tag, component) - if version is None: - return [("", f"cannot parse version from tag '{git_tag}' for component '{component}'")] - +def _check_release_target(version: str, package: str, component: str, repo_root: Path) -> list[tuple[str | Path, str]]: if is_post_release(version) and component != "cuda-pathfinder": return [] - path = notes_path(COMPONENT_TO_PACKAGE[component], version) + path = notes_path(package, version) full = repo_root / path if not full.is_file(): return [(path, "missing")] @@ -120,16 +114,6 @@ def check_release_notes(git_tag: str, component: str, repo_root: Path = Path("." return [] -def write_step_summary(message: str) -> None: - summary_path = os.environ.get("GITHUB_STEP_SUMMARY") - if not summary_path: - return - with open(summary_path, "a", encoding="utf-8") as f: - f.write(message) - if not message.endswith("\n"): - f.write("\n") - - def write_version_output(version: str) -> None: output_path = os.environ.get("GITHUB_OUTPUT") if output_path: @@ -137,126 +121,69 @@ def write_version_output(version: str) -> None: f.write(f"version={version}\n") -def warn_missing_backport_notes(git_tag: str, component: str, problems: list[tuple[str | Path, str]]) -> None: - print(f"WARNING: missing or empty release notes for backport tag {git_tag}:") - summary_lines = [ - "## Release Notes Reminder", - "", - f"Backport release `{git_tag}` for `{component}` is allowed to continue,", - "but the following release-note files are missing or empty in the workflow source:", - "", - ] - for path, reason in problems: - print(f"::warning file={path}::Release notes for backport tag {git_tag} are {reason}.") - print(f" - {path} ({reason})") - summary_lines.append(f"- `{path}` ({reason})") - summary_lines.extend(["", "Please add the backport release notes on `main` if they are not already present."]) - write_step_summary("\n".join(summary_lines)) - - -def validate_backport_decision( - *, +def check_release_notes( git_tag: str, component: str, - version: str, - backport_git_tag: str, - backport_branch: str | None, - repo_root: Path, -) -> tuple[int | None, list[tuple[str | Path, str]]]: - if component not in BACKPORT_PLANNING_COMPONENTS or is_post_release(version): - return None, [] - - if backport_branch is None: - print("ERROR: cannot determine backport branch from ci/versions.yml or GITHUB_REF_NAME.", file=sys.stderr) - return 2, [] - - if is_backport_version(version, backport_branch): - problems = check_release_notes(git_tag, component, repo_root) - if problems: - warn_missing_backport_notes(git_tag, component, problems) - else: - print(f"Release notes present for backport tag {git_tag}, component {component}.") - return 0, [] - - decision = backport_git_tag.strip() - if not decision: - return ( - 1, - [ - ( - "", - f"required for {component} mainline releases; use a backport tag or '{BACKPORT_NOT_PLANNED}'", - ) - ], - ) - - if decision == BACKPORT_NOT_PLANNED: - print(f"Backport release not planned for {git_tag}, skipping backport release-notes check.") - return None, [] + repo_root: Path = Path("."), + bindings_package: Mapping[str, object] | None = None, +) -> list[tuple[str | Path, str]]: + """Return a list of (path, reason) for missing or empty release notes. - backport_version = parse_version_from_tag(decision, component) - if backport_version is None: - print( - f"ERROR: backport tag {decision!r} does not match the expected format for component {component!r}.", - file=sys.stderr, - ) - return 2, [] + ``path`` is the repo-relative notes path, or a ```` naming the + offending argument when the tag or component itself is the problem. - if not is_backport_version(backport_version, backport_branch): - print( - f"ERROR: backport tag {decision!r} does not match configured backport branch {backport_branch!r}.", - file=sys.stderr, - ) - return 2, [] + Pathfinder requires a notes file, including for .post releases, but allows + an empty file. Other components require non-empty notes and skip .post. + """ + if component not in COMPONENTS: + return [("", f"unknown component '{component}'")] - problems = check_release_notes(decision, component, repo_root) - if problems: - return 1, problems - return None, [] + target = _release_target_from_tag(git_tag, component, bindings_package) + if target is None: + return [("", f"cannot parse version from tag '{git_tag}' for component '{component}'")] + version, package = target + return _check_release_target(version, package, component, repo_root) def main(argv: list[str] | None = None) -> int: parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("--git-tag", required=True) - parser.add_argument("--component", required=True, choices=list(COMPONENT_TO_PACKAGE)) - parser.add_argument("--repo-root", default=Path("."), type=Path) - parser.add_argument("--backport-git-tag", default="") - parser.add_argument("--backport-branch", default="") + parser.add_argument("--component", required=True, choices=list(COMPONENTS)) + parser.add_argument( + "--repo-root", + default=Path("."), + type=Path, + help="tagged source checkout containing the component's versioned release notes", + ) + parser.add_argument( + "--bindings-package", + default="", + help="normalized CUDA bindings package JSON from the release resolver", + ) args = parser.parse_args(argv) - version = parse_version_from_tag(args.git_tag, args.component) - if version is None: + try: + bindings_package = json.loads(args.bindings_package) if args.bindings_package else None + if bindings_package is not None and not isinstance(bindings_package, dict): + raise ValueError("resolved CUDA bindings package must be a JSON object") + target = _release_target_from_tag(args.git_tag, args.component, bindings_package) + except ValueError as error: + print(f"ERROR: invalid CUDA bindings configuration: {error}", file=sys.stderr) + return 2 + if target is None: print( f"ERROR: tag {args.git_tag!r} does not match the expected format for component {args.component!r}.", file=sys.stderr, ) return 2 + version, package = target if is_post_release(version) and args.component != "cuda-pathfinder": print(f"Post-release tag ({args.git_tag}), skipping release-notes check.") write_version_output(version) return 0 - backport_branch = args.backport_branch or load_backport_branch(args.repo_root) - rc, problems = validate_backport_decision( - git_tag=args.git_tag, - component=args.component, - version=version, - backport_git_tag=args.backport_git_tag, - backport_branch=backport_branch, - repo_root=args.repo_root, - ) - if rc is not None: - if problems: - print(f"ERROR: release notes policy failed for tag {args.git_tag}:", file=sys.stderr) - for path, reason in problems: - print(f" - {path} ({reason})", file=sys.stderr) - if rc == 0: - write_version_output(version) - return rc - - if not problems: - problems = check_release_notes(args.git_tag, args.component, args.repo_root) + problems = _check_release_target(version, package, args.component, args.repo_root) if not problems: print(f"Release notes present for tag {args.git_tag}, component {args.component}.") @@ -266,7 +193,7 @@ def main(argv: list[str] | None = None) -> int: print(f"ERROR: missing or empty release notes for tag {args.git_tag}:", file=sys.stderr) for path, reason in problems: print(f" - {path} ({reason})", file=sys.stderr) - print("Add versioned release notes before releasing.", file=sys.stderr) + print("Add versioned release notes to the tagged source before releasing.", file=sys.stderr) return 1 diff --git a/ci/tools/download-wheels b/ci/tools/download-wheels index 709c81d3d12..28b2da21bb2 100755 --- a/ci/tools/download-wheels +++ b/ci/tools/download-wheels @@ -26,7 +26,7 @@ _retry_gh_run_download() { local staging staging=$(mktemp -d -p "${RUNNER_TEMP:-/tmp}") - until gh run download "$@" -D "${staging}"; do + until gh run download "$@" --dir "${staging}"; do rm -rf "${staging}" if (( attempt >= max_attempts )); then echo "::error::gh run download failed after ${attempt} attempt(s): $*" >&2 @@ -39,20 +39,22 @@ _retry_gh_run_download() { staging=$(mktemp -d -p "${RUNNER_TEMP:-/tmp}") done - # Promote each downloaded artifact directory into the caller's CWD. - for artifact_dir in "${staging}"/*/; do - mv "${artifact_dir%/}" . + # Promote the selected artifact into the private release staging directory. + for artifact in "${staging}"/*; do + mv "${artifact}" "${ARTIFACTS_DIR}/" done rm -rf "${staging}" } # Check required arguments if [[ $# -lt 3 ]]; then - echo "Usage: $0 [output-dir]" >&2 + echo "Usage: $0 [output-dir] [git-tag] [bindings-package-json]" >&2 echo " run-id: The GitHub Actions run ID containing the artifacts" >&2 echo " component: The component name pattern to download (e.g., cuda-core, cuda-bindings)" >&2 echo " repository: The GitHub repository (e.g., NVIDIA/cuda-python)" >&2 echo " output-dir: Optional output directory (default: ./dist)" >&2 + echo " git-tag: Optional release tag used to select its configured bindings package" >&2 + echo " bindings-package-json: Resolved package JSON; required for bindings/python release tags" >&2 exit 1 fi @@ -60,6 +62,8 @@ RUN_ID="$1" COMPONENT="$2" REPOSITORY="$3" OUTPUT_DIR="${4:-./dist}" +GIT_TAG="${5:-}" +RESOLVED_BINDINGS_PACKAGE_JSON="${6:-}" # Ensure we have a GitHub token if [[ -z "${GH_TOKEN:-}" ]]; then @@ -69,44 +73,111 @@ fi echo "Downloading wheels for component: $COMPONENT from run: $RUN_ID" -# Download component wheels using the same logic as release.yml +ARTIFACTS_DIR="$(mktemp -d)" +cleanup() { + rm -rf -- "$ARTIFACTS_DIR" +} +trap cleanup EXIT + +# Select artifacts before downloading so non-wheel test artifacts cannot enter +# the release staging directory. if [[ "$COMPONENT" == "all" ]]; then - # Download all component patterns - _retry_gh_run_download "$RUN_ID" -p "cuda-*" -R "$REPOSITORY" + ARTIFACT_PATTERN="cuda-*" else - _retry_gh_run_download "$RUN_ID" -p "${COMPONENT}*" -R "$REPOSITORY" + ARTIFACT_PATTERN="${COMPONENT}*" fi -# Create output directory -mkdir -p "$OUTPUT_DIR" +IS_BINDINGS_RELEASE=false +if [[ "$COMPONENT" != "all" \ + && "$COMPONENT" =~ ^cuda-(bindings|python)$ \ + && "$GIT_TAG" == v* ]]; then + IS_BINDINGS_RELEASE=true +fi -# Process downloaded artifacts -for p in cuda-* -do - if [[ ! -d "$p" ]]; then - continue +if [[ "$IS_BINDINGS_RELEASE" == true ]]; then + if [[ -z "$RESOLVED_BINDINGS_PACKAGE_JSON" ]]; then + echo "Error: resolved bindings-package JSON is required for $COMPONENT release tag $GIT_TAG" >&2 + exit 1 fi - - # exclude cython test artifacts - if [[ "${p}" == *-tests ]]; then - echo "Skipping test artifact: $p" - continue + if ! command -v jq >/dev/null 2>&1; then + echo "Error: jq is required for bindings release artifact routing" >&2 + exit 1 fi + if ! TOOLKIT_VERSION="$(jq -er '.toolkit_version | select(type == "string")' \ + <<< "$RESOLVED_BINDINGS_PACKAGE_JSON")"; then + echo "Error: resolved bindings-package JSON has no string toolkit_version" >&2 + exit 1 + fi + if [[ ! "$TOOLKIT_VERSION" =~ ^[1-9][0-9]*\.[0-9]+\.[0-9]+([.-][A-Za-z0-9]+)*$ ]]; then + echo "Error: invalid toolkit_version in resolved bindings-package JSON: $TOOLKIT_VERSION" >&2 + exit 1 + fi +fi + +if ! ARTIFACT_NAMES="$(gh api --paginate \ + "repos/${REPOSITORY}/actions/runs/${RUN_ID}/artifacts?per_page=100" \ + --jq '.artifacts[] | select(.expired == false) | .name')"; then + echo "Error: failed to inspect artifacts for run $RUN_ID" >&2 + exit 1 +fi - # If we're not downloading "all", only process matching component - if [[ "$COMPONENT" != "all" && "$p" != ${COMPONENT}* ]]; then - continue +MATCHING_ARTIFACTS=() +if [[ "$IS_BINDINGS_RELEASE" == true && "$COMPONENT" == "cuda-python" ]]; then + ARTIFACT_NAME="cuda-python-wheel-cuda${TOOLKIT_VERSION}" + if grep -Fxq "$ARTIFACT_NAME" <<< "$ARTIFACT_NAMES"; then + MATCHING_ARTIFACTS+=("$ARTIFACT_NAME") + elif [[ "$TOOLKIT_VERSION" == 13.* ]] \ + && jq -e '.allow_legacy_python_artifact == true' \ + <<< "$RESOLVED_BINDINGS_PACKAGE_JSON" >/dev/null \ + && grep -Fxq "cuda-python-wheel" <<< "$ARTIFACT_NAMES"; then + MATCHING_ARTIFACTS+=("cuda-python-wheel") fi +else + if [[ "$IS_BINDINGS_RELEASE" == true ]]; then + ARTIFACT_PATTERN="cuda-bindings-python*-cuda${TOOLKIT_VERSION}-*" + fi + while IFS= read -r artifact_name; do + # Release patterns contain only the validated toolkit version. Other + # patterns preserve the component matching accepted by this script. + # shellcheck disable=SC2053 + if [[ "$artifact_name" == $ARTIFACT_PATTERN && "$artifact_name" != *-tests ]]; then + MATCHING_ARTIFACTS+=("$artifact_name") + fi + done <<< "$ARTIFACT_NAMES" +fi - echo "Processing artifact: $p" - # Move wheel files to output directory - if [[ -d "$p" ]]; then - find "$p" -name "*.whl" -exec mv {} "$OUTPUT_DIR/" \; +if [[ ${#MATCHING_ARTIFACTS[@]} == 0 ]]; then + if [[ "$IS_BINDINGS_RELEASE" == true ]]; then + echo "Error: run $RUN_ID has no unexpired release artifact for CUDA $TOOLKIT_VERSION" >&2 + else + echo "Error: run $RUN_ID has no unexpired releasable artifact matching $ARTIFACT_PATTERN" >&2 fi + exit 1 +fi + +for artifact_name in "${MATCHING_ARTIFACTS[@]}"; do + _retry_gh_run_download "$RUN_ID" --name "$artifact_name" \ + -R "$REPOSITORY" done -# Clean up artifact directories -rm -rf cuda-* +# Create output directory +mkdir -p "$OUTPUT_DIR" + +# `gh run download` extracts a sole selected artifact directly into --dir, +# while multiple artifacts get per-artifact subdirectories. Find wheels +# recursively so both layouts are handled identically. +MOVED_WHEELS=0 +while IFS= read -r -d '' wheel; do + relative_path="${wheel#"$ARTIFACTS_DIR"/}" + echo "Processing wheel: $relative_path" + mv "$wheel" "$OUTPUT_DIR/" + MOVED_WHEELS=$((MOVED_WHEELS + 1)) +done < <(find "$ARTIFACTS_DIR" -type f -name "*.whl" -print0) + +if [[ "$MOVED_WHEELS" == 0 ]]; then + echo "Error: selected artifacts contain no releasable wheels" >&2 + exit 1 +fi echo "Downloaded wheels to: $OUTPUT_DIR" ls -la "$OUTPUT_DIR" diff --git a/ci/tools/env-vars b/ci/tools/env-vars index 6474bea5308..30ff358ae98 100755 --- a/ci/tools/env-vars +++ b/ci/tools/env-vars @@ -67,7 +67,7 @@ if [[ "${1}" == "build" ]]; then echo "MAINTENANCE_CUDA_MAJOR=${maintenance_version%%.*}" echo "MAINTENANCE_BINDINGS_ARTIFACTS_DIR=$(realpath "${REPO_DIR}/${maintenance_root}/dist")" echo "MAINTENANCE_BINDINGS_CYTHON_TESTS_DIR=$(realpath "${REPO_DIR}/${maintenance_root}/tests/cython")" - echo "MAINTENANCE_BINDINGS_ARTIFACT_NAME=maintenance-bindings-python${PYTHON_VERSION_FORMATTED}-cuda${maintenance_version}-${HOST_PLATFORM}-${SHA}" + echo "MAINTENANCE_BINDINGS_ARTIFACT_NAME=cuda-bindings-python${PYTHON_VERSION_FORMATTED}-cuda${maintenance_version}-${HOST_PLATFORM}-${SHA}" } >> "$GITHUB_ENV" elif [[ "${1}" == "test" ]]; then BUILD_CUDA_MAJOR="$(cut -d '.' -f 1 <<< ${BUILD_CUDA_VER})" diff --git a/ci/tools/lookup-run-id b/ci/tools/lookup-run-id index 89833cfe1bd..15d8e7f59b0 100755 --- a/ci/tools/lookup-run-id +++ b/ci/tools/lookup-run-id @@ -18,7 +18,7 @@ set -euo pipefail usage() { cat >&2 < [workflow-name] + $0 --tag [--run-id ] [workflow-name] $0 --branch [workflow-name] Options: @@ -26,6 +26,7 @@ Options: --branch Find latest successful run on the given branch --artifact Require an unexpired artifact matching this shell glob (repeatable; branch mode only) + --run-id Validate and use this exact run ID (tag mode only) --head-sha Also print the run's head commit SHA (second line) Examples: @@ -42,6 +43,7 @@ MODE="" REF="" HEAD_SHA_FLAG=0 ARTIFACT_PATTERNS=() +EXPLICIT_RUN_ID="" while [[ $# -gt 0 ]]; do case "${1}" in @@ -53,6 +55,9 @@ while [[ $# -gt 0 ]]; do [[ $# -ge 2 ]] || usage [[ -n "${MODE}" && "${MODE}" != "branch" ]] && { echo "Error: --tag and --branch are mutually exclusive" >&2; exit 1; } MODE="branch"; REF="${2}"; shift 2 ;; + --run-id) + [[ $# -ge 2 ]] || usage + EXPLICIT_RUN_ID="${2}"; shift 2 ;; --artifact) [[ $# -ge 2 ]] || usage ARTIFACT_PATTERNS+=("${2}"); shift 2 ;; @@ -83,6 +88,16 @@ if [[ "${MODE}" != "branch" && ${#ARTIFACT_PATTERNS[@]} -gt 0 ]]; then exit 1 fi +if [[ "${MODE}" != "tag" && -n "${EXPLICIT_RUN_ID}" ]]; then + echo "Error: --run-id is only supported with --tag" >&2 + exit 1 +fi + +if [[ -n "${EXPLICIT_RUN_ID}" && ! "${EXPLICIT_RUN_ID}" =~ ^[1-9][0-9]*$ ]]; then + echo "Error: --run-id must be a positive integer" >&2 + exit 1 +fi + # ── Prerequisite checks ── if [[ -z "${GH_TOKEN:-}" ]]; then echo "Error: GH_TOKEN environment variable is required" >&2 @@ -246,7 +261,7 @@ fi # ── Mode: tag ── echo "Looking up run ID for tag: ${REF} in repository: ${REPOSITORY}" >&2 -if ! COMMIT_SHA=$(git rev-parse "${REF}^{commit}"); then +if ! COMMIT_SHA=$(git rev-parse --verify "refs/tags/${REF}^{commit}"); then echo "Error: Could not resolve git tag '${REF}' to a commit SHA" >&2 echo "Make sure the tag exists and you have fetched it" >&2 exit 1 @@ -255,6 +270,42 @@ fi echo "Resolved tag '${REF}' to commit: ${COMMIT_SHA}" >&2 echo "Searching for '${WORKFLOW_NAME}' workflow runs for commit: ${COMMIT_SHA} (tag: ${REF})" >&2 +if [[ -n "${EXPLICIT_RUN_ID}" ]]; then + echo "Validating explicitly requested run ID: ${EXPLICIT_RUN_ID}" >&2 + if ! RUN_DATA=$(gh run view "${EXPLICIT_RUN_ID}" \ + --repo "${REPOSITORY}" \ + --json databaseId,workflowName,status,conclusion,headSha,headBranch,event,createdAt,url); then + echo "Error: Could not inspect workflow run ${EXPLICIT_RUN_ID}" >&2 + exit 1 + fi + + if ! jq -e \ + --argjson id "${EXPLICIT_RUN_ID}" \ + --arg workflow "${WORKFLOW_NAME}" \ + --arg sha "${COMMIT_SHA}" \ + --arg tag "${REF}" \ + '.databaseId == $id + and .workflowName == $workflow + and .status == "completed" + and .conclusion == "success" + and .headSha == $sha + and .headBranch == $tag + and .event == "push"' <<< "${RUN_DATA}" >/dev/null; then + echo "Error: Run ${EXPLICIT_RUN_ID} is not a successful tag-triggered '${WORKFLOW_NAME}' run for '${REF}' at ${COMMIT_SHA}" >&2 + echo "Observed run metadata:" >&2 + jq -c '{workflowName, status, conclusion, headSha, headBranch, event}' <<< "${RUN_DATA}" >&2 + exit 1 + fi + + echo "Validated workflow run ID: ${EXPLICIT_RUN_ID} for tag '${REF}'" >&2 + echo "${EXPLICIT_RUN_ID}" + if [[ "${HEAD_SHA_FLAG}" == 1 ]]; then + echo "Head SHA: ${COMMIT_SHA}" >&2 + echo "${COMMIT_SHA}" + fi + exit 0 +fi + RUN_DATA=$(gh run list \ --repo "${REPOSITORY}" \ --commit "${COMMIT_SHA}" \ @@ -270,8 +321,11 @@ if [[ -z "${RUN_DATA}" || "${RUN_DATA}" == "[]" ]]; then exit 1 fi -RUN_ID=$(echo "${RUN_DATA}" | jq -r --arg tag "${REF}" ' - map(select(.conclusion == "success" and .event == "push" and .headBranch == $tag)) +RUN_ID=$(echo "${RUN_DATA}" | jq -r \ + --arg tag "${REF}" --arg workflow "${WORKFLOW_NAME}" --arg sha "${COMMIT_SHA}" ' + map(select(.conclusion == "success" and .status == "completed" + and .event == "push" and .headBranch == $tag + and .workflowName == $workflow and .headSha == $sha)) | sort_by(.createdAt) | reverse | .[0].databaseId // empty diff --git a/ci/tools/tests/test_bindings_release_compat.py b/ci/tools/tests/test_bindings_release_compat.py new file mode 100644 index 00000000000..e5670250de5 --- /dev/null +++ b/ci/tools/tests/test_bindings_release_compat.py @@ -0,0 +1,129 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +import json + +import pytest +import yaml + +from ci.tools.bindings_config import main, parse_config, resolve_release_bindings_package, write_github_env + + +def _source(root, *, old=False, schema2=False): + current_root = "cuda_bindings" if old else "cuda_bindings_13" + packages = { + "cuda_bindings_12": {"toolkit_version": "12.9.1", "release_status": "maintenance"}, + current_root: {"toolkit_version": "13.4.2", "release_status": "current"}, + } + raw = {"cuda": {"build": {"version": "13.4.2"}, "prev_build": {"version": "12.9.1"}}} + if not old: + raw["python"] = {"supported": ["3.11", "3.14t"]} + if schema2: + raw["schema_version"] = 2 + raw["cuda"] = {"bindings": {"package_roots": packages}} + config = root / "ci" / "versions.yml" + config.parent.mkdir(parents=True) + config.write_text(yaml.safe_dump(raw)) + (root / current_root).mkdir() + if not old: + (root / "cuda_bindings_12").mkdir() + return root, raw + + +@pytest.mark.parametrize( + ("old", "schema2", "tag", "expected_root", "legacy_artifact"), + [ + (True, False, "v13.4.4", "cuda_bindings", True), + (False, False, "v12.9.11", "cuda_bindings_12", False), + (False, True, "v12.9.11", "cuda_bindings_12", False), + (False, True, "v13.4.9", "cuda_bindings_13", False), + ], +) +@pytest.mark.agent_authored(model="gpt-6") +def test_tagged_source_compatibility(tmp_path, old, schema2, tag, expected_root, legacy_artifact): + source, _ = _source(tmp_path, old=old, schema2=schema2) + record = resolve_release_bindings_package(tag, source) + assert record["package_root"] == expected_root + assert record["release_version"] == tag.removeprefix("v") + assert record.get("allow_legacy_python_artifact", False) is legacy_artifact + + +@pytest.mark.agent_authored(model="gpt-6") +def test_old_cuda13_source_cannot_resolve_cuda12(tmp_path): + source, _ = _source(tmp_path, old=True) + with pytest.raises(ValueError, match="no bindings root"): + resolve_release_bindings_package("v12.9.11", source) + + +@pytest.mark.agent_authored(model="gpt-6") +def test_release_cli_uses_tagged_source_without_control_fallback(tmp_path, capsys): + source, _ = _source(tmp_path / "tagged", old=True) + assert ( + main( + [ + "--config", + str(tmp_path / "absent-control.yml"), + "--release-tag", + "v13.4.4", + "--release-source-root", + str(source), + ] + ) + == 0 + ) + assert json.loads(capsys.readouterr().out) == { + "package_root": "cuda_bindings", + "toolkit_version": "13.4.2", + "release_version": "13.4.4", + "allow_legacy_python_artifact": True, + } + empty = tmp_path / "absent-source" + empty.mkdir() + with pytest.raises(SystemExit): + main( + [ + "--config", + str(source / "ci/versions.yml"), + "--release-tag", + "v13.4.4", + "--release-source-root", + str(empty), + ] + ) + + +@pytest.mark.agent_authored(model="gpt-6") +def test_dependent_release_uses_current_tagged_bindings(tmp_path): + source, _ = _source(tmp_path, schema2=True) + assert resolve_release_bindings_package("cuda-core-v1.2.0", source) == { + "package_root": "cuda_bindings_13", + "toolkit_version": "13.4.2", + } + + +@pytest.mark.parametrize("conflict", ["roles", "majors"]) +@pytest.mark.agent_authored(model="gpt-6") +def test_schema2_rejects_ambiguous_release_routing(tmp_path, conflict): + _, raw = _source(tmp_path, schema2=True) + maintenance = raw["cuda"]["bindings"]["package_roots"]["cuda_bindings_12"] + maintenance["release_status" if conflict == "roles" else "toolkit_version"] = ( + "current" if conflict == "roles" else "13.4.1" + ) + message = "one current and one maintenance" if conflict == "roles" else "cuda_major values must be unique" + with pytest.raises(ValueError, match=message): + parse_config(raw) + + +@pytest.mark.agent_authored(model="gpt-6") +def test_github_env_exports_record_without_newline_injection(tmp_path): + path = tmp_path / "github-env" + record = {"package_root": "cuda_bindings_12", "toolkit_version": "12.9.1", "note": "one\ntwo"} + write_github_env(record, path) + before = path.read_text() + lines = before.splitlines() + assert lines[:2] == ["BUILD_CTK_VER=12.9.1", "BINDINGS_PACKAGE_ROOT=cuda_bindings_12"] + assert len(lines) == 3 + assert json.loads(lines[2].split("=", 1)[1]) == record + with pytest.raises(ValueError, match="resolved package_root"): + write_github_env({**record, "package_root": "cuda_bindings_12\nINJECTED=1"}, path) + assert path.read_text() == before diff --git a/ci/tools/tests/test_check_release_notes.py b/ci/tools/tests/test_check_release_notes.py index 30301be302c..a447fbc2fea 100644 --- a/ci/tools/tests/test_check_release_notes.py +++ b/ci/tools/tests/test_check_release_notes.py @@ -3,336 +3,224 @@ from __future__ import annotations -import sys +import json from pathlib import Path import pytest -sys.path.insert(0, str(Path(__file__).parent.parent)) -from check_release_notes import ( - check_release_notes, - is_post_release, - load_backport_branch, - main, - parse_version_from_tag, -) - - -class TestParseVersionFromTag: - def test_plain_tag_bindings(self): - assert parse_version_from_tag("v13.1.0", "cuda-bindings") == "13.1.0" - - def test_plain_tag_python(self): - assert parse_version_from_tag("v13.1.0", "cuda-python") == "13.1.0" - - def test_component_prefix_core(self): - assert parse_version_from_tag("cuda-core-v0.7.0", "cuda-core") == "0.7.0" - - def test_component_prefix_pathfinder(self): - assert parse_version_from_tag("cuda-pathfinder-v1.5.2", "cuda-pathfinder") == "1.5.2" +from ci.tools.check_release_notes import check_release_notes, main, notes_path, parse_version_from_tag - def test_post_release(self): - assert parse_version_from_tag("v12.6.2.post1", "cuda-bindings") == "12.6.2.post1" - def test_invalid_tag(self): - assert parse_version_from_tag("not-a-tag", "cuda-core") is None +def write_notes(root: Path, package: str, version: str, content: str = "Release notes.") -> Path: + path = root / notes_path(package, version) + path.parent.mkdir(parents=True, exist_ok=True) + path.write_text(content, encoding="utf-8") + return path - def test_no_v_prefix(self): - assert parse_version_from_tag("13.1.0", "cuda-bindings") is None - def test_component_prefix_mismatch(self): - # cuda-core-v* must not be accepted for component=cuda-pathfinder - assert parse_version_from_tag("cuda-core-v0.7.0", "cuda-pathfinder") is None +def resolved_12_package(package_root: str = "cuda_bindings_12") -> dict[str, object]: + return { + "package_root": package_root, + "toolkit_version": "12.9.1", + "release_version": "12.9.8", + } - def test_bare_v_rejected_for_core(self): - # bare v* belongs to cuda-bindings/cuda-python, not cuda-core - assert parse_version_from_tag("v0.7.0", "cuda-core") is None - def test_unknown_component(self): - assert parse_version_from_tag("v13.1.0", "bogus") is None +@pytest.mark.parametrize( + ("tag", "component", "version"), + ( + ("v13.4.1", "cuda-bindings", "13.4.1"), + ("v13.4.1rc1", "cuda-bindings", "13.4.1rc1"), + ("v13.4.1.dev1", "cuda-bindings", "13.4.1.dev1"), + ("v12.9.8.post1", "cuda-python", "12.9.8.post1"), + ("cuda-core-v1.1.1", "cuda-core", "1.1.1"), + ("cuda-pathfinder-v1.8.1", "cuda-pathfinder", "1.8.1"), + ), +) +@pytest.mark.agent_authored(model="gpt-5.6") +def test_parse_version_from_tag(tag, component, version): + assert parse_version_from_tag(tag, component) == version - def test_path_traversal_rejected(self): - assert parse_version_from_tag("v1.0.0/../evil", "cuda-bindings") is None - def test_path_separator_rejected(self): - assert parse_version_from_tag("v1/2/3", "cuda-bindings") is None +@pytest.mark.parametrize( + ("tag", "component"), + ( + ("not-a-tag", "cuda-core"), + ("v1.0.0/../evil", "cuda-bindings"), + ("cuda-core-v1.0.0", "cuda-pathfinder"), + ("vv13.3.0", "cuda-bindings"), + ("cuda-core-vv1.0.0", "cuda-core"), + ("cuda-core-v1!2.0.0", "cuda-core"), + ("cuda-core-v1.0.0-1", "cuda-core"), + ("cuda-core-v01.0.0", "cuda-core"), + ("cuda-core-v1.0", "cuda-core"), + ), +) +@pytest.mark.agent_authored(model="gpt-5.6") +def test_parse_version_rejects_invalid_or_mismatched_tags(tag, component): + assert parse_version_from_tag(tag, component) is None - def test_leading_dot_rejected(self): - assert parse_version_from_tag("v.1.0", "cuda-bindings") is None - def test_whitespace_rejected(self): - assert parse_version_from_tag("v1.0.0 ", "cuda-bindings") is None +@pytest.mark.parametrize( + ("tag", "package", "version"), + ( + ("v13.4.1", "cuda_bindings_13", "13.4.1"), + ("v12.9.8", "cuda_bindings_12", "12.9.8"), + ), +) +@pytest.mark.agent_authored(model="gpt-5.6") +def test_bindings_notes_follow_current_and_maintenance_packages(tmp_path, tag, package, version): + write_notes(tmp_path, package, version) + + assert check_release_notes(tag, "cuda-bindings", tmp_path) == [] + + +@pytest.mark.parametrize("version", ("12.9.8", "12.9.8rc1", "12.9.8.dev1")) +@pytest.mark.agent_authored(model="gpt-6") +def test_resolved_package_selects_exact_version_and_tagged_root(tmp_path, version): + package_root = "cuda_bindings_12_maintenance" + package = resolved_12_package(package_root) + package["release_version"] = version + write_notes(tmp_path, package_root, version) + + problems = check_release_notes( + f"v{version}", + "cuda-bindings", + tmp_path, + package, + ) - def test_trailing_suffix_rejected(self): - # \w permits alphanumerics + underscore only; hyphens and shell meta-chars are out - assert parse_version_from_tag("v1.0.0-extra", "cuda-bindings") is None + assert problems == [] -class TestIsPostRelease: - def test_normal(self): - assert not is_post_release("13.1.0") +@pytest.mark.agent_authored(model="gpt-5.6") +def test_present_missing_and_empty_notes(tmp_path): + write_notes(tmp_path, "cuda_core", "1.1.1") + assert check_release_notes("cuda-core-v1.1.1", "cuda-core", tmp_path) == [] - def test_post(self): - assert is_post_release("12.6.2.post1") + missing = check_release_notes("cuda-pathfinder-v1.8.1", "cuda-pathfinder", tmp_path) + assert missing == [(notes_path("cuda_pathfinder", "1.8.1"), "missing")] - def test_post_no_number(self): - assert is_post_release("1.0.0.post") + write_notes(tmp_path, "cuda_python", "13.3.0", content="") + empty = check_release_notes("v13.3.0", "cuda-python", tmp_path) + assert empty == [(notes_path("cuda_python", "13.3.0"), "empty")] -class TestCheckReleaseNotes: - def _make_notes(self, tmp_path, pkg, version, content="Release notes."): - d = tmp_path / pkg / "docs" / "source" / "release" - d.mkdir(parents=True, exist_ok=True) - f = d / f"{version}-notes.rst" - f.write_text(content) - return f +@pytest.mark.agent_authored(model="gpt-5.6") +def test_post_release_needs_no_notes(tmp_path): + assert check_release_notes("v12.9.8.post1", "cuda-bindings", tmp_path) == [] - def test_present_and_nonempty(self, tmp_path): - self._make_notes(tmp_path, "cuda_core", "0.7.0") - problems = check_release_notes("cuda-core-v0.7.0", "cuda-core", tmp_path) - assert problems == [] - def test_missing(self, tmp_path): - problems = check_release_notes("cuda-core-v0.7.0", "cuda-core", tmp_path) - assert len(problems) == 1 - assert problems[0][1] == "missing" +@pytest.mark.agent_authored(model="gpt-5.6") +def test_main_accepts_resolved_package_and_reports_missing_notes(tmp_path, capsys): + package = resolved_12_package() + args = [ + "--git-tag", + "v12.9.8", + "--component", + "cuda-bindings", + "--repo-root", + str(tmp_path), + "--bindings-package", + json.dumps(package), + ] - def test_empty(self, tmp_path): - self._make_notes(tmp_path, "cuda_core", "0.7.0", content="") - problems = check_release_notes("cuda-core-v0.7.0", "cuda-core", tmp_path) - assert len(problems) == 1 - assert problems[0][1] == "empty" + assert main(args) == 1 + assert "cuda_bindings_12/docs/source/release/12.9.8-notes.rst" in capsys.readouterr().err - def test_post_release_skipped(self, tmp_path): - problems = check_release_notes("v12.6.2.post1", "cuda-bindings", tmp_path) - assert problems == [] + write_notes(tmp_path, "cuda_bindings_12", "12.9.8") + assert main(args) == 0 - def test_invalid_tag(self, tmp_path): - problems = check_release_notes("not-a-tag", "cuda-core", tmp_path) - assert len(problems) == 1 - assert "cannot parse" in problems[0][1] - def test_component_prefix_mismatch(self, tmp_path): - # Pass a cuda-core tag with component=cuda-pathfinder; must be rejected. - problems = check_release_notes("cuda-core-v0.7.0", "cuda-pathfinder", tmp_path) - assert len(problems) == 1 - assert "cannot parse" in problems[0][1] +@pytest.mark.agent_authored(model="gpt-5.6") +def test_main_rejects_unsafe_resolved_package_root(tmp_path, capsys): + args = [ + "--git-tag", + "v12.9.8", + "--component", + "cuda-bindings", + "--repo-root", + str(tmp_path), + "--bindings-package", + json.dumps(resolved_12_package("../outside")), + ] - def test_unknown_component(self, tmp_path): - problems = check_release_notes("v13.1.0", "bogus", tmp_path) - assert len(problems) == 1 - assert "unknown component" in problems[0][1] + assert main(args) == 2 + assert "normalized repository-relative POSIX path" in capsys.readouterr().err - def test_plain_v_tag(self, tmp_path): - self._make_notes(tmp_path, "cuda_python", "13.1.0") - problems = check_release_notes("v13.1.0", "cuda-python", tmp_path) - assert problems == [] +def release_args(repo_root: Path, component: str, package: dict[str, object]) -> list[str]: + args = [ + "--git-tag", + "v12.9.8", + "--component", + component, + "--repo-root", + str(repo_root), + "--bindings-package", + json.dumps(package), + ] + return args -class TestLoadBackportBranch: - def test_from_versions_yml(self, tmp_path): - d = tmp_path / "ci" - d.mkdir(parents=True) - (d / "versions.yml").write_text('backport_branch: "12.9.x"\n') - assert load_backport_branch(tmp_path) == "12.9.x" +@pytest.mark.agent_authored(model="gpt-6") +def test_notes_in_another_checkout_do_not_satisfy_release_check(tmp_path, capsys, monkeypatch): + write_notes(tmp_path / "other", "cuda_bindings_12", "12.9.8") + monkeypatch.chdir(tmp_path / "other") - def test_from_github_ref_name_for_legacy_backport_branch(self, tmp_path, monkeypatch): - monkeypatch.setenv("GITHUB_REF_NAME", "12.9.x") + assert main(release_args(tmp_path / "tagged", "cuda-bindings", resolved_12_package())) == 1 + assert f"{notes_path('cuda_bindings_12', '12.9.8')} (missing)" in capsys.readouterr().err - assert load_backport_branch(tmp_path) == "12.9.x" - def test_ignores_non_backport_github_ref_name(self, tmp_path, monkeypatch): - monkeypatch.setenv("GITHUB_REF_NAME", "main") +@pytest.mark.agent_authored(model="gpt-6") +def test_metapackage_requires_its_own_notes(tmp_path, capsys): + write_notes(tmp_path, "cuda_bindings_12", "12.9.8") - assert load_backport_branch(tmp_path) is None + assert main(release_args(tmp_path, "cuda-python", resolved_12_package())) == 1 + assert "cuda_python/docs/source/release/12.9.8-notes.rst (missing)" in capsys.readouterr().err + write_notes(tmp_path, "cuda_python", "12.9.8") + assert main(release_args(tmp_path, "cuda-python", resolved_12_package())) == 0 -class TestMain: - def _make_notes(self, tmp_path, pkg, version, content="Release notes."): - d = tmp_path / pkg / "docs" / "source" / "release" - d.mkdir(parents=True, exist_ok=True) - (d / f"{version}-notes.rst").write_text(content) - def test_success(self, tmp_path): - d = tmp_path / "cuda_core" / "docs" / "source" / "release" - d.mkdir(parents=True) - (d / "0.7.0-notes.rst").write_text("Notes here.") - rc = main(["--git-tag", "cuda-core-v0.7.0", "--component", "cuda-core", "--repo-root", str(tmp_path)]) - assert rc == 0 - - def test_failure(self, tmp_path): - rc = main(["--git-tag", "cuda-core-v0.7.0", "--component", "cuda-core", "--repo-root", str(tmp_path)]) - assert rc == 1 - - def test_post_skip(self, tmp_path): - rc = main(["--git-tag", "v12.6.2.post1", "--component", "cuda-bindings", "--repo-root", str(tmp_path)]) - assert rc == 0 - - def test_unparsable_tag_returns_2(self, tmp_path): - rc = main(["--git-tag", "not-a-tag", "--component", "cuda-core", "--repo-root", str(tmp_path)]) - assert rc == 2 - - def test_path_traversal_returns_2(self, tmp_path): - rc = main(["--git-tag", "v1.0.0/../evil", "--component", "cuda-bindings", "--repo-root", str(tmp_path)]) - assert rc == 2 - - def test_component_prefix_mismatch_returns_2(self, tmp_path): - rc = main( - [ - "--git-tag", - "cuda-core-v0.7.0", - "--component", - "cuda-pathfinder", - "--repo-root", - str(tmp_path), - ] - ) - assert rc == 2 - - def test_mainline_bindings_requires_backport_decision(self, tmp_path, capsys): - rc = main( - [ - "--git-tag", - "v13.3.0", - "--component", - "cuda-bindings", - "--repo-root", - str(tmp_path), - "--backport-branch", - "12.9.x", - ] - ) +@pytest.mark.parametrize("component", ("cuda-bindings", "cuda-python")) +@pytest.mark.agent_authored(model="gpt-6") +def test_release_rejects_other_version_notes(tmp_path, capsys, component): + write_notes(tmp_path, "cuda_bindings_12", "12.9.7") + write_notes(tmp_path, "cuda_python", "12.9.7") - captured = capsys.readouterr() - assert rc == 1 - assert "" in captured.err - - def test_mainline_bindings_accepts_not_planned(self, tmp_path): - self._make_notes(tmp_path, "cuda_bindings_13", "13.3.0") - - rc = main( - [ - "--git-tag", - "v13.3.0", - "--component", - "cuda-bindings", - "--repo-root", - str(tmp_path), - "--backport-branch", - "12.9.x", - "--backport-git-tag", - "not planned", - ] - ) + assert main(release_args(tmp_path, component, resolved_12_package())) == 1 + assert "ERROR: missing or empty release notes" in capsys.readouterr().err - assert rc == 0 - - def test_mainline_bindings_checks_planned_backport_notes(self, tmp_path, capsys): - self._make_notes(tmp_path, "cuda_bindings_13", "13.3.0") - - rc = main( - [ - "--git-tag", - "v13.3.0", - "--component", - "cuda-bindings", - "--repo-root", - str(tmp_path), - "--backport-branch", - "12.9.x", - "--backport-git-tag", - "v12.9.7", - ] - ) - captured = capsys.readouterr() - assert rc == 1 - assert "12.9.7-notes.rst" in captured.err - - def test_mainline_bindings_accepts_planned_backport_notes(self, tmp_path): - self._make_notes(tmp_path, "cuda_bindings_13", "13.3.0") - self._make_notes(tmp_path, "cuda_bindings_13", "12.9.7") - - rc = main( - [ - "--git-tag", - "v13.3.0", - "--component", - "cuda-bindings", - "--repo-root", - str(tmp_path), - "--backport-branch", - "12.9.x", - "--backport-git-tag", - "v12.9.7", - ] - ) +@pytest.mark.agent_authored(model="gpt-6") +def test_release_rejects_resolver_version_mismatch(tmp_path, capsys): + write_notes(tmp_path, "cuda_bindings_12", "12.9.9") + package = resolved_12_package() + package["release_version"] = "12.9.9" + args = release_args(tmp_path, "cuda-bindings", package) - assert rc == 0 - - def test_mainline_cuda_python_accepts_planned_backport_notes(self, tmp_path): - self._make_notes(tmp_path, "cuda_python", "13.3.0") - self._make_notes(tmp_path, "cuda_python", "12.9.7") - - rc = main( - [ - "--git-tag", - "v13.3.0", - "--component", - "cuda-python", - "--repo-root", - str(tmp_path), - "--backport-branch", - "12.9.x", - "--backport-git-tag", - "v12.9.7", - ] - ) + assert main(args) == 2 + assert "does not match release tag" in capsys.readouterr().err - assert rc == 0 - - def test_backport_bindings_missing_notes_warns_without_failing(self, tmp_path, monkeypatch, capsys): - summary_path = tmp_path / "summary.md" - monkeypatch.setenv("GITHUB_STEP_SUMMARY", str(summary_path)) - - rc = main( - [ - "--git-tag", - "v12.9.7", - "--component", - "cuda-bindings", - "--repo-root", - str(tmp_path), - "--backport-branch", - "12.9.x", - ] - ) - captured = capsys.readouterr() - assert rc == 0 - assert "::warning file=cuda_bindings_13/docs/source/release/12.9.7-notes.rst::" in captured.out - assert "12.9.7-notes.rst" in summary_path.read_text() - - def test_mainline_bindings_rejects_non_backport_tag(self, tmp_path): - self._make_notes(tmp_path, "cuda_bindings_13", "13.3.0") - - rc = main( - [ - "--git-tag", - "v13.3.0", - "--component", - "cuda-bindings", - "--repo-root", - str(tmp_path), - "--backport-branch", - "12.9.x", - "--backport-git-tag", - "v13.2.0", - ] - ) +@pytest.mark.parametrize( + ("component", "tag"), + ( + ("cuda-bindings", "v12.9.8.post1"), + ("cuda-python", "v12.9.8.post1"), + ("cuda-core", "cuda-core-v1.1.1.post1"), + ), +) +@pytest.mark.agent_authored(model="gpt-6") +def test_main_skips_post_release_without_notes(tmp_path, capsys, component, tag): + package = resolved_12_package() + package["release_version"] = "12.9.8.post1" + args = release_args(tmp_path, component, package) + args[args.index("--git-tag") + 1] = tag - assert rc == 2 + assert main(args) == 0 + assert "skipping release-notes check" in capsys.readouterr().out @pytest.mark.parametrize("version", ["1.5.2", "1.5.2.post1"]) @@ -370,25 +258,23 @@ def test_pathfinder_missing_notes_fail_without_version_output(tmp_path, monkeypa @pytest.mark.parametrize( - "component,tag,version,extra_args", + "component,tag,version,package", [ - ("cuda-core", "cuda-core-v0.7.0", "0.7.0", []), - ("cuda-bindings", "v12.9.7", "12.9.7", ["--backport-branch", "12.9.x"]), - ("cuda-python", "v13.3.0", "13.3.0", ["--backport-branch", "12.9.x", "--backport-git-tag", "not planned"]), - ("cuda-bindings", "v12.9.7.post1", "12.9.7.post1", []), + ("cuda-core", "cuda-core-v1.1.1", "1.1.1", "cuda_core"), + ("cuda-bindings", "v12.9.8", "12.9.8", "cuda_bindings_12"), + ("cuda-bindings", "v12.9.8.post1", "12.9.8.post1", "cuda_bindings_12"), + ("cuda-python", "v13.3.0", "13.3.0", "cuda_python"), ], ) @pytest.mark.agent_authored(model="gpt-6.1") -def test_successful_checks_expose_version_for_every_policy(tmp_path, monkeypatch, component, tag, version, extra_args): - if component == "cuda-core" or version == "13.3.0": - notes = tmp_path / component.replace("-", "_") / "docs" / "source" / "release" / f"{version}-notes.rst" - notes.parent.mkdir(parents=True) - notes.write_text("Release notes.") +def test_successful_checks_expose_version_for_every_policy(tmp_path, monkeypatch, component, tag, version, package): + if ".post" not in version: + write_notes(tmp_path, package, version) output = tmp_path / "output" output.write_text("existing=value\n") monkeypatch.setenv("GITHUB_OUTPUT", str(output)) - assert main(["--git-tag", tag, "--component", component, "--repo-root", str(tmp_path), *extra_args]) == 0 + assert main(["--git-tag", tag, "--component", component, "--repo-root", str(tmp_path)]) == 0 assert output.read_text() == f"existing=value\nversion={version}\n" diff --git a/ci/tools/tests/test_download_wheels.py b/ci/tools/tests/test_download_wheels.py new file mode 100644 index 00000000000..5eba0ec224f --- /dev/null +++ b/ci/tools/tests/test_download_wheels.py @@ -0,0 +1,135 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +"""Keep unrelated CUDA lines and test artifacts out of release staging.""" + +import json +import os +import subprocess +from pathlib import Path + +import pytest + +DOWNLOAD_WHEELS = Path(__file__).parent.parent / "download-wheels" +FAKE_GH = r"""#!/usr/bin/env python3 +import fnmatch +import json +import os +import sys +from pathlib import Path + +args = sys.argv[1:] +artifacts = json.loads(os.environ["FAKE_ARTIFACTS"]) +if args[:1] == ["api"]: + print(*artifacts, sep="\n") + raise SystemExit(0) +if args[:2] == ["run", "download"]: + selector = "--name" if "--name" in args else "-p" + pattern = args[args.index(selector) + 1] + selected = [artifact for artifact in artifacts if fnmatch.fnmatchcase(artifact, pattern)] + for artifact in selected: + destination = Path(args[args.index("--dir") + 1]) / artifact + destination.mkdir(parents=True) + suffix = ".so" if artifact.endswith("-tests") else ".whl" + (destination / f"{artifact}{suffix}").touch() + raise SystemExit(0 if selected else 1) +raise SystemExit(2) +""" + + +def run_download(tmp_path, artifacts, component, *, package=None, tag=""): + binary = tmp_path / "gh" + binary.write_text(FAKE_GH, encoding="utf-8") + binary.chmod(0o755) + args = [str(DOWNLOAD_WHEELS), "123", component, "NVIDIA/cuda-python", str(tmp_path / "dist"), tag] + if package is not None: + args.append(json.dumps(package)) + return subprocess.run( # noqa: S603 - the checked-in utility receives separate arguments. + args, + cwd=tmp_path, + env={ + **os.environ, + "FAKE_ARTIFACTS": json.dumps(artifacts), + "GH_TOKEN": "test-token", + "PATH": f"{tmp_path}{os.pathsep}{os.environ['PATH']}", + }, + check=False, + capture_output=True, + text=True, + ) + + +@pytest.mark.parametrize("component", ["cuda-bindings", "cuda-python"]) +@pytest.mark.parametrize("major,toolkit", [(12, "12.9.1"), (13, "13.3.0")]) +@pytest.mark.agent_authored(model="gpt-6.1-sol") +def test_release_stages_only_wheels_for_its_exact_toolkit(tmp_path, component, major, toolkit): + release = f"{toolkit.rsplit('.', 1)[0]}.99" + package = {"package_root": f"cuda_bindings_{major}", "toolkit_version": toolkit, "release_version": release} + prefix = "cuda-bindings-python312" if component == "cuda-bindings" else "cuda-python-wheel" + suffix = "-linux-64-sha" if component == "cuda-bindings" else "" + expected = f"{prefix}-cuda{toolkit}{suffix}" + result = run_download( + tmp_path, + [f"{prefix}-cuda11.8.0{suffix}", expected, f"{expected}-tests", "cuda-python-wheel"], + component, + package=package, + tag=f"v{package['release_version']}", + ) + assert result.returncode == 0, result.stderr + assert {path.name for path in (tmp_path / "dist").iterdir()} == {f"{expected}.whl"} + + +@pytest.mark.parametrize("component", ["cuda-bindings", "cuda-python"]) +@pytest.mark.agent_authored(model="gpt-6.1-sol") +def test_release_cannot_stage_another_toolkit_or_test_artifacts(tmp_path, component): + package = {"package_root": "cuda_bindings_13", "toolkit_version": "13.3.0", "release_version": "13.3.1"} + result = run_download( + tmp_path, + ["cuda-bindings-python312-cuda13.3.0-linux-64-sha-tests", "cuda-python-wheel-cuda13.2.0"], + component, + package=package, + tag="v13.3.1", + ) + assert result.returncode != 0 + assert not list((tmp_path / "dist").glob("*.whl")) + + +@pytest.mark.agent_authored(model="gpt-6.1-sol") +def test_release_routing_requires_a_resolved_package(tmp_path): + result = run_download(tmp_path, ["cuda-python-wheel-cuda13.3.0"], "cuda-python", tag="v13.3.1") + assert result.returncode != 0 + assert not list((tmp_path / "dist").glob("*.whl")) + + +@pytest.mark.parametrize( + "component,expected", + [("all", {"cuda-core-wheel", "cuda-python-wheel-cuda13.3.0"}), ("cuda-core", {"cuda-core-wheel"})], +) +@pytest.mark.agent_authored(model="gpt-6.1-sol") +def test_nonrelease_components_stage_wheels_without_test_artifacts(tmp_path, component, expected): + result = run_download( + tmp_path, + ["cuda-core-wheel", "cuda-core-wheel-tests", "cuda-python-wheel-cuda13.3.0", "build-metadata"], + component, + ) + assert result.returncode == 0, result.stderr + assert {path.name for path in (tmp_path / "dist").iterdir()} == {f"{artifact}.whl" for artifact in expected} + + +@pytest.mark.parametrize( + ("toolkit", "artifacts", "expected"), + [ + ("13.4.2", ["cuda-python-wheel"], "cuda-python-wheel"), + ("13.4.2", ["cuda-python-wheel", "cuda-python-wheel-cuda13.4.2"], "cuda-python-wheel-cuda13.4.2"), + ("12.9.1", ["cuda-python-wheel"], None), + ], +) +@pytest.mark.agent_authored(model="GPT-6") +def test_legacy_metapackage_fallback_is_limited_to_cuda_13(tmp_path, toolkit, artifacts, expected): + package = {"toolkit_version": toolkit, "allow_legacy_python_artifact": True} + result = run_download(tmp_path, artifacts, "cuda-python", package=package, tag=f"v{toolkit}") + + assert (result.returncode == 0) == (expected is not None), result.stderr + assert {path.name for path in (tmp_path / "dist").glob("*.whl")} == ( + set() if expected is None else {f"{expected}.whl"} + ) diff --git a/ci/tools/tests/test_validate_release_wheels.py b/ci/tools/tests/test_validate_release_wheels.py new file mode 100644 index 00000000000..7bebf93677e --- /dev/null +++ b/ci/tools/tests/test_validate_release_wheels.py @@ -0,0 +1,218 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +from __future__ import annotations + +import json +import subprocess +import sys +from pathlib import Path + +import pytest +import yaml + +from ci.tools.validate_release_wheels import WheelTarget, expected_binary_targets + + +def resolved_package() -> str: + return json.dumps( + { + "package_root": "alternate_bindings_12_8", + "toolkit_version": "12.8.0", + "release_version": "12.8.0", + }, + separators=(",", ":"), + ) + + +def write_release_matrix( + root: Path, + *, + python_versions: tuple[str, ...] = ("3.12",), + platforms: tuple[str, ...] = ("linux-64",), +) -> None: + config = root / "ci" / "versions.yml" + config.parent.mkdir(parents=True, exist_ok=True) + config.write_text(yaml.safe_dump({"python": {"supported": list(python_versions)}}), encoding="utf-8") + ci_workflow = root / ".github" / "workflows" / "ci.yml" + ci_workflow.parent.mkdir(parents=True, exist_ok=True) + ci_workflow.write_text( + yaml.safe_dump( + { + "jobs": { + f"build-{platform}": { + "uses": "./.github/workflows/build-wheel.yml", + "with": {"host-platform": platform}, + } + for platform in platforms + } + } + ), + encoding="utf-8", + ) + + +def run_validator( + wheel_dir: Path, + release_source_root: Path, + *extra_args: str, + git_tag: str = "v12.8.0", + component: str = "cuda-bindings", +) -> subprocess.CompletedProcess[str]: + return subprocess.run( # noqa: S603 - invokes the repository script under test + [ + sys.executable, + "-m", + "ci.tools.validate_release_wheels", + git_tag, + component, + str(wheel_dir), + "--release-source-root", + str(release_source_root), + *extra_args, + ], + check=False, + capture_output=True, + text=True, + ) + + +@pytest.fixture +def release_source(tmp_path): + root = tmp_path / "release-source" + write_release_matrix(root) + return root + + +@pytest.mark.agent_authored(model="gpt-5.6-sol") +def test_tag_authoritative_package_validates_after_control_registry_moves_on(tmp_path, release_source): + (tmp_path / "cuda_bindings-12.8.0-cp312-cp312-manylinux_2_28_x86_64.whl").touch() + + without_resolved_package = run_validator(tmp_path, release_source) + with_resolved_package = run_validator( + tmp_path, + release_source, + "--bindings-package", + resolved_package(), + ) + + assert without_resolved_package.returncode == 1 + assert with_resolved_package.returncode == 0, with_resolved_package.stderr + + +@pytest.mark.agent_authored(model="gpt-5.6-sol") +def test_resolved_package_must_match_the_release_tag(tmp_path, release_source): + (tmp_path / "cuda_bindings-12.8.0-cp312-cp312-manylinux_2_28_x86_64.whl").touch() + package = json.loads(resolved_package()) + package["release_version"] = "12.9.0" + + result = run_validator(tmp_path, release_source, "--bindings-package", json.dumps(package)) + + assert result.returncode == 1 + assert "does not match release tag" in result.stderr + + +@pytest.mark.agent_authored(model="gpt-5.6") +def test_unexpected_distribution_is_rejected(tmp_path, release_source): + (tmp_path / "cuda_bindings-12.8.0-cp312-cp312-manylinux_2_28_x86_64.whl").touch() + unexpected_wheel = "cuda_core-12.8.0-py3-none-any.whl" + (tmp_path / unexpected_wheel).touch() + + result = run_validator(tmp_path, release_source, "--bindings-package", resolved_package()) + + assert result.returncode == 1 + assert f"{unexpected_wheel}: unexpected distribution 'cuda_core'" in result.stderr + + +@pytest.mark.agent_authored(model="gpt-5.6-sol") +def test_complete_binary_wheel_matrix_is_required(tmp_path): + release_source = tmp_path / "release-source" + write_release_matrix( + release_source, + python_versions=("3.11", "3.14t", "3.15", "3.15t"), + platforms=("linux-64", "win-64"), + ) + wheel_names = ( + "cuda_bindings-12.8.0-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", + "cuda_bindings-12.8.0-cp311-cp311-win_amd64.whl", + "cuda_bindings-12.8.0-cp314-cp314t-manylinux_2_28_x86_64.whl", + "cuda_bindings-12.8.0-cp315-cp315-manylinux_2_28_x86_64.whl", + "cuda_bindings-12.8.0-cp315-cp315-win_amd64.whl", + "cuda_bindings-12.8.0-cp315-cp315t-manylinux_2_28_x86_64.whl", + "cuda_bindings-12.8.0-cp315-cp315t-win_amd64.whl", + "cuda_bindings-12.8.0-cp314-cp314t-win_amd64.whl", + ) + for wheel_name in wheel_names: + (tmp_path / wheel_name).touch() + + complete = run_validator( + tmp_path, + release_source, + "--bindings-package", + resolved_package(), + ) + (tmp_path / wheel_names[-1]).unlink() + partial = run_validator( + tmp_path, + release_source, + "--bindings-package", + resolved_package(), + ) + + assert complete.returncode == 0, complete.stderr + assert partial.returncode == 1 + assert "Missing expected cuda_bindings wheel targets: cp314-cp314t-win_amd64" in partial.stderr + + +@pytest.mark.agent_authored(model="gpt-5.6-sol") +def test_windows_arm64_targets_follow_the_tagged_toolkit_line(tmp_path): + release_source = tmp_path / "release-source" + write_release_matrix( + release_source, + python_versions=("3.10", "3.11"), + platforms=("linux-64", "win-arm64"), + ) + + cuda_12 = expected_binary_targets(release_source, {"toolkit_version": "12.9.1"}) + cuda_13 = expected_binary_targets(release_source, {"toolkit_version": "13.4.1"}) + + assert cuda_12 == { + WheelTarget("cp310", "cp310", "manylinux-x86_64"), + WheelTarget("cp311", "cp311", "manylinux-x86_64"), + } + assert cuda_13 == cuda_12 | {WheelTarget("cp311", "cp311", "win_arm64")} + + +@pytest.mark.agent_authored(model="gpt-5.6-sol") +def test_cuda_core_uses_the_complete_binary_wheel_matrix(tmp_path): + release_source = tmp_path / "release-source" + write_release_matrix(release_source, platforms=("linux-64", "win-64")) + (tmp_path / "cuda_core-1.2.0-cp312-cp312-manylinux_2_28_x86_64.whl").touch() + (tmp_path / "cuda_core-1.2.0-cp312-cp312-win_amd64.whl").touch() + + result = run_validator( + tmp_path, + release_source, + "--bindings-package", + resolved_package(), + git_tag="cuda-core-v1.2.0", + component="cuda-core", + ) + + assert result.returncode == 0, result.stderr + + +@pytest.mark.agent_authored(model="GPT-6") +def test_retained_tag_uses_its_build_workflow_python_matrix(tmp_path): + write_release_matrix(tmp_path, platforms=("linux-64", "win-arm64")) + (tmp_path / "ci/versions.yml").write_text("cuda:\n build:\n version: '13.4.2'\n", encoding="utf-8") + (tmp_path / ".github/workflows/build-wheel.yml").write_text( + yaml.safe_dump({"jobs": {"build": {"strategy": {"matrix": {"python-version": ["3.10", "3.12"]}}}}}), + encoding="utf-8", + ) + + assert expected_binary_targets(tmp_path, {"toolkit_version": "13.4.2"}) == { + WheelTarget("cp310", "cp310", "manylinux-x86_64"), + WheelTarget("cp312", "cp312", "manylinux-x86_64"), + WheelTarget("cp312", "cp312", "win_arm64"), + } diff --git a/ci/tools/validate-release-wheels b/ci/tools/validate-release-wheels deleted file mode 100755 index 52d24df4731..00000000000 --- a/ci/tools/validate-release-wheels +++ /dev/null @@ -1,138 +0,0 @@ -#!/usr/bin/env python3 - -# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -# -# SPDX-License-Identifier: Apache-2.0 - -"""Validate downloaded release wheels against the requested release tag.""" - -from __future__ import annotations - -import argparse -import sys -from collections import defaultdict -from pathlib import Path - -from check_release_notes import parse_version_from_tag - -COMPONENT_TO_DISTRIBUTIONS: dict[str, set[str]] = { - "cuda-core": {"cuda_core"}, - "cuda-bindings": {"cuda_bindings"}, - "cuda-pathfinder": {"cuda_pathfinder"}, - "cuda-python": {"cuda_python"}, - "all": {"cuda_core", "cuda_bindings", "cuda_pathfinder", "cuda_python"}, -} - -COMPONENT_TO_TAG_COMPONENTS: dict[str, tuple[str, ...]] = { - "cuda-core": ("cuda-core",), - "cuda-bindings": ("cuda-bindings",), - "cuda-pathfinder": ("cuda-pathfinder",), - "cuda-python": ("cuda-python",), - "all": ("cuda-core", "cuda-bindings", "cuda-pathfinder", "cuda-python"), -} - - -def parse_args() -> argparse.Namespace: - parser = argparse.ArgumentParser( - description=( - "Validate that wheel versions match the release tag. " - "This rejects dev/local wheel versions for release uploads." - ) - ) - parser.add_argument("git_tag", help="Release git tag (for example: v13.0.0)") - parser.add_argument("component", choices=sorted(COMPONENT_TO_DISTRIBUTIONS.keys())) - parser.add_argument("wheel_dir", help="Directory containing wheel files") - return parser.parse_args() - - -def version_from_tag(tag: str, component: str) -> str: - versions = { - version - for tag_component in COMPONENT_TO_TAG_COMPONENTS[component] - if (version := parse_version_from_tag(tag, tag_component)) is not None - } - if len(versions) == 1: - return versions.pop() - raise ValueError( - "Unsupported git tag format " - f"{tag!r} for component {component!r}; expected vX.Y.Z[.postN], " - "cuda-core-vX.Y.Z[.postN], or cuda-pathfinder-vX.Y.Z[.postN]." - ) - - -def parse_wheel_dist_and_version(path: Path) -> tuple[str, str]: - # Wheel name format starts with: {distribution}-{version}-... - parts = path.stem.split("-") - if len(parts) < 5: - raise ValueError(f"Invalid wheel filename format: {path.name}") - return parts[0], parts[1] - - -def main() -> int: - args = parse_args() - try: - expected_version = version_from_tag(args.git_tag, args.component) - except ValueError as exc: - print(f"Error: {exc}", file=sys.stderr) - return 1 - - expected_distributions = COMPONENT_TO_DISTRIBUTIONS[args.component] - wheel_dir = Path(args.wheel_dir) - - wheels = sorted(wheel_dir.glob("*.whl")) - if not wheels: - print(f"Error: No wheel files found in {wheel_dir}", file=sys.stderr) - return 1 - - seen_versions: dict[str, set[str]] = defaultdict(set) - errors: list[str] = [] - - for wheel in wheels: - try: - distribution, version = parse_wheel_dist_and_version(wheel) - except ValueError as exc: - errors.append(str(exc)) - continue - - if distribution not in expected_distributions: - continue - - seen_versions[distribution].add(version) - - if ".dev" in version or "+" in version: - errors.append( - f"{wheel.name}: wheel version {version!r} contains dev/local markers " - "(.dev or +), which is not allowed for release uploads." - ) - - if version != expected_version: - errors.append( - f"{wheel.name}: wheel version {version!r} does not match expected " - f"release version {expected_version!r} from git tag {args.git_tag!r}." - ) - - missing_distributions = sorted(expected_distributions - set(seen_versions)) - if missing_distributions: - errors.append("Missing expected component wheels in download set: " + ", ".join(missing_distributions)) - - for distribution, versions in sorted(seen_versions.items()): - if len(versions) > 1: - errors.append( - f"Expected one release version for {distribution}, found multiple: " + ", ".join(sorted(versions)) - ) - - if errors: - print("Wheel validation failed:", file=sys.stderr) - for error in errors: - print(f" - {error}", file=sys.stderr) - return 1 - - print( - "Validated release wheels for component " - f"{args.component} at version {expected_version} from tag {args.git_tag}." - ) - return 0 - - -if __name__ == "__main__": - raise SystemExit(main()) diff --git a/ci/tools/validate_release_wheels.py b/ci/tools/validate_release_wheels.py new file mode 100644 index 00000000000..558eea256ac --- /dev/null +++ b/ci/tools/validate_release_wheels.py @@ -0,0 +1,280 @@ +#!/usr/bin/env python3 + +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# +# SPDX-License-Identifier: Apache-2.0 + +"""Validate downloaded release wheels against the requested release tag.""" + +from __future__ import annotations + +import argparse +import json +import sys +from dataclasses import dataclass +from pathlib import Path +from typing import Mapping + +import yaml +from packaging.tags import Tag +from packaging.utils import InvalidWheelFilename, parse_wheel_filename + +from .check_release_notes import COMPONENTS, parse_version_from_tag + +_BINARY_DISTRIBUTIONS = frozenset({"cuda_bindings", "cuda_core"}) +_VERSIONS_CONFIG = Path("ci/versions.yml") +_CI_WORKFLOW = Path(".github/workflows/ci.yml") + + +@dataclass(frozen=True, order=True) +class WheelTarget: + interpreter: str + abi: str + platform: str + + def __str__(self) -> str: + return f"{self.interpreter}-{self.abi}-{self.platform}" + + +def parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser( + description=( + "Validate that wheel versions match the release tag. " + "This rejects dev/local wheel versions for release uploads." + ) + ) + parser.add_argument("git_tag", help="Release git tag (for example: v13.0.0)") + parser.add_argument("component", choices=[*sorted(COMPONENTS), "all"]) + parser.add_argument("wheel_dir", help="Directory containing wheel files") + parser.add_argument( + "--bindings-package", + default="", + help="normalized CUDA bindings package JSON from the release resolver", + ) + parser.add_argument( + "--release-source-root", + type=Path, + help="tagged source tree whose CI build matrix produced the wheels", + ) + return parser.parse_args() + + +def version_from_tag( + tag: str, + component: str, + bindings_package: Mapping[str, object] | None = None, +) -> str: + versions = { + version + for tag_component in (COMPONENTS if component == "all" else (component,)) + if ( + version := parse_version_from_tag( + tag, + tag_component, + bindings_package if tag_component == "cuda-bindings" else None, + ) + ) + is not None + } + if len(versions) == 1: + return versions.pop() + raise ValueError( + "Unsupported git tag format " + f"{tag!r} for component {component!r}; expected vX.Y.Z[.postN], " + "cuda-core-vX.Y.Z[.postN], or cuda-pathfinder-vX.Y.Z[.postN]." + ) + + +def _release_python_versions(release_source_root: Path) -> list[str]: + path = release_source_root / _VERSIONS_CONFIG + config = yaml.safe_load(path.read_text(encoding="utf-8")) + if "python" in config or "schema_version" in config: + return config["python"]["supported"] + # Retained CUDA 13 tags predate the shared Python-version list. + workflow = release_source_root / ".github/workflows/build-wheel.yml" + return yaml.safe_load(workflow.read_text(encoding="utf-8"))["jobs"]["build"]["strategy"]["matrix"]["python-version"] + + +def _release_platforms(release_source_root: Path) -> list[str]: + path = release_source_root / _CI_WORKFLOW + jobs = yaml.safe_load(path.read_text(encoding="utf-8"))["jobs"] + + platforms: list[str] = [] + for value in jobs.values(): + if value.get("uses") != "./.github/workflows/build-wheel.yml": + continue + platform = value["with"]["host-platform"] + if "${{" not in platform: + platforms.append(platform) + else: + platforms.extend(value["strategy"]["matrix"]["host-platform"]) + + if not platforms: + raise ValueError(f"could not find any build-wheel host platforms in {path}") + return platforms + + +def _python_target(version: str) -> tuple[str, str]: + free_threaded = version.endswith("t") + digits = version.removesuffix("t").replace(".", "") + if not digits.isdecimal(): + raise ValueError(f"unsupported Python build-matrix version: {version!r}") + interpreter = f"cp{digits}" + return interpreter, f"{interpreter}t" if free_threaded else interpreter + + +def _platform_target(platform: str) -> str: + targets = { + "linux-64": "manylinux-x86_64", + "linux-aarch64": "manylinux-aarch64", + "win-64": "win_amd64", + "win-arm64": "win_arm64", + } + try: + return targets[platform] + except KeyError as error: + raise ValueError(f"unsupported release build platform: {platform!r}") from error + + +def expected_binary_targets( + release_source_root: Path, + bindings_package: Mapping[str, object] | None, +) -> set[WheelTarget]: + python_versions = _release_python_versions(release_source_root) + platforms = _release_platforms(release_source_root) + + if "win-arm64" in platforms: + toolkit_version = None if bindings_package is None else bindings_package.get("toolkit_version") + if not isinstance(toolkit_version, str): + raise ValueError("resolved CUDA bindings package must supply toolkit_version for matrix validation") + try: + toolkit_major, toolkit_minor = (int(part) for part in toolkit_version.split(".", maxsplit=2)[:2]) + except ValueError as error: + raise ValueError(f"invalid resolved toolkit_version: {toolkit_version!r}") from error + if (toolkit_major, toolkit_minor) < (13, 4): + platforms.remove("win-arm64") + + targets: set[WheelTarget] = set() + for version in python_versions: + interpreter, abi = _python_target(version) + for platform in platforms: + if platform == "win-arm64" and version == "3.10": + continue + targets.add(WheelTarget(interpreter, abi, _platform_target(platform))) + return targets + + +def _normalized_platform(platform: str) -> str: + if platform.startswith("manylinux") and platform.endswith("_x86_64"): + return "manylinux-x86_64" + if platform.startswith("manylinux") and platform.endswith("_aarch64"): + return "manylinux-aarch64" + return platform + + +def _wheel_target(tags: frozenset[Tag], wheel_name: str) -> WheelTarget: + targets = {WheelTarget(tag.interpreter, tag.abi, _normalized_platform(tag.platform)) for tag in tags} + if len(targets) != 1: + raise ValueError(f"{wheel_name}: expected one wheel target, found {len(targets)}") + return targets.pop() + + +def main() -> int: + args = parse_args() + try: + bindings_package = json.loads(args.bindings_package) if args.bindings_package else None + if bindings_package is not None and not isinstance(bindings_package, dict): + raise ValueError("resolved CUDA bindings package must be a JSON object") + expected_version = version_from_tag(args.git_tag, args.component, bindings_package) + expected_targets = { + distribution: ( + expected_binary_targets(args.release_source_root, bindings_package) + if distribution in _BINARY_DISTRIBUTIONS and args.release_source_root is not None + else {WheelTarget("py3", "none", "any")} + ) + for distribution in ( + {component.replace("-", "_") for component in COMPONENTS} + if args.component == "all" + else {args.component.replace("-", "_")} + ) + } + binary_distributions = set(expected_targets) & _BINARY_DISTRIBUTIONS + if binary_distributions and args.release_source_root is None: + raise ValueError("--release-source-root is required to validate binary wheel matrices") + except (json.JSONDecodeError, ValueError) as exc: + print(f"Error: {exc}", file=sys.stderr) + return 1 + + expected_distributions = set(expected_targets) + wheel_dir = Path(args.wheel_dir) + + wheels = sorted(wheel_dir.glob("*.whl")) + if not wheels: + print(f"Error: No wheel files found in {wheel_dir}", file=sys.stderr) + return 1 + + seen_targets: dict[str, set[WheelTarget]] = {distribution: set() for distribution in expected_distributions} + errors: list[str] = [] + + for wheel in wheels: + try: + parsed_distribution, version, build, tags = parse_wheel_filename(wheel.name) + distribution = str(parsed_distribution).replace("-", "_") + target = _wheel_target(tags, wheel.name) + except (InvalidWheelFilename, ValueError) as exc: + errors.append(f"Invalid wheel filename {wheel.name!r}: {exc}") + continue + + if distribution not in expected_distributions: + errors.append( + f"{wheel.name}: unexpected distribution {distribution!r} for component " + f"{args.component!r}; expected one of: " + ", ".join(sorted(expected_distributions)) + ) + continue + + if build: + errors.append(f"{wheel.name}: wheel build tags are not expected for a release") + + if target in seen_targets[distribution]: + errors.append(f"{wheel.name}: duplicate wheel target {target} for {distribution}") + seen_targets[distribution].add(target) + + if version.is_devrelease or version.local is not None: + errors.append( + f"{wheel.name}: wheel version {str(version)!r} contains dev/local markers " + "(.dev or +), which is not allowed for release uploads." + ) + + if str(version) != expected_version: + errors.append( + f"{wheel.name}: wheel version {str(version)!r} does not match expected " + f"release version {expected_version!r} from git tag {args.git_tag!r}." + ) + + missing_distributions = sorted(distribution for distribution, targets in seen_targets.items() if not targets) + if missing_distributions: + errors.append("Missing expected component wheels in download set: " + ", ".join(missing_distributions)) + + for distribution, expected in sorted(expected_targets.items()): + missing = sorted(expected - seen_targets[distribution]) + unexpected = sorted(seen_targets[distribution] - expected) + if missing: + errors.append(f"Missing expected {distribution} wheel targets: " + ", ".join(map(str, missing))) + if unexpected: + errors.append(f"Unexpected {distribution} wheel targets: " + ", ".join(map(str, unexpected))) + + if errors: + print("Wheel validation failed:", file=sys.stderr) + for error in errors: + print(f" - {error}", file=sys.stderr) + return 1 + + print( + "Validated release wheels for component " + f"{args.component} at version {expected_version} from tag {args.git_tag}." + ) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/cuda_bindings_13/docs/build_docs.sh b/cuda_bindings_13/docs/build_docs.sh index 199ababce60..53d0e14d0ea 100755 --- a/cuda_bindings_13/docs/build_docs.sh +++ b/cuda_bindings_13/docs/build_docs.sh @@ -16,13 +16,12 @@ fi # SPHINX_CUDA_BINDINGS_VER is used to create a subdir under build/html # (the Makefile file for sphinx-build also honors it if defined). -# If there's a post release (ex: .post1) we don't want it to show up in the -# version selector or directory structure. +# Post releases reuse their base release directory, while prerelease and +# development releases remain distinct so they cannot overwrite stable docs. if [[ -z "${SPHINX_CUDA_BINDINGS_VER}" ]]; then export SPHINX_CUDA_BINDINGS_VER=$(python -c "from importlib.metadata import version; \ - ver = '.'.join(str(version('cuda-bindings')).split('.')[:3]); \ - print(ver)" \ - | awk -F'+' '{print $1}') + ver = str(version('cuda-bindings')).split('+', 1)[0]; \ + print(ver if '.dev' in ver else ver.split('.post', 1)[0])") fi if [[ "${LATEST_ONLY}" == "1" && -z "${BUILD_PREVIEW:-}" && -z "${BUILD_LATEST:-}" ]]; then diff --git a/cuda_bindings_13/pixi.lock b/cuda_bindings_13/pixi.lock index 127ea67e004..8215ccf81db 100644 --- a/cuda_bindings_13/pixi.lock +++ b/cuda_bindings_13/pixi.lock @@ -273,8 +273,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.16.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wayland-protocols-1.49-hd8ed1ab_0.conda - - conda_source: cuda-bindings[6c9e4564] @ . - - conda_source: cuda-pathfinder[9b57eb00] @ ../cuda_pathfinder + - conda_source: cuda-bindings[8784abeb] @ . + - conda_source: cuda-pathfinder[1065009d] @ ../cuda_pathfinder - pypi: ../cuda_python_test_helpers linux-aarch64: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-20_gnu.conda @@ -517,8 +517,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.5.0-pyh5ded981_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.16.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda - - conda_source: cuda-bindings[e3183a23] @ . - - conda_source: cuda-pathfinder[a51836e4] @ ../cuda_pathfinder + - conda_source: cuda-bindings[bcb684b4] @ . + - conda_source: cuda-pathfinder[81b61b10] @ ../cuda_pathfinder - pypi: ../cuda_python_test_helpers win-64: - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.10.19-h4c7d964_0.conda @@ -680,8 +680,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/zlib-1.3.2-hfd05255_3.conda - conda: https://conda.anaconda.org/conda-forge/win-64/zlib-ng-2.3.3-h0261ad2_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.7-h534d264_7.conda - - conda_source: cuda-bindings[8a8ae161] @ . - - conda_source: cuda-pathfinder[f6abc7c0] @ ../cuda_pathfinder + - conda_source: cuda-bindings[33efffaf] @ . + - conda_source: cuda-pathfinder[06f93f27] @ ../cuda_pathfinder - pypi: ../cuda_python_test_helpers cu13: channels: @@ -939,8 +939,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.16.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wayland-protocols-1.49-hd8ed1ab_0.conda - - conda_source: cuda-bindings[a363e215] @ . - - conda_source: cuda-pathfinder[9b57eb00] @ ../cuda_pathfinder + - conda_source: cuda-bindings[134a05d1] @ . + - conda_source: cuda-pathfinder[1065009d] @ ../cuda_pathfinder - pypi: ../cuda_python_test_helpers linux-aarch64: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-20_gnu.conda @@ -1183,8 +1183,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.5.0-pyh5ded981_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.16.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda - - conda_source: cuda-bindings[de0b57e4] @ . - - conda_source: cuda-pathfinder[a51836e4] @ ../cuda_pathfinder + - conda_source: cuda-bindings[6746efef] @ . + - conda_source: cuda-pathfinder[81b61b10] @ ../cuda_pathfinder - pypi: ../cuda_python_test_helpers win-64: - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.10.19-h4c7d964_0.conda @@ -1346,8 +1346,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/zlib-1.3.2-hfd05255_3.conda - conda: https://conda.anaconda.org/conda-forge/win-64/zlib-ng-2.3.3-h0261ad2_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.7-h534d264_7.conda - - conda_source: cuda-bindings[9de6602e] @ . - - conda_source: cuda-pathfinder[f6abc7c0] @ ../cuda_pathfinder + - conda_source: cuda-bindings[99a4b917] @ . + - conda_source: cuda-pathfinder[06f93f27] @ ../cuda_pathfinder - pypi: ../cuda_python_test_helpers default: channels: @@ -1605,8 +1605,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.16.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wayland-protocols-1.49-hd8ed1ab_0.conda - - conda_source: cuda-bindings[a363e215] @ . - - conda_source: cuda-pathfinder[9b57eb00] @ ../cuda_pathfinder + - conda_source: cuda-bindings[134a05d1] @ . + - conda_source: cuda-pathfinder[1065009d] @ ../cuda_pathfinder - pypi: ../cuda_python_test_helpers linux-aarch64: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-20_gnu.conda @@ -1849,8 +1849,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.5.0-pyh5ded981_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.16.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda - - conda_source: cuda-bindings[de0b57e4] @ . - - conda_source: cuda-pathfinder[a51836e4] @ ../cuda_pathfinder + - conda_source: cuda-bindings[6746efef] @ . + - conda_source: cuda-pathfinder[81b61b10] @ ../cuda_pathfinder - pypi: ../cuda_python_test_helpers win-64: - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.10.19-h4c7d964_0.conda @@ -2012,8 +2012,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/zlib-1.3.2-hfd05255_3.conda - conda: https://conda.anaconda.org/conda-forge/win-64/zlib-ng-2.3.3-h0261ad2_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.7-h534d264_7.conda - - conda_source: cuda-bindings[9de6602e] @ . - - conda_source: cuda-pathfinder[f6abc7c0] @ ../cuda_pathfinder + - conda_source: cuda-bindings[99a4b917] @ . + - conda_source: cuda-pathfinder[06f93f27] @ ../cuda_pathfinder - pypi: ../cuda_python_test_helpers docs: channels: @@ -2027,9 +2027,10 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.2.0-py312he9c40d5_4.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_10.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/charset-normalizer-3.5.2-h1114479_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-bindings-13.2.0-py312hf79963d_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-nvrtc-13.4.92-hd2095e1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-nvvm-13.4.92-h69a702a_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-nvvm-impl-13.4.92-hb03c661_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-nvvm-tools-13.4.92-hb03c661_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/cython-3.2.9-py312h68e6be4_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/debugpy-1.8.22-py312h80505a6_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-h7cc23a3_1.conda @@ -2101,7 +2102,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/comm-0.2.3-pyhe01879c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.12.15-py312hd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-pathfinder-1.8.3-pyhc364b38_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-nvvm-dev_linux-64-13.4.92-ha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-version-13.4-hfacf21a_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/dict2css-0.6.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/docutils-0.21.2-pyhd8ed1ab_1.conda @@ -2194,15 +2195,18 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/webencodings-0.5.1-pyhd8ed1ab_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.48.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-4.1.1-pyh5ded981_0.conda + - conda_source: cuda-bindings[884be7d5] @ . + - conda_source: cuda-pathfinder[224d4d31] @ ../cuda_pathfinder - pypi: https://files.pythonhosted.org/packages/8c/79/017fab2f7167a9a9795665f894d04f77aafceca80821b51589bb4b23ff5c/nvidia_sphinx_theme-0.0.9.post1-py3-none-any.whl linux-aarch64: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-20_gnu.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/backports.zstd-1.7.0-py312h22d1088_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/brotli-python-1.2.0-py312h41c1d46_4.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h4777abc_10.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-bindings-13.2.0-py312hdc0efb6_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-nvrtc-13.4.92-hae6cbe8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-nvvm-13.4.92-he9431aa_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-nvvm-impl-13.4.92-hbe86820_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-nvvm-tools-13.4.92-hbe86820_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cython-3.2.9-py312hbda70bc_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/debugpy-1.8.22-py312ha0853ce_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/keyutils-1.6.3-h5bc82ec_1.conda @@ -2276,7 +2280,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/comm-0.2.3-pyhe01879c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.12.15-py312hd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-pathfinder-1.8.3-pyhc364b38_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-nvvm-dev_linux-aarch64-13.4.92-h579c4fd_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-version-13.4-hfacf21a_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/dict2css-0.6.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/docutils-0.21.2-pyhd8ed1ab_1.conda @@ -2369,6 +2373,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/webencodings-0.5.1-pyhd8ed1ab_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.48.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-4.1.1-pyh5ded981_0.conda + - conda_source: cuda-bindings[f3b12d4f] @ . + - conda_source: cuda-pathfinder[4653f308] @ ../cuda_pathfinder - pypi: https://files.pythonhosted.org/packages/8c/79/017fab2f7167a9a9795665f894d04f77aafceca80821b51589bb4b23ff5c/nvidia_sphinx_theme-0.0.9.post1-py3-none-any.whl win-64: - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_3.conda @@ -2388,7 +2394,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/comm-0.2.3-pyhe01879c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.12.15-py312hd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-pathfinder-1.8.3-pyhc364b38_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-nvvm-dev_win-64-13.4.92-h57928b3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-version-13.4-hfacf21a_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/dict2css-0.6.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/docutils-0.21.2-pyhd8ed1ab_1.conda @@ -2485,9 +2491,10 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/brotli-python-1.2.0-py312ha763cb9_4.conda - conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_10.conda - conda: https://conda.anaconda.org/conda-forge/win-64/charset-normalizer-3.5.2-h308a848_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/cuda-bindings-13.2.0-py312hc128f0a_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/cuda-nvrtc-13.4.92-hac47afa_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cuda-nvvm-13.4.92-h719f0c7_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/cuda-nvvm-impl-13.4.92-hfd05255_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cuda-nvvm-tools-13.4.92-hfd05255_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/cython-3.2.9-py312hd245ac3_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/debugpy-1.8.22-py312ha1a9051_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/icu-78.3-h5112557_2.conda @@ -2538,6 +2545,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/yaml-0.2.5-h6a83c73_3.conda - conda: https://conda.anaconda.org/conda-forge/win-64/zeromq-4.3.5-h3a581c9_12.conda - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.7-h534d264_7.conda + - conda_source: cuda-bindings[96493b48] @ . + - conda_source: cuda-pathfinder[1083a6c1] @ ../cuda_pathfinder - pypi: https://files.pythonhosted.org/packages/8c/79/017fab2f7167a9a9795665f894d04f77aafceca80821b51589bb4b23ff5c/nvidia_sphinx_theme-0.0.9.post1-py3-none-any.whl packages: - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda @@ -2614,6 +2623,18 @@ packages: run_exports: {} size: 3713752 timestamp: 1784214522814 +- conda: https://conda.anaconda.org/conda-forge/linux-64/binutils_impl_linux-64-2.46.1-default_hfdba357_103.conda + sha256: 98f9ddc6dc5d56a824b7eaea5bab6ad4bb47642288fc70d6b1b4024ac39d5595 + md5: e86f9dc615d7533c5be8b15b3a1dee8d + depends: + - ld_impl_linux-64 2.46.1 default_hbd61a6d_103 + - sysroot_linux-64 + - zstd >=1.5.7,<1.6.0a0 + license: GPL-3.0-only + license_family: GPL + run_exports: {} + size: 3706604 + timestamp: 1791565481839 - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils_linux-64-2.46.1-default_h4852527_102.conda sha256: 08d7238663fc408ba2ab60b02fa3d06a7ca9d872962e03e90c7e0fdecb7ed1d0 md5: 32fd07abe84eb14f17c7f5cc6fa8df82 @@ -2624,6 +2645,16 @@ packages: run_exports: {} size: 36337 timestamp: 1784214551894 +- conda: https://conda.anaconda.org/conda-forge/linux-64/binutils_linux-64-2.46.1-default_h4852527_103.conda + sha256: 606a42c754752fb905fe2012d52ff370d47b5b6adefd5f7befc4ec30ce758f23 + md5: ca26f0a4f8d04fd83147af557fbd932c + depends: + - binutils_impl_linux-64 2.46.1 default_hfdba357_103 + license: GPL-3.0-only + license_family: GPL + run_exports: {} + size: 36335 + timestamp: 1791565508736 - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-1.2.0-h505cf86_4.conda sha256: 61b78574f002390b6a7fc79834fc344beaab09550068a51100eea5a485dac741 md5: 746aa619a1bcaf4da541101179d7c60e @@ -2764,31 +2795,6 @@ packages: run_exports: {} size: 331601 timestamp: 1789746783338 -- conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-bindings-13.2.0-py312hf79963d_1.conda - sha256: 749c0e2e664f76833a24a7a4d970a643888ca582fba1c46ca1b7c01b245dc99d - md5: 13d8b143b3513c95a1d3aec4e65a9529 - depends: - - __glibc >=2.17,<3.0.a0 - - cuda-nvrtc >=13,<14.0a0 - - cuda-nvvm-impl >=13,<14.0a0 - - cuda-pathfinder >=1.1.0,<2 - - cuda-version >=13,<14.0a0 - - libcufile >=1,<2.0a0 - - libgcc >=14 - - libnvfatbin - - libnvjitlink >=13.0,<14.0a0 - - libstdcxx >=14 - - python >=3.12,<3.13.0a0 - - python_abi 3.12.* *_cp312 - constrains: - - cuda-python >=13.2.0,<13.3.0a0 - - cuda-cudart >=13,<14.0a0 - license: LicenseRef-NVIDIA-SOFTWARE-LICENSE - purls: - - pkg:pypi/cuda-bindings?source=hash-mapping - run_exports: {} - size: 4143685 - timestamp: 1779249651391 - conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-cudart-12.9.79-h5888daf_0.conda sha256: 57d1294ecfaf9dc8cdb5fc4be3e63ebc7614538bddb5de53cfd9b1b7de43aed5 md5: cb15315d19b58bd9cd424084e58ad081 @@ -2817,6 +2823,19 @@ packages: run_exports: {} size: 24234 timestamp: 1789613674738 +- conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-cudart-13.4.92-hd2095e1_1.conda + sha256: 2672a4c726ae152cbd011533a3092f601f03314073ba65874d34ceb6b51a2d61 + md5: 3042de847b53d8a818d5be7380f2b3d0 + depends: + - __glibc >=2.17,<3.0.a0 + - cuda-cudart_linux-64 13.4.92 h9e77f9f_1 + - cuda-version >=13.4,<13.5.0a0 + - libgcc >=15 + - libstdcxx >=15 + license: LicenseRef-NVIDIA-End-User-License-Agreement + run_exports: {} + size: 24261 + timestamp: 1791918060137 - conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-cudart-dev-12.9.79-h5888daf_0.conda sha256: 04d8235cb3cb3510c0492c3515a9d1a6053b50ef39be42b60cafb05044b5f4c6 md5: ba38a7c3b4c14625de45784b773f0c71 @@ -2853,6 +2872,23 @@ packages: - cuda-cudart >=13.4.92,<14.0a0 size: 24719 timestamp: 1789613691099 +- conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-cudart-dev-13.4.92-hd2095e1_1.conda + sha256: 66c42f44f3ed0c3a5808e8b01c58878fc6f320b63d7bdc446a965556888dba0d + md5: 456e334d56cfae38659da009f8dcdb15 + depends: + - __glibc >=2.17,<3.0.a0 + - cuda-cudart 13.4.92 hd2095e1_1 + - cuda-cudart-dev_linux-64 13.4.92 h9e77f9f_1 + - cuda-cudart-static 13.4.92 hd2095e1_1 + - cuda-version >=13.4,<13.5.0a0 + - libgcc >=15 + - libstdcxx >=15 + license: LicenseRef-NVIDIA-End-User-License-Agreement + run_exports: + weak: + - cuda-cudart >=13.4.92,<14.0a0 + size: 24799 + timestamp: 1791918074095 - conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-cudart-static-12.9.79-h5888daf_0.conda sha256: 6261e1d9af80e1ec308e3e5e2ff825d189ef922d24093beaf6efca12e67ce060 md5: d3c4ac48f4967f09dd910d9c15d40c81 @@ -2881,6 +2917,19 @@ packages: run_exports: {} size: 24203 timestamp: 1789613683675 +- conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-cudart-static-13.4.92-hd2095e1_1.conda + sha256: c9733c366e0bf39aba805e4a1af73864ee1c8aa32636d78649ab5ed15a702a3e + md5: 0cbec9120f1ba047ff3fe4af49fcea2b + depends: + - __glibc >=2.17,<3.0.a0 + - cuda-cudart-static_linux-64 13.4.92 h9e77f9f_1 + - cuda-version >=13.4,<13.5.0a0 + - libgcc >=15 + - libstdcxx >=15 + license: LicenseRef-NVIDIA-End-User-License-Agreement + run_exports: {} + size: 24189 + timestamp: 1791918068720 - conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-nvrtc-12.9.86-hecca717_1.conda sha256: 68f81268c25befa9b70dc49af469ab0eb131960e3700b9a4edb46a32da343a28 md5: 53f0062e2243b26e43ddac0b5267c6a3 @@ -2907,6 +2956,18 @@ packages: run_exports: {} size: 40891762 timestamp: 1789606732241 +- conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-nvrtc-13.4.92-hd2095e1_1.conda + sha256: 57319804ae25e7912180761325ca7ae016c8d6b2e4bc8435ae32545ecc744d6d + md5: f851f3ec1da56007ac2a527c9c47bb75 + depends: + - __glibc >=2.17,<3.0.a0 + - cuda-version >=13.4,<13.5.0a0 + - libgcc >=15 + - libstdcxx >=15 + license: LicenseRef-NVIDIA-End-User-License-Agreement + run_exports: {} + size: 40861730 + timestamp: 1791919218242 - conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-nvrtc-dev-12.9.86-hecca717_1.conda sha256: ae620051c16eabf7720a47c5115634d64f7703d32124555ad0afccfd4b8d7cf4 md5: 0d28090f4e63410e20397c7975612837 @@ -2941,6 +3002,23 @@ packages: - cuda-nvrtc >=13.4.92,<14.0a0 size: 39261 timestamp: 1789606830146 +- conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-nvrtc-dev-13.4.92-hd2095e1_1.conda + sha256: 219e74a39c7cf28ece1812a464b9678ee03493a137f725846321d7558607b72b + md5: 4afc933b4cd0164a27a95996037e6142 + depends: + - __glibc >=2.17,<3.0.a0 + - cuda-nvrtc 13.4.92 hd2095e1_1 + - cuda-version >=13.4,<13.5.0a0 + - libgcc >=15 + - libstdcxx >=15 + constrains: + - cuda-nvrtc-static >=13.4.92 + license: LicenseRef-NVIDIA-End-User-License-Agreement + run_exports: + weak: + - cuda-nvrtc >=13.4.92,<14.0a0 + size: 39135 + timestamp: 1791919341732 - conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-nvvm-12.9.86-h69a702a_6.conda sha256: 5c70d91e6d30eb6000ea036558a20fd0b1bc13cdd2c04fd5dbf94d9caa0a7fbc md5: 704956f67e44ddf046565ead01f9efcd @@ -2965,6 +3043,18 @@ packages: run_exports: {} size: 26192 timestamp: 1789628110041 +- conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-nvvm-13.4.92-h69a702a_1.conda + sha256: b56e84b0c5ff2a24bbcf80e10adf670060b18297a4768c377ad5141a6994816c + md5: 333d434b7590b7da177f92c195816127 + depends: + - cuda-nvvm-dev_linux-64 13.4.92.* + - cuda-nvvm-impl 13.4.92.* + - cuda-nvvm-tools 13.4.92.* + license: LicenseRef-NVIDIA-End-User-License-Agreement + purls: [] + run_exports: {} + size: 26278 + timestamp: 1792180995966 - conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-nvvm-impl-12.9.86-h4bc722e_2.conda sha256: f4d34556174e4faa9d374ba2244707082870e1bbc1bb441ad3d9d2cea37da6af md5: 82125dd3c0c4aa009faa00e2829b93d8 @@ -5005,6 +5095,17 @@ packages: run_exports: {} size: 572864 timestamp: 1790777898360 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libsystemd0-262.1-h26e0ef7_0.conda + sha256: fc930c169a0844dcb1f3084032d3f4e53798b2f48d4c7f4a151a87012833008a + md5: a6bb6ea85431d21bebdf7184517524ca + depends: + - __glibc >=2.17,<3.0.a0 + - libcap >=2.78,<2.79.0a0 + - libgcc >=15 + license: LGPL-2.1-or-later + run_exports: {} + size: 574718 + timestamp: 1792224216335 - conda: https://conda.anaconda.org/conda-forge/linux-64/libtiff-4.7.2-hcc2c06a_1.conda sha256: 10e125da82ca93e09191e66e5a94d566b2cf8d4024e2a0db3a9114297447e0d9 md5: 0907d876f460ebc941ae590338b6102f @@ -5038,6 +5139,17 @@ packages: run_exports: {} size: 184629 timestamp: 1790777902394 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libudev1-262.1-h26e0ef7_0.conda + sha256: 63bc48418ed3be6166c27f294504153bf3da8579aa5d565ae4fee8bdd1682e54 + md5: b7e3531ad0f828ee27f5731fcb9ebdc3 + depends: + - __glibc >=2.17,<3.0.a0 + - libcap >=2.78,<2.79.0a0 + - libgcc >=15 + license: LGPL-2.1-or-later + run_exports: {} + size: 184945 + timestamp: 1792224219990 - conda: https://conda.anaconda.org/conda-forge/linux-64/libunwind-1.8.3-h65a8314_0.conda sha256: 71c8b9d5c72473752a0bb6e91b01dd209a03916cb71f36cc6a564e3a2a132d7a md5: e179a69edd30d75c0144d7a380b88f28 @@ -5820,38 +5932,6 @@ packages: size: 26698311 timestamp: 1793015162391 python_site_packages_path: lib/python3.14/site-packages -- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.15.2-h6e52b48_100_cp315.conda - build_number: 100 - sha256: dd6fdef748df5636029673a834ca3632ce44c86d71e4986d70bcdb2ae5607a25 - md5: 38c3edc23439db3ca383be02ae2b702e - depends: - - __glibc >=2.17,<3.0.a0 - - bzip2 >=1.0.8,<2.0a0 - - ld_impl_linux-64 >=2.36.1 - - libedit >=3.1.20260512,<3.2.0a0 - - libexpat >=2.8.5,<3.0a0 - - libffi >=3.7.0,<3.8.0a0 - - libgcc >=15 - - liblzma >=5.8.3,<6.0a0 - - libmpdec >=4.0.0,<5.0a0 - - libsqlite >=3.54.1,<4.0a0 - - libuuid >=2.42.4,<3.0a0 - - libzlib >=1.3.2,<2.0a0 - - ncurses >=6.6,<7.0a0 - - openssl >=3.5.9,<4.0a0 - - python_abi 3.15.* *_cp315 - - tk >=8.6.13,<8.7.0a0 - - tzdata - - zstd >=1.5.7,<1.6.0a0 - license: Python-2.0 - run_exports: - weak: - - python_abi 3.15.* *_cp315 - noarch: - - python - size: 29327137 - timestamp: 1793015518763 - python_site_packages_path: lib/python3.15/site-packages - conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py312h8a5da7c_1.conda sha256: cb142bfd92f6e55749365ddc244294fa7b64db6d08c45b018ff1c658907bfcbf md5: 15878599a87992e44c059731771591cb @@ -6833,6 +6913,18 @@ packages: run_exports: {} size: 4677171 timestamp: 1784214549910 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/binutils_impl_linux-aarch64-2.46.1-default_h5f4c503_103.conda + sha256: 1827893f9d6aa13794196b1820b8003bfff0105774a323a61026a16cec6dc66d + md5: 1ebaa45e5556156b3c7bf5bd5c527634 + depends: + - ld_impl_linux-aarch64 2.46.1 default_h1979696_103 + - sysroot_linux-aarch64 + - zstd >=1.5.7,<1.6.0a0 + license: GPL-3.0-only + license_family: GPL + run_exports: {} + size: 4911258 + timestamp: 1791565579362 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/binutils_linux-aarch64-2.46.1-default_hf1166c9_102.conda sha256: d41099a3fe2809a3ab3e4c718ecff4d5f8879e7949f3c8e8efa97fa06a90248c md5: 9a340123cb7217eae51c5cae24484631 @@ -6843,6 +6935,16 @@ packages: run_exports: {} size: 36196 timestamp: 1784214578949 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/binutils_linux-aarch64-2.46.1-default_hf1166c9_103.conda + sha256: 60e63ac488aac474f8a22ea465d317daa02fccd039cca75e288bd0fc37e8745a + md5: 9074b4a634a2be79ee49cd85b54a7f34 + depends: + - binutils_impl_linux-aarch64 2.46.1 default_h5f4c503_103 + license: GPL-3.0-only + license_family: GPL + run_exports: {} + size: 36474 + timestamp: 1791565619784 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/brotli-1.2.0-h52fc18c_4.conda sha256: 73cccc8488da976cbdf32e3b5c6182aef6d77c9dfabd0e5f5fa2ca6e03d51921 md5: 207d4f45f94f6d755a7fe1455e3148d7 @@ -6960,31 +7062,6 @@ packages: run_exports: {} size: 350096 timestamp: 1789746782725 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-bindings-13.2.0-py312hdc0efb6_1.conda - sha256: b8784c43ccd7c61c3944b48e7751e454e8c4b9ae50cabf42696e432b2e5b6b3b - md5: c7560ec15413c9b14e46d26c2ce94fb3 - depends: - - cuda-nvrtc >=13,<14.0a0 - - cuda-nvvm-impl >=13,<14.0a0 - - cuda-pathfinder >=1.1.0,<2 - - cuda-version >=13,<14.0a0 - - libcufile >=1,<2.0a0 - - libgcc >=14 - - libnvfatbin - - libnvjitlink >=13.0,<14.0a0 - - libstdcxx >=14 - - python >=3.12,<3.13.0a0 - - python >=3.12,<3.13.0a0 *_cpython - - python_abi 3.12.* *_cp312 - constrains: - - cuda-python >=13.2.0,<13.3.0a0 - - cuda-cudart >=13,<14.0a0 - license: LicenseRef-NVIDIA-SOFTWARE-LICENSE - purls: - - pkg:pypi/cuda-bindings?source=hash-mapping - run_exports: {} - size: 3866781 - timestamp: 1779249873318 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-cudart-12.9.79-h3ae8b8a_0.conda sha256: 3d6699fc27ffabf28a9d359b48e7b88437e4d945844718a58608627998db5d1b md5: df78e19e5fe656631d1470aa0fcf6ced @@ -7013,6 +7090,19 @@ packages: run_exports: {} size: 24420 timestamp: 1789613707699 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-cudart-13.4.92-hae6cbe8_1.conda + sha256: 770b6d73c8f2b20eddd8e670079b93245d58fb613c6a377bc612be221c41c3de + md5: b104d84fca7f8253c40aa5120906e050 + depends: + - arm-variant * sbsa + - cuda-cudart_linux-aarch64 13.4.92 hae6cbe8_1 + - cuda-version >=13.4,<13.5.0a0 + - libgcc >=15 + - libstdcxx >=15 + license: LicenseRef-NVIDIA-End-User-License-Agreement + run_exports: {} + size: 24455 + timestamp: 1791918095186 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-cudart-dev-12.9.79-h3ae8b8a_0.conda sha256: d70f85411992e03494f2fe94a9852d79f366a92f40ba791611eda5551044afe9 md5: d58cc487273764a11637456c06399ff0 @@ -7049,6 +7139,23 @@ packages: - cuda-cudart >=13.4.92,<14.0a0 size: 24906 timestamp: 1789613723829 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-cudart-dev-13.4.92-hae6cbe8_1.conda + sha256: 77beb9c91a07a21147541d229c8fce9b69513e8e0c1049bbdfb0c1c36d837533 + md5: 259c69ef83a5920548a789672ac479c7 + depends: + - arm-variant * sbsa + - cuda-cudart 13.4.92 hae6cbe8_1 + - cuda-cudart-dev_linux-aarch64 13.4.92 hae6cbe8_1 + - cuda-cudart-static 13.4.92 hae6cbe8_1 + - cuda-version >=13.4,<13.5.0a0 + - libgcc >=15 + - libstdcxx >=15 + license: LicenseRef-NVIDIA-End-User-License-Agreement + run_exports: + weak: + - cuda-cudart >=13.4.92,<14.0a0 + size: 24850 + timestamp: 1791918109321 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-cudart-static-12.9.79-h3ae8b8a_0.conda sha256: dac33edcebbf557563a41521f67961039186efbc276903d937b32243ef3be937 md5: 365adcddf99b81eb323698fda31d507c @@ -7077,6 +7184,19 @@ packages: run_exports: {} size: 24336 timestamp: 1789613715481 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-cudart-static-13.4.92-hae6cbe8_1.conda + sha256: d40d5ba6da848b01c1595cda45505651069c98669fde4725b8c4eb87d66b50e3 + md5: c02b4368963fd077341a2f3f48563400 + depends: + - arm-variant * sbsa + - cuda-cudart-static_linux-aarch64 13.4.92 hae6cbe8_1 + - cuda-version >=13.4,<13.5.0a0 + - libgcc >=15 + - libstdcxx >=15 + license: LicenseRef-NVIDIA-End-User-License-Agreement + run_exports: {} + size: 24414 + timestamp: 1791918102674 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-nvrtc-12.9.86-h8f3c8d4_1.conda sha256: e7f8d835d7bf993dcad9fba6db5af89c35b2b4f0282799b729bf6ad2c3bd896d md5: 48187c09673a42f9930764e8170b8787 @@ -7103,6 +7223,18 @@ packages: run_exports: {} size: 39026820 timestamp: 1789606765991 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-nvrtc-13.4.92-hae6cbe8_1.conda + sha256: c43853c59e2b6894489aae23a552e313e37687b3aca709e9d5f8ddb10b8e3554 + md5: d79160de33f2098808a6069a885b72ac + depends: + - arm-variant * sbsa + - cuda-version >=13.4,<13.5.0a0 + - libgcc >=15 + - libstdcxx >=15 + license: LicenseRef-NVIDIA-End-User-License-Agreement + run_exports: {} + size: 39027767 + timestamp: 1791919196421 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-nvrtc-dev-12.9.86-h8f3c8d4_1.conda sha256: b1d1a74cbbdcf46c4ee737279df3220eb7a29393999bc96b3c1398f7de78c912 md5: 2346ee558cbfb7b857c8353ffc2553fa @@ -7139,6 +7271,24 @@ packages: - cuda-nvrtc >=13.4.92,<14.0a0 size: 39133 timestamp: 1789606900425 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-nvrtc-dev-13.4.92-hae6cbe8_1.conda + sha256: 6eb1b25932421a1f2448088e41ae99cd0707b9745f2c85d0c0e4c1469da96f38 + md5: c796f4e54351b72c9ebd277e2b30d97c + depends: + - arm-variant * sbsa + - cuda-nvrtc 13.4.92 hae6cbe8_1 + - cuda-version >=13.4,<13.5.0a0 + - libgcc >=15 + - libstdcxx >=15 + constrains: + - arm-variant * sbsa + - cuda-nvrtc-static >=13.4.92 + license: LicenseRef-NVIDIA-End-User-License-Agreement + run_exports: + weak: + - cuda-nvrtc >=13.4.92,<14.0a0 + size: 39155 + timestamp: 1791919300033 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-nvvm-12.9.86-he9431aa_106.conda sha256: 97bf1688e3847090d1c4193c39ca575a67e2183d0c20ddf8bcedc0f9d9528bbc md5: 8ace2a8121a5f733a902822290aae11c @@ -7163,6 +7313,18 @@ packages: run_exports: {} size: 26203 timestamp: 1789628130654 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-nvvm-13.4.92-he9431aa_1.conda + sha256: b835df7c790cc0d60be31a870348173dca3ef6d73c7c8d8a679fa062ab7b8764 + md5: 0d49e36b65fd93fcfcba7614ed92dafb + depends: + - cuda-nvvm-dev_linux-aarch64 13.4.92.* + - cuda-nvvm-impl 13.4.92.* + - cuda-nvvm-tools 13.4.92.* + license: LicenseRef-NVIDIA-End-User-License-Agreement + purls: [] + run_exports: {} + size: 26382 + timestamp: 1792181032938 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-nvvm-impl-12.9.86-h7b14b0b_2.conda sha256: 100accfc6f608004ddef4b9004ee5179eddbac19e7d5c4c7bd5e6e8b71bd7c5d md5: 8e9fceb7b677be7107cc9c20f8d71d86 @@ -9035,6 +9197,16 @@ packages: run_exports: {} size: 592152 timestamp: 1790777808830 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsystemd0-262.1-hd1ea486_0.conda + sha256: aea93da32087cc4e1f46bd0596f487ad92e1dbab282dec0d739a7f406cb42df6 + md5: 5f1e0ce7fe60051e614f505b00055cb9 + depends: + - libcap >=2.78,<2.79.0a0 + - libgcc >=15 + license: LGPL-2.1-or-later + run_exports: {} + size: 593299 + timestamp: 1792224110959 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libtiff-4.7.2-h45f9f85_1.conda sha256: fa6daf2301dee912def3e74344fae792a8fc2bbbf7880dedee0e93ee8fb98fc5 md5: c6f35f8f9695623b9055341bc280a642 @@ -9066,6 +9238,16 @@ packages: run_exports: {} size: 195674 timestamp: 1790777812289 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libudev1-262.1-hd1ea486_0.conda + sha256: ed708af321e72984beb4cbf2c9127b6d0a0b2e484d4cca670f0ae02ceee76a83 + md5: 7d5081ffee4a31823c3af8dc2cb1cf24 + depends: + - libcap >=2.78,<2.79.0a0 + - libgcc >=15 + license: LGPL-2.1-or-later + run_exports: {} + size: 196616 + timestamp: 1792224114009 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libunwind-1.8.3-h6470e1d_0.conda sha256: 86c013d522975b76e16a74341bfcb22f6ec2e9b8b87ec3e15380f46c435eaa7b md5: 5d8191a950e492a06dc29b491dd5f7c5 @@ -9739,37 +9921,6 @@ packages: size: 25620130 timestamp: 1793015285925 python_site_packages_path: lib/python3.14/site-packages -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.15.2-h0c7c799_100_cp315.conda - build_number: 100 - sha256: 788a8c701af3fb86e7e7d8f40335804959e796c705b7b7e9a409de2eea8ded18 - md5: 9874b7ceebe929da370eddcc23314fa3 - depends: - - bzip2 >=1.0.8,<2.0a0 - - ld_impl_linux-aarch64 >=2.36.1 - - libedit >=3.1.20260512,<3.2.0a0 - - libexpat >=2.8.5,<3.0a0 - - libffi >=3.7.0,<3.8.0a0 - - libgcc >=15 - - liblzma >=5.8.3,<6.0a0 - - libmpdec >=4.0.0,<5.0a0 - - libsqlite >=3.54.1,<4.0a0 - - libuuid >=2.42.4,<3.0a0 - - libzlib >=1.3.2,<2.0a0 - - ncurses >=6.6,<7.0a0 - - openssl >=3.5.9,<4.0a0 - - python_abi 3.15.* *_cp315 - - tk >=8.6.13,<8.7.0a0 - - tzdata - - zstd >=1.5.7,<1.6.0a0 - license: Python-2.0 - run_exports: - weak: - - python_abi 3.15.* *_cp315 - noarch: - - python - size: 27765007 - timestamp: 1793015442708 - python_site_packages_path: lib/python3.15/site-packages - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pyyaml-6.0.3-py312ha4530ae_1.conda sha256: 0ba02720b470150a8c6261a86ea4db01dcf121e16a3e3978a84e965d3fe9c39a md5: 47018c13dbb26186b577fd8bd1823a44 @@ -10802,6 +10953,24 @@ packages: run_exports: {} size: 131396 timestamp: 1792483552251 +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.10.23-h4c7d964_0.conda + sha256: f1d280d2618de987204102090e83733089c092dc2dd45686fd3dcbe809034f6a + md5: ea9dc39dcd2815202749c1e5bc2a8973 + depends: + - __win + license: ISC + run_exports: {} + size: 130423 + timestamp: 1792772460189 +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.10.23-hbd8a1cb_0.conda + sha256: 95619b9c1184be7175392eeb0ee7eeb5ccf25d280951f4225f2d62e725790be3 + md5: 3fd02989038a1e1cee627c14c2d73f29 + depends: + - __unix + license: ISC + run_exports: {} + size: 130057 + timestamp: 1792772446739 - conda: https://conda.anaconda.org/conda-forge/noarch/cachecontrol-0.14.4-pyha770c72_0.conda sha256: cca3a26282a5bc37a10afb1aa2006a21c45033cbc4ff012f9501f56f2a115c12 md5: 13bdbb9b693b29134c56a9a00c23de41 @@ -11045,6 +11214,20 @@ packages: - cuda-cudart >=13.4.92,<14.0a0 size: 416061 timestamp: 1789613678504 +- conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cudart-dev_linux-64-13.4.92-h9e77f9f_1.conda + sha256: b57e47ceaa7a3ddfc578f03c1856cd02008f95bf633332a8e53bf9287a8702c7 + md5: 5f9ffe3ad903033e93e98d78f16378be + depends: + - cuda-cccl_linux-64 + - cuda-cudart-static_linux-64 + - cuda-cudart_linux-64 + - cuda-version >=13.4,<13.5.0a0 + license: LicenseRef-NVIDIA-End-User-License-Agreement + run_exports: + weak: + - cuda-cudart >=13.4.92,<14.0a0 + size: 414750 + timestamp: 1791918064480 - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cudart-dev_linux-aarch64-12.9.79-h3ae8b8a_0.conda sha256: ad64a1ecfc933172dbc6407d71b1abb78dc7ffcd5cc871baee238350307a7c0c md5: 60e07c05a51d5549bec1e7ee38849feb @@ -11077,6 +11260,21 @@ packages: - cuda-cudart >=13.4.92,<14.0a0 size: 415739 timestamp: 1789613711959 +- conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cudart-dev_linux-aarch64-13.4.92-hae6cbe8_1.conda + sha256: 12ec82791e888381c91313d665ecc46df601341636e9b058cf3cabb03c5f6096 + md5: 36d5fad84dbeb187005f085d9daeb8c4 + depends: + - arm-variant * sbsa + - cuda-cccl_linux-aarch64 + - cuda-cudart-static_linux-aarch64 + - cuda-cudart_linux-aarch64 + - cuda-version >=13.4,<13.5.0a0 + license: LicenseRef-NVIDIA-End-User-License-Agreement + run_exports: + weak: + - cuda-cudart >=13.4.92,<14.0a0 + size: 414595 + timestamp: 1791918098639 - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cudart-dev_win-64-12.9.79-he0c23c2_0.conda sha256: e022d36a333420130faf6473c49f8dab54bf976cf320577ffb06db0a0797b734 md5: 3c3e2f6b5455783fd332a072d632ea78 @@ -11105,8 +11303,20 @@ packages: run_exports: {} size: 1668588 timestamp: 1789613696484 -- conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cudart-static_linux-64-12.9.79-h3f2d84a_0.conda - sha256: d435f8a19b59b52ce460ee3a6bfd877288a0d1d645119a6ba60f1c3627dc5032 +- conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cudart-dev_win-64-13.4.92-hac47afa_1.conda + sha256: 5fe763d0bfd19a7c122cae5eee218f7a8276763417b7116250bcfd161f9f7595 + md5: cbc8db11f210a9af642c8a82fc3d0efa + depends: + - cuda-cccl_win-64 + - cuda-cudart-static_win-64 + - cuda-cudart_win-64 + - cuda-version >=13.4,<13.5.0a0 + license: LicenseRef-NVIDIA-End-User-License-Agreement + run_exports: {} + size: 1672429 + timestamp: 1791918060378 +- conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cudart-static_linux-64-12.9.79-h3f2d84a_0.conda + sha256: d435f8a19b59b52ce460ee3a6bfd877288a0d1d645119a6ba60f1c3627dc5032 md5: b87bf315d81218dd63eb46cc1eaef775 depends: - cuda-version >=12.9,<12.10.0a0 @@ -11125,6 +11335,15 @@ packages: run_exports: {} size: 1249118 timestamp: 1789613660480 +- conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cudart-static_linux-64-13.4.92-h9e77f9f_1.conda + sha256: e51d1a571b02b1a427d16e2dc0c135a682900007e26d9d717e79bab0c58e4571 + md5: e6bd43601eb40f4330a934dc77f7d62c + depends: + - cuda-version >=13.4,<13.5.0a0 + license: LicenseRef-NVIDIA-End-User-License-Agreement + run_exports: {} + size: 1244417 + timestamp: 1791918050319 - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cudart-static_linux-aarch64-12.9.79-h3ae8b8a_0.conda sha256: d4be038bad9abf0eac1e88dc57c8db6a469db8eb5d7c281085dfbb018ef84212 md5: 52498fedeb43bbd4c45f84a0fb722d21 @@ -11147,6 +11366,16 @@ packages: run_exports: {} size: 1245773 timestamp: 1789613695146 +- conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cudart-static_linux-aarch64-13.4.92-hae6cbe8_1.conda + sha256: 9b7dff56b77ac18628f75cccb4dc7b940ff790e65f1def546facd73ffa726f5e + md5: 148d6b955ea3e7ec16d3e0e46de5c8f1 + depends: + - arm-variant * sbsa + - cuda-version >=13.4,<13.5.0a0 + license: LicenseRef-NVIDIA-End-User-License-Agreement + run_exports: {} + size: 1242539 + timestamp: 1791918083843 - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cudart-static_win-64-12.9.79-he0c23c2_0.conda sha256: 6a3410cd7ce07955cb705801055ef129ebee1cd6390c6fe9e5f607b67c3dba36 md5: 0dd152a1493d90356037604a865f050f @@ -11167,6 +11396,15 @@ packages: run_exports: {} size: 82544 timestamp: 1789613678949 +- conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cudart-static_win-64-13.4.92-hac47afa_1.conda + sha256: aa034a686ab953d19c462b91512ca75dc6c765fb7251357393103f7dabff9eb0 + md5: 8dd7ed65a32572fe4718ce7b6884a8cf + depends: + - cuda-version >=13.4,<13.5.0a0 + license: LicenseRef-NVIDIA-End-User-License-Agreement + run_exports: {} + size: 82491 + timestamp: 1791918049017 - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cudart_linux-64-12.9.79-h3f2d84a_0.conda sha256: 6cde0ace2b995b49d0db2eefb7bc30bf00ffc06bb98ef7113632dec8f8907475 md5: 64508631775fbbf9eca83c84b1df0cae @@ -11187,6 +11425,15 @@ packages: run_exports: {} size: 209905 timestamp: 1789613664868 +- conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cudart_linux-64-13.4.92-h9e77f9f_1.conda + sha256: 33ff49906d42aa43847fd9b7fb139c064df3eb40dd10c85e0a84d224658d0bfc + md5: 49b13a38cd090122c59c10c77fd2a566 + depends: + - cuda-version >=13.4,<13.5.0a0 + license: LicenseRef-NVIDIA-End-User-License-Agreement + run_exports: {} + size: 209978 + timestamp: 1791918053765 - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cudart_linux-aarch64-12.9.79-h3ae8b8a_0.conda sha256: 4900ff2f000a4f8a70a7bc8576469640aa6590618fa9e73c84e066e025dcb760 md5: cc2459ad427431e089d78d760cf24437 @@ -11209,6 +11456,16 @@ packages: run_exports: {} size: 223916 timestamp: 1789613700405 +- conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cudart_linux-aarch64-13.4.92-hae6cbe8_1.conda + sha256: d8057012693e22e398b1089652545a338e3d577ca90f090da5bb2c62f7d72d02 + md5: 2e93fd552844f60e9fbe9d2c287be7d2 + depends: + - arm-variant * sbsa + - cuda-version >=13.4,<13.5.0a0 + license: LicenseRef-NVIDIA-End-User-License-Agreement + run_exports: {} + size: 223994 + timestamp: 1791918088368 - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cudart_win-64-12.9.79-he0c23c2_0.conda sha256: 6a89a53cdbcfafa0bb55abee1b58492c6a9a28e688abe04f48f0d01649c5f3e4 md5: 71c9c2ab52226f990f268164381d8494 @@ -11229,6 +11486,15 @@ packages: run_exports: {} size: 24076 timestamp: 1789613682979 +- conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cudart_win-64-13.4.92-hac47afa_1.conda + sha256: 6a53afca9c5db3b75d57e446ba926b3327e261da39bd637f9b996f2e257267f9 + md5: 37a74c183777ec891017fe03c1705c3e + depends: + - cuda-version >=13.4,<13.5.0a0 + license: LicenseRef-NVIDIA-End-User-License-Agreement + run_exports: {} + size: 24041 + timestamp: 1791918051282 - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-nvvm-dev_linux-64-12.9.86-ha770c72_2.conda sha256: 522722dcaffd133e0c7500c69dc70e21ac34d6762dcbaabfe847439f944028f0 md5: 7b386291414c7eea113d25ac28a33772 @@ -11293,20 +11559,6 @@ packages: run_exports: {} size: 33726 timestamp: 1789621799731 -- conda: https://conda.anaconda.org/conda-forge/noarch/cuda-pathfinder-1.8.3-pyhc364b38_0.conda - sha256: 25b8f625cebe056be045bf9e484549188296b79793a340e059f13de4338939be - md5: cb2babe521da8b1acaaea1cc12a282af - depends: - - python >=3.10 - - cuda-version >=12.0,<14 - - python - license: Apache-2.0 - license_family: APACHE - purls: - - pkg:pypi/cuda-pathfinder?source=compressed-mapping - run_exports: {} - size: 53393 - timestamp: 1790912935126 - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-version-12.9-h4f385c5_3.conda sha256: 5f5f428031933f117ff9f7fcc650e6ea1b3fef5936cf84aa24af79167513b656 md5: b6d5d7f1c171cbd228ea06b556cfa859 @@ -11572,7 +11824,7 @@ packages: license: MIT license_family: MIT purls: - - pkg:pypi/imagesize?source=hash-mapping + - pkg:pypi/imagesize?source=compressed-mapping run_exports: {} size: 21467 timestamp: 1787649248672 @@ -13111,6 +13363,13 @@ packages: run_exports: {} size: 118849 timestamp: 1784250406640 +- conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026e-h5d301ff_0.conda + sha256: 2b7ca858879f183ce2dcc65b300f48a0133d5430550f35b23d80d405a0788dbf + md5: abccc3810d2b97e570dee487f2b46e38 + license: LicenseRef-Public-Domain + run_exports: {} + size: 119208 + timestamp: 1792758382821 - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.8.0-pyhd8ed1ab_0.conda sha256: c5511c190ab55168ca412f3c54592fbf677ae6250784cb72b227a7cf3f538f7d md5: 407a3d3778570bae8e8fcf554e803e43 @@ -13409,30 +13668,6 @@ packages: run_exports: {} size: 252875 timestamp: 1789746805191 -- conda: https://conda.anaconda.org/conda-forge/win-64/cuda-bindings-13.2.0-py312hc128f0a_1.conda - sha256: 31113f2c14b5e549aa59863f711890e9bf442defd7af3bd6ff192ec96e5dcdf1 - md5: a17fac259dd34ef9ee1f508933614967 - depends: - - cuda-nvrtc >=13,<14.0a0 - - cuda-nvvm-impl >=13,<14.0a0 - - cuda-pathfinder >=1.1.0,<2 - - cuda-version >=13,<14.0a0 - - libnvfatbin - - libnvjitlink >=13.0,<14.0a0 - - python >=3.12,<3.13.0a0 - - python_abi 3.12.* *_cp312 - - ucrt >=10.0.20348.0 - - vc >=14.3,<15 - - vc14_runtime >=14.44.35208 - constrains: - - cuda-python >=13.2.0,<13.3.0a0 - - cuda-cudart >=13,<14.0a0 - license: LicenseRef-NVIDIA-SOFTWARE-LICENSE - purls: - - pkg:pypi/cuda-bindings?source=hash-mapping - run_exports: {} - size: 3509245 - timestamp: 1779249639234 - conda: https://conda.anaconda.org/conda-forge/win-64/cuda-cudart-12.9.79-he0c23c2_0.conda sha256: a30cd9adf3a70d069d4d87c5728ec16778b77071629612ca5d8513cd92d89c09 md5: 0a243d4f000a0d2f51dd94ee9132b234 @@ -13461,6 +13696,19 @@ packages: run_exports: {} size: 215067 timestamp: 1789613690715 +- conda: https://conda.anaconda.org/conda-forge/win-64/cuda-cudart-13.4.92-hac47afa_1.conda + sha256: 8072dd05bd1913f079725fa2b0b8f3de07203a48f295dbe25be14eb98980bc37 + md5: fbaa83a80783c23d2e8309a468772075 + depends: + - cuda-cudart_win-64 13.4.92 hac47afa_1 + - cuda-version >=13.4,<13.5.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: LicenseRef-NVIDIA-End-User-License-Agreement + run_exports: {} + size: 215004 + timestamp: 1791918056787 - conda: https://conda.anaconda.org/conda-forge/win-64/cuda-cudart-dev-12.9.79-he0c23c2_0.conda sha256: 1ee68f0ffd37889f0fc438d4da7124054b124632e1c3bc15950b9851b002473e md5: e5bb074108bc2501f8374e80748aa181 @@ -13495,6 +13743,21 @@ packages: run_exports: {} size: 23884 timestamp: 1789613707493 +- conda: https://conda.anaconda.org/conda-forge/win-64/cuda-cudart-dev-13.4.92-hac47afa_1.conda + sha256: 83496a41db7ba5bcb24dd1df9577b3fa11f944c734826e02370d26b7b909e9be + md5: d445165d6611c98536982b6fd6a95ace + depends: + - cuda-cudart 13.4.92 hac47afa_1 + - cuda-cudart-dev_win-64 13.4.92 hac47afa_1 + - cuda-cudart-static 13.4.92 hac47afa_1 + - cuda-version >=13.4,<13.5.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: LicenseRef-NVIDIA-End-User-License-Agreement + run_exports: {} + size: 23941 + timestamp: 1791918067507 - conda: https://conda.anaconda.org/conda-forge/win-64/cuda-cudart-static-12.9.79-he0c23c2_0.conda sha256: 02d3ff9ec59c7f59132ffe9398746ad9422a75706e7cad19acc6c30a5c0fc763 md5: 718879691b8119c893f587f46c734fca @@ -13523,6 +13786,19 @@ packages: run_exports: {} size: 23877 timestamp: 1789613703473 +- conda: https://conda.anaconda.org/conda-forge/win-64/cuda-cudart-static-13.4.92-hac47afa_1.conda + sha256: cbd7a3ddefe3f275aef653f2ce71c0177b61a549a141f6f5af10891c218e7adb + md5: b4852e2f2c5922ef5732facd6397d915 + depends: + - cuda-cudart-static_win-64 13.4.92 hac47afa_1 + - cuda-version >=13.4,<13.5.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: LicenseRef-NVIDIA-End-User-License-Agreement + run_exports: {} + size: 23939 + timestamp: 1791918065348 - conda: https://conda.anaconda.org/conda-forge/win-64/cuda-nvrtc-12.9.86-hac47afa_1.conda sha256: d90ef446ac859db26286a5d39d39333c4e4cee31ba5042b5c7922bd25de531f6 md5: d68b5d96a53c80dc3dbbd8f7c3b8106d @@ -13549,6 +13825,18 @@ packages: run_exports: {} size: 36407421 timestamp: 1789606716374 +- conda: https://conda.anaconda.org/conda-forge/win-64/cuda-nvrtc-13.4.92-hac47afa_1.conda + sha256: bcf76878a22a140bf93c4ab77c9f2d3400e636e8478c4524b4cf1199629c247f + md5: d14681f66ecaae3949396f55e6a56a7b + depends: + - cuda-version >=13.4,<13.5.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: LicenseRef-NVIDIA-End-User-License-Agreement + run_exports: {} + size: 36407569 + timestamp: 1791919216363 - conda: https://conda.anaconda.org/conda-forge/win-64/cuda-nvrtc-dev-12.9.86-hac47afa_1.conda sha256: 1e1c41f95d606eaf6581fccf9546ed6ee4053c42b78e11057cd6d2801b96f0e2 md5: b97225dd005cb0dcdca7911c61ca38e5 @@ -13579,6 +13867,21 @@ packages: - cuda-nvrtc >=13.4.92,<14.0a0 size: 38246 timestamp: 1789607226146 +- conda: https://conda.anaconda.org/conda-forge/win-64/cuda-nvrtc-dev-13.4.92-hac47afa_1.conda + sha256: 0e913bd798aa37746c6f3874097ab2490caf83e5650eeee27d27d76622c9f90d + md5: ba6bcf634f8c95008f82a2562074c054 + depends: + - cuda-nvrtc 13.4.92 hac47afa_1 + - cuda-version >=13.4,<13.5.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: LicenseRef-NVIDIA-End-User-License-Agreement + run_exports: + weak: + - cuda-nvrtc >=13.4.92,<14.0a0 + size: 38346 + timestamp: 1791919775736 - conda: https://conda.anaconda.org/conda-forge/win-64/cuda-nvvm-12.9.86-h719f0c7_6.conda sha256: 020a5bb67a35654f391d21b170ba763f95b7f133fec5678d69e676559dcd5653 md5: b162c7fb8b19f9102bd5f801d7f58ca2 @@ -13603,6 +13906,18 @@ packages: run_exports: {} size: 26714 timestamp: 1789628111155 +- conda: https://conda.anaconda.org/conda-forge/win-64/cuda-nvvm-13.4.92-h719f0c7_1.conda + sha256: d421379e5437c91fbbc06fa8cdfb966faa6f8f96a3579dd80289dcafa89cf793 + md5: a8d53f64997c6374a91f750d89138753 + depends: + - cuda-nvvm-dev_win-64 13.4.92.* + - cuda-nvvm-impl 13.4.92.* + - cuda-nvvm-tools 13.4.92.* + license: LicenseRef-NVIDIA-End-User-License-Agreement + purls: [] + run_exports: {} + size: 26872 + timestamp: 1792181036038 - conda: https://conda.anaconda.org/conda-forge/win-64/cuda-nvvm-impl-12.9.86-h2466b09_2.conda sha256: 7b995ea653816b129bae6e4ee92898824a39fe82227472537bf75ac6ece7e955 md5: d8cea7bc32045bde718d0b1ceb595445 @@ -15295,35 +15610,6 @@ packages: size: 18780090 timestamp: 1793016249254 python_site_packages_path: Lib/site-packages -- conda: https://conda.anaconda.org/conda-forge/win-64/python-3.15.2-h53f6dd8_100_cp315.conda - build_number: 100 - sha256: 75ce979442c5a5cd4f38ced72c5060c35e3b3d4539d92d2cb8bae5e3b6043fa4 - md5: 969c2999f8e4cc1da50ec1930cc7f3a5 - depends: - - bzip2 >=1.0.8,<2.0a0 - - libexpat >=2.8.5,<3.0a0 - - libffi >=3.7.0,<3.8.0a0 - - liblzma >=5.8.3,<6.0a0 - - libmpdec >=4.0.0,<5.0a0 - - libsqlite >=3.54.1,<4.0a0 - - libzlib >=1.3.2,<2.0a0 - - openssl >=3.5.9,<4.0a0 - - python_abi 3.15.* *_cp315 - - tk >=8.6.13,<8.7.0a0 - - tzdata - - ucrt >=10.0.20348.0 - - vc >=14.3,<15 - - vc14_runtime >=14.44.35208 - - zstd >=1.5.7,<1.6.0a0 - license: Python-2.0 - run_exports: - weak: - - python_abi 3.15.* *_cp315 - noarch: - - python - size: 18579162 - timestamp: 1793015037227 - python_site_packages_path: lib/python/site-packages - conda: https://conda.anaconda.org/conda-forge/win-64/pywin32-312-py312h95189c4_2.conda sha256: 60ef47866053b10e2174eac2cc391cf80d7060ec9af1f57aa05397b5953cc4fb md5: 3e862f114987b14f1a179b6c8f2b4976 @@ -15823,29 +16109,29 @@ packages: - zstd >=1.5.7,<1.6.0a0 size: 387535 timestamp: 1786599623274 -- conda_source: cuda-bindings[6c9e4564] @ . +- conda_source: cuda-bindings[134a05d1] @ . variants: c_stdlib: sysroot c_stdlib_version: '2.28' - cuda_version: 12.* + cuda_version: 13.4.* python: 3.14.* target_platform: linux-64 depends: - - __glibc >=2.28,<3.0.a0 + - python + - python >=3.11 + - cuda-version + - cuda-pathfinder + - libnvjitlink - cuda-nvrtc - - cuda-nvrtc >=12.9.86,<13.0a0 + - cuda-nvrtc >=13.4.92,<14.0a0 - cuda-nvvm - - cuda-pathfinder - - cuda-version + - libnvfatbin - libcufile - - libcufile >=1.14.1.1,<2.0a0 + - libcufile >=1.19.1.55,<2.0a0 - libgcc >=16 - libgcc >=16 - - libnvfatbin - - libnvjitlink - libstdcxx >=16 - - python - - python >=3.11 + - __glibc >=2.28,<3.0.a0 - python_abi 3.14.* *_cp314 license: Apache-2.0 source_depends: @@ -15874,20 +16160,20 @@ packages: host_packages: - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_10.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-cudart-12.9.79-h5888daf_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-cudart-dev-12.9.79-h5888daf_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-cudart-static-12.9.79-h5888daf_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-nvrtc-12.9.86-hecca717_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-nvrtc-dev-12.9.86-hecca717_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-nvvm-12.9.86-h69a702a_6.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-nvvm-impl-12.9.86-h4bc722e_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-nvvm-tools-12.9.86-h4bc722e_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-profiler-api-12.9.79-h7938cbb_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-cudart-13.4.92-hd2095e1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-cudart-dev-13.4.92-hd2095e1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-cudart-static-13.4.92-hd2095e1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-nvrtc-13.4.92-hd2095e1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-nvrtc-dev-13.4.92-hd2095e1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-nvvm-13.4.92-h69a702a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-nvvm-impl-13.4.92-hb03c661_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-nvvm-tools-13.4.92-hb03c661_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-profiler-api-13.4.92-h7938cbb_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/cython-3.2.9-py314h1807b08_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.46.1-default_hbd61a6d_102.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libcap-2.78-h084b8d7_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libcufile-1.14.1.1-hbc026e6_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libcufile-dev-1.14.1.1-hecca717_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcufile-1.19.1.55-h63c01a6_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcufile-dev-1.19.1.55-h393e864_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.8.5-hd2095e1_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.7.0-h81df57d_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-16.2.0-ha9f2e26_7.conda @@ -15911,13 +16197,13 @@ packages: - conda: https://conda.anaconda.org/conda-forge/linux-64/uv-0.13.5-h535ca38_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_7.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.10.19-hbd8a1cb_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cccl_linux-64-12.9.27-ha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-crt-dev_linux-64-12.9.86-ha770c72_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cudart-dev_linux-64-12.9.79-h3f2d84a_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cudart-static_linux-64-12.9.79-h3f2d84a_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cudart_linux-64-12.9.79-h3f2d84a_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-nvvm-dev_linux-64-12.9.86-ha770c72_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-version-12.9-h4f385c5_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cccl_linux-64-13.3.4.3.1-ha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-crt-dev_linux-64-13.4.92-ha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cudart-dev_linux-64-13.4.92-h9e77f9f_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cudart-static_linux-64-13.4.92-h9e77f9f_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cudart_linux-64-13.4.92-h9e77f9f_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-nvvm-dev_linux-64-13.4.92-ha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-version-13.4-hfacf21a_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.3-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-9_cp314.conda - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-84.0.0-pyh332efcf_0.conda @@ -15926,8 +16212,8 @@ packages: - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.16.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/vcs_versioning-2.6.0-pyh5ded981_0.conda - - conda_source: cuda-pathfinder[9b57eb00] @ ../cuda_pathfinder -- conda_source: cuda-bindings[8a8ae161] @ . + - conda_source: cuda-pathfinder[1065009d] @ ../cuda_pathfinder +- conda_source: cuda-bindings[33efffaf] @ . variants: c_compiler: vs2022 cuda_version: 12.* @@ -15935,19 +16221,19 @@ packages: python: 3.14.* target_platform: win-64 depends: + - python + - python >=3.11 + - cuda-version + - cuda-pathfinder + - libnvjitlink - cuda-nvrtc - cuda-nvrtc >=12.9.86,<13.0a0 - cuda-nvvm - - cuda-pathfinder - - cuda-version - libnvfatbin - - libnvjitlink - - python - - python >=3.11 - - python_abi 3.14.* *_cp314 - - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - python_abi 3.14.* *_cp314 license: Apache-2.0 source_depends: cuda-pathfinder: @@ -15999,103 +16285,135 @@ packages: - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.51.36247-habf1de7_41.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vcomp14-14.51.36247-habf1de7_41.conda - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.7-h534d264_7.conda - - conda_source: cuda-pathfinder[f6abc7c0] @ ../cuda_pathfinder -- conda_source: cuda-bindings[9de6602e] @ . + - conda_source: cuda-pathfinder[06f93f27] @ ../cuda_pathfinder +- conda_source: cuda-bindings[6746efef] @ . variants: - c_compiler: vs2022 + c_stdlib: sysroot + c_stdlib_version: '2.28' cuda_version: 13.4.* - cxx_compiler: vs2022 python: 3.14.* - target_platform: win-64 + target_platform: linux-aarch64 depends: + - python + - python >=3.11 + - cuda-version + - cuda-pathfinder + - libnvjitlink - cuda-nvrtc - cuda-nvrtc >=13.4.92,<14.0a0 - cuda-nvvm - - cuda-pathfinder - - cuda-version - libnvfatbin - - libnvjitlink - - python - - python >=3.11 + - libcufile + - libcufile >=1.19.1.55,<2.0a0 + - libgcc >=16 + - libgcc >=16 + - libstdcxx >=16 + - __glibc >=2.28,<3.0.a0 - python_abi 3.14.* *_cp314 - - ucrt >=10.0.20348.0 - - vc >=14.3,<15 - - vc14_runtime >=14.44.35208 license: Apache-2.0 source_depends: cuda-pathfinder: path: ../cuda_pathfinder build_packages: - - conda: https://conda.anaconda.org/conda-forge/noarch/vswhere-3.1.7-h40126e0_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/vs2022_win-64-19.44.35207-ha74f236_41.conda - host_packages: - - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.10.19-h4c7d964_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cccl_win-64-13.3.4.3.1-h57928b3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-crt-dev_win-64-13.4.92-h57928b3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cudart-dev_win-64-13.4.92-hac47afa_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cudart-static_win-64-13.4.92-hac47afa_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cudart_win-64-13.4.92-hac47afa_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-nvvm-dev_win-64-13.4.92-h57928b3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-version-13.4-hfacf21a_3.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.3-pyhc364b38_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-9_cp314.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-84.0.0-pyh332efcf_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-scm-10.3.4-pyh5ded981_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.5.0-pyh5ded981_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.16.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-20_gnu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/binutils_impl_linux-aarch64-2.46.1-default_h5f4c503_102.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/binutils_linux-aarch64-2.46.1-default_hf1166c9_102.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gcc_impl_linux-aarch64-16.2.0-h5425ead_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gcc_linux-aarch64-16.2.0-h25cc031_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gxx_impl_linux-aarch64-16.2.0-h1e3c31f_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gxx_linux-aarch64-16.2.0-h423111d_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.46.1-default_h1979696_102.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-16.2.0-h205dda4_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-16.2.0-h8acb6b2_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsanitizer-16.2.0-h73cac2c_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-16.2.0-hef695bb_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.3.2-hdc9db2a_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.7-h9d15635_7.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-aarch64-4.18.0-h05a177a_9.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_linux-aarch64-16.2.0-hc0c2482_107.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/libstdcxx-devel_linux-aarch64-16.2.0-h082e5f6_107.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-aarch64-2.28-h585391f_9.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda + host_packages: + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-20_gnu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h4777abc_10.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-cudart-13.4.92-hae6cbe8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-cudart-dev-13.4.92-hae6cbe8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-cudart-static-13.4.92-hae6cbe8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-nvrtc-13.4.92-hae6cbe8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-nvrtc-dev-13.4.92-hae6cbe8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-nvvm-13.4.92-he9431aa_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-nvvm-impl-13.4.92-hbe86820_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-nvvm-tools-13.4.92-hbe86820_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-profiler-api-13.4.92-h16bee8c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cython-3.2.9-py314hc6b4731_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.46.1-default_h1979696_102.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcap-2.78-hfcc8634_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcufile-1.19.1.55-hc7dfe37_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcufile-dev-1.19.1.55-hc1d3098_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.8.5-h4154aff_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.7.0-hdaad0be_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-16.2.0-h205dda4_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-16.2.0-h8acb6b2_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblzma-5.8.3-he30d5cf_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libmpdec-4.0.0-he30d5cf_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libnl-3.11.0-he30d5cf_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libpython-3.14.10-h150030a_100_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.54.1-hd26f1b6_101.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-16.2.0-hef695bb_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsystemd0-262-hd1ea486_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libudev1-262-hd1ea486_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.42.4-hd6fdeab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.3.2-hdc9db2a_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.6-h2b6f883_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.5-he6ad1d5_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.14.10-hbec3b18_100_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rdma-core-65.0-h807d763_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.3-ha7194a6_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-noxft_hf03c496_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/uv-0.13.5-h779c035_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.7-h9d15635_7.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/arm-variant-1.2.0-sbsa.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.10.19-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cccl_linux-aarch64-13.3.4.3.1-h579c4fd_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-crt-dev_linux-aarch64-13.4.92-h579c4fd_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cudart-dev_linux-aarch64-13.4.92-hae6cbe8_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cudart-static_linux-aarch64-13.4.92-hae6cbe8_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cudart_linux-aarch64-13.4.92-hae6cbe8_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-nvvm-dev_linux-aarch64-13.4.92-h579c4fd_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-version-13.4-hfacf21a_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.3-pyhc364b38_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-9_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-84.0.0-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-scm-10.3.4-pyh5ded981_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.5.0-pyh5ded981_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.16.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/vcs_versioning-2.6.0-pyh5ded981_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_10.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/cuda-cudart-13.4.92-hac47afa_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/cuda-cudart-dev-13.4.92-hac47afa_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/cuda-cudart-static-13.4.92-hac47afa_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/cuda-nvrtc-13.4.92-hac47afa_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/cuda-nvrtc-dev-13.4.92-hac47afa_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/cuda-nvvm-13.4.92-h719f0c7_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/cuda-nvvm-impl-13.4.92-hfd05255_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/cuda-nvvm-tools-13.4.92-hfd05255_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/cuda-profiler-api-13.4.92-h57928b3_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/cython-3.2.9-py314h344ed54_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.8.5-hac47afa_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libffi-3.7.0-h3d046cb_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/liblzma-5.8.3-hfd05255_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libmpdec-4.0.0-hfd05255_2.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libpython-3.14.10-hc6187dd_100_cp314.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.54.1-hf5d6505_101.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.3.2-hfd05255_3.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.6.5-hf411b9b_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.14.10-h53f6dd8_100_cp314.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h967ab96_4.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/uv-0.13.5-hf7a7c96_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.5-ha367084_41.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.51.36247-habf1de7_41.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/vcomp14-14.51.36247-habf1de7_41.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.7-h534d264_7.conda - - conda_source: cuda-pathfinder[f6abc7c0] @ ../cuda_pathfinder -- conda_source: cuda-bindings[a363e215] @ . + - conda_source: cuda-pathfinder[81b61b10] @ ../cuda_pathfinder +- conda_source: cuda-bindings[8784abeb] @ . variants: c_stdlib: sysroot c_stdlib_version: '2.28' - cuda_version: 13.4.* + cuda_version: 12.* python: 3.14.* target_platform: linux-64 depends: - - __glibc >=2.28,<3.0.a0 + - python + - python >=3.11 + - cuda-version + - cuda-pathfinder + - libnvjitlink - cuda-nvrtc - - cuda-nvrtc >=13.4.92,<14.0a0 + - cuda-nvrtc >=12.9.86,<13.0a0 - cuda-nvvm - - cuda-pathfinder - - cuda-version + - libnvfatbin - libcufile - - libcufile >=1.19.1.55,<2.0a0 + - libcufile >=1.14.1.1,<2.0a0 - libgcc >=16 - libgcc >=16 - - libnvfatbin - - libnvjitlink - libstdcxx >=16 - - python - - python >=3.11 + - __glibc >=2.28,<3.0.a0 - python_abi 3.14.* *_cp314 license: Apache-2.0 source_depends: @@ -16124,20 +16442,20 @@ packages: host_packages: - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_10.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-cudart-13.4.92-hd2095e1_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-cudart-dev-13.4.92-hd2095e1_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-cudart-static-13.4.92-hd2095e1_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-nvrtc-13.4.92-hd2095e1_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-nvrtc-dev-13.4.92-hd2095e1_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-nvvm-13.4.92-h69a702a_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-nvvm-impl-13.4.92-hb03c661_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-nvvm-tools-13.4.92-hb03c661_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-profiler-api-13.4.92-h7938cbb_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-cudart-12.9.79-h5888daf_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-cudart-dev-12.9.79-h5888daf_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-cudart-static-12.9.79-h5888daf_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-nvrtc-12.9.86-hecca717_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-nvrtc-dev-12.9.86-hecca717_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-nvvm-12.9.86-h69a702a_6.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-nvvm-impl-12.9.86-h4bc722e_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-nvvm-tools-12.9.86-h4bc722e_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-profiler-api-12.9.79-h7938cbb_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/cython-3.2.9-py314h1807b08_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.46.1-default_hbd61a6d_102.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libcap-2.78-h084b8d7_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libcufile-1.19.1.55-h63c01a6_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libcufile-dev-1.19.1.55-h393e864_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcufile-1.14.1.1-hbc026e6_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcufile-dev-1.14.1.1-hecca717_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.8.5-hd2095e1_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.7.0-h81df57d_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-16.2.0-ha9f2e26_7.conda @@ -16161,13 +16479,13 @@ packages: - conda: https://conda.anaconda.org/conda-forge/linux-64/uv-0.13.5-h535ca38_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_7.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.10.19-hbd8a1cb_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cccl_linux-64-13.3.4.3.1-ha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-crt-dev_linux-64-13.4.92-ha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cudart-dev_linux-64-13.4.92-h9e77f9f_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cudart-static_linux-64-13.4.92-h9e77f9f_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cudart_linux-64-13.4.92-h9e77f9f_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-nvvm-dev_linux-64-13.4.92-ha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-version-13.4-hfacf21a_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cccl_linux-64-12.9.27-ha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-crt-dev_linux-64-12.9.86-ha770c72_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cudart-dev_linux-64-12.9.79-h3f2d84a_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cudart-static_linux-64-12.9.79-h3f2d84a_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cudart_linux-64-12.9.79-h3f2d84a_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-nvvm-dev_linux-64-12.9.86-ha770c72_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-version-12.9-h4f385c5_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.3-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-9_cp314.conda - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-84.0.0-pyh332efcf_0.conda @@ -16176,30 +16494,280 @@ packages: - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.16.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/vcs_versioning-2.6.0-pyh5ded981_0.conda - - conda_source: cuda-pathfinder[9b57eb00] @ ../cuda_pathfinder -- conda_source: cuda-bindings[de0b57e4] @ . + - conda_source: cuda-pathfinder[1065009d] @ ../cuda_pathfinder +- conda_source: cuda-bindings[884be7d5] @ . variants: c_stdlib: sysroot c_stdlib_version: '2.28' cuda_version: 13.4.* - python: 3.14.* - target_platform: linux-aarch64 + python: 3.12.* + target_platform: linux-64 depends: - - __glibc >=2.28,<3.0.a0 + - python + - python >=3.11 + - cuda-version + - cuda-pathfinder + - libnvjitlink - cuda-nvrtc - cuda-nvrtc >=13.4.92,<14.0a0 - cuda-nvvm - - cuda-pathfinder - - cuda-version + - libnvfatbin - libcufile - libcufile >=1.19.1.55,<2.0a0 - libgcc >=16 - libgcc >=16 + - libstdcxx >=16 + - __glibc >=2.28,<3.0.a0 + - python_abi 3.12.* *_cp312 + license: Apache-2.0 + source_depends: + cuda-pathfinder: + path: ../cuda_pathfinder + build_packages: + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils_impl_linux-64-2.46.1-default_hfdba357_103.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils_linux-64-2.46.1-default_h4852527_103.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_impl_linux-64-16.2.0-h9891192_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_linux-64-16.2.0-h0ab548f_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gxx_impl_linux-64-16.2.0-h0d273dc_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gxx_linux-64-16.2.0-h23aca61_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.46.1-default_hbd61a6d_103.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-16.2.0-ha9f2e26_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-16.2.0-he0feb66_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsanitizer-16.2.0-h3048135_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-16.2.0-h934c35e_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_7.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-64-4.18.0-he073ed8_9.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_linux-64-16.2.0-he3ce08f_107.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/libstdcxx-devel_linux-64-16.2.0-h86e191b_107.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-64-2.28-h4ee821c_9.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026e-h5d301ff_0.conda + host_packages: + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_10.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-cudart-13.4.92-hd2095e1_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-cudart-dev-13.4.92-hd2095e1_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-cudart-static-13.4.92-hd2095e1_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-nvrtc-13.4.92-hd2095e1_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-nvrtc-dev-13.4.92-hd2095e1_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-nvvm-13.4.92-h69a702a_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-nvvm-impl-13.4.92-hb03c661_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-nvvm-tools-13.4.92-hb03c661_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cuda-profiler-api-13.4.92-h7938cbb_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cython-3.2.9-py312h68e6be4_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.46.1-default_hbd61a6d_103.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcap-2.78-h084b8d7_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcufile-1.19.1.55-h63c01a6_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcufile-dev-1.19.1.55-h393e864_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.8.5-hd2095e1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.7.0-h81df57d_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-16.2.0-ha9f2e26_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-16.2.0-he0feb66_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-hb03c661_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libnl-3.11.0-hb03c661_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hb9d3cd8_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libpython-3.12.16-ha57cdbe_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.54.1-h0737f62_100.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-16.2.0-h934c35e_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsystemd0-262.1-h26e0ef7_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libudev1-262.1-h26e0ef7_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42.4-hcfc3c73_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.38-h280c20c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.5-h781a0a9_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.16-h5f976f7_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/rdma-core-65.0-h7b4f2e6_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-hd6e31c0_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h1df4ec4_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/uv-0.13.5-h535ca38_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_7.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.10.23-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cccl_linux-64-13.3.4.3.1-ha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-crt-dev_linux-64-13.4.92-ha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cudart-dev_linux-64-13.4.92-h9e77f9f_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cudart-static_linux-64-13.4.92-h9e77f9f_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cudart_linux-64-13.4.92-h9e77f9f_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-nvvm-dev_linux-64-13.4.92-ha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-version-13.4-hfacf21a_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.3-pyhc364b38_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-9_cp312.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-84.2.1-pyhe730653_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-scm-10.3.4-pyh5ded981_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.5.0-pyh5ded981_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.16.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026e-h5d301ff_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/vcs_versioning-2.6.0-pyh5ded981_0.conda + - conda_source: cuda-pathfinder[224d4d31] @ ../cuda_pathfinder +- conda_source: cuda-bindings[96493b48] @ . + variants: + c_compiler: vs2022 + cuda_version: 13.4.* + cxx_compiler: vs2022 + python: 3.12.* + target_platform: win-64 + depends: + - python + - python >=3.11 + - cuda-version + - cuda-pathfinder + - libnvjitlink + - cuda-nvrtc + - cuda-nvrtc >=13.4.92,<14.0a0 + - cuda-nvvm - libnvfatbin + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - python_abi 3.12.* *_cp312 + license: Apache-2.0 + source_depends: + cuda-pathfinder: + path: ../cuda_pathfinder + build_packages: + - conda: https://conda.anaconda.org/conda-forge/noarch/vswhere-3.1.7-h40126e0_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vs2022_win-64-19.44.35207-ha74f236_41.conda + host_packages: + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.10.23-h4c7d964_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cccl_win-64-13.3.4.3.1-h57928b3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-crt-dev_win-64-13.4.92-h57928b3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cudart-dev_win-64-13.4.92-hac47afa_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cudart-static_win-64-13.4.92-hac47afa_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cudart_win-64-13.4.92-hac47afa_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-nvvm-dev_win-64-13.4.92-h57928b3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-version-13.4-hfacf21a_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.3-pyhc364b38_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-9_cp312.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-84.2.1-pyhe730653_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-scm-10.3.4-pyh5ded981_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.5.0-pyh5ded981_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.16.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026e-h5d301ff_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/vcs_versioning-2.6.0-pyh5ded981_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_10.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cuda-cudart-13.4.92-hac47afa_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cuda-cudart-dev-13.4.92-hac47afa_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cuda-cudart-static-13.4.92-hac47afa_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cuda-nvrtc-13.4.92-hac47afa_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cuda-nvrtc-dev-13.4.92-hac47afa_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cuda-nvvm-13.4.92-h719f0c7_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cuda-nvvm-impl-13.4.92-hfd05255_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cuda-nvvm-tools-13.4.92-hfd05255_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cuda-profiler-api-13.4.92-h57928b3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cython-3.2.9-py312hd245ac3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.8.5-hac47afa_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libffi-3.7.0-h3d046cb_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/liblzma-5.8.3-hfd05255_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libpython-3.12.16-hfb4101e_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.54.1-hf5d6505_100.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.3.2-hfd05255_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.6.5-hf411b9b_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.12.16-hb12b558_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h967ab96_4.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/uv-0.13.5-hf7a7c96_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.5-ha367084_41.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.51.36247-habf1de7_41.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vcomp14-14.51.36247-habf1de7_41.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.7-h534d264_7.conda + - conda_source: cuda-pathfinder[1083a6c1] @ ../cuda_pathfinder +- conda_source: cuda-bindings[99a4b917] @ . + variants: + c_compiler: vs2022 + cuda_version: 13.4.* + cxx_compiler: vs2022 + python: 3.14.* + target_platform: win-64 + depends: + - python + - python >=3.11 + - cuda-version + - cuda-pathfinder - libnvjitlink - - libstdcxx >=16 + - cuda-nvrtc + - cuda-nvrtc >=13.4.92,<14.0a0 + - cuda-nvvm + - libnvfatbin + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - python_abi 3.14.* *_cp314 + license: Apache-2.0 + source_depends: + cuda-pathfinder: + path: ../cuda_pathfinder + build_packages: + - conda: https://conda.anaconda.org/conda-forge/noarch/vswhere-3.1.7-h40126e0_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vs2022_win-64-19.44.35207-ha74f236_41.conda + host_packages: + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.10.19-h4c7d964_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cccl_win-64-13.3.4.3.1-h57928b3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-crt-dev_win-64-13.4.92-h57928b3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cudart-dev_win-64-13.4.92-hac47afa_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cudart-static_win-64-13.4.92-hac47afa_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cudart_win-64-13.4.92-hac47afa_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-nvvm-dev_win-64-13.4.92-h57928b3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-version-13.4-hfacf21a_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.3-pyhc364b38_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-9_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-84.0.0-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-scm-10.3.4-pyh5ded981_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.5.0-pyh5ded981_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.16.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/vcs_versioning-2.6.0-pyh5ded981_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_10.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cuda-cudart-13.4.92-hac47afa_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cuda-cudart-dev-13.4.92-hac47afa_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cuda-cudart-static-13.4.92-hac47afa_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cuda-nvrtc-13.4.92-hac47afa_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cuda-nvrtc-dev-13.4.92-hac47afa_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cuda-nvvm-13.4.92-h719f0c7_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cuda-nvvm-impl-13.4.92-hfd05255_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cuda-nvvm-tools-13.4.92-hfd05255_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cuda-profiler-api-13.4.92-h57928b3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cython-3.2.9-py314h344ed54_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.8.5-hac47afa_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libffi-3.7.0-h3d046cb_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/liblzma-5.8.3-hfd05255_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libmpdec-4.0.0-hfd05255_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libpython-3.14.10-hc6187dd_100_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.54.1-hf5d6505_101.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.3.2-hfd05255_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.6.5-hf411b9b_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.14.10-h53f6dd8_100_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h967ab96_4.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/uv-0.13.5-hf7a7c96_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.5-ha367084_41.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.51.36247-habf1de7_41.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vcomp14-14.51.36247-habf1de7_41.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.7-h534d264_7.conda + - conda_source: cuda-pathfinder[06f93f27] @ ../cuda_pathfinder +- conda_source: cuda-bindings[bcb684b4] @ . + variants: + c_stdlib: sysroot + c_stdlib_version: '2.28' + cuda_version: 12.* + python: 3.14.* + target_platform: linux-aarch64 + depends: - python - python >=3.11 + - cuda-version + - cuda-pathfinder + - libnvjitlink + - cuda-nvrtc + - cuda-nvrtc >=12.9.86,<13.0a0 + - cuda-nvvm + - libnvfatbin + - libcufile + - libcufile >=1.14.1.1,<2.0a0 + - libgcc >=16 + - libgcc >=16 + - libstdcxx >=16 + - __glibc >=2.28,<3.0.a0 - python_abi 3.14.* *_cp314 license: Apache-2.0 source_depends: @@ -16228,20 +16796,20 @@ packages: host_packages: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-20_gnu.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h4777abc_10.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-cudart-13.4.92-hae6cbe8_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-cudart-dev-13.4.92-hae6cbe8_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-cudart-static-13.4.92-hae6cbe8_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-nvrtc-13.4.92-hae6cbe8_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-nvrtc-dev-13.4.92-hae6cbe8_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-nvvm-13.4.92-he9431aa_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-nvvm-impl-13.4.92-hbe86820_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-nvvm-tools-13.4.92-hbe86820_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-profiler-api-13.4.92-h16bee8c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-cudart-12.9.79-h3ae8b8a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-cudart-dev-12.9.79-h3ae8b8a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-cudart-static-12.9.79-h3ae8b8a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-nvrtc-12.9.86-h8f3c8d4_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-nvrtc-dev-12.9.86-h8f3c8d4_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-nvvm-12.9.86-he9431aa_106.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-nvvm-impl-12.9.86-h7b14b0b_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-nvvm-tools-12.9.86-h7b14b0b_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-profiler-api-12.9.79-h16bee8c_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cython-3.2.9-py314hc6b4731_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.46.1-default_h1979696_102.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcap-2.78-hfcc8634_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcufile-1.19.1.55-hc7dfe37_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcufile-dev-1.19.1.55-hc1d3098_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcufile-1.14.1.1-had8bf56_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcufile-dev-1.14.1.1-he38c790_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.8.5-h4154aff_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.7.0-hdaad0be_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-16.2.0-h205dda4_7.conda @@ -16266,13 +16834,13 @@ packages: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.7-h9d15635_7.conda - conda: https://conda.anaconda.org/conda-forge/noarch/arm-variant-1.2.0-sbsa.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.10.19-hbd8a1cb_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cccl_linux-aarch64-13.3.4.3.1-h579c4fd_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-crt-dev_linux-aarch64-13.4.92-h579c4fd_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cudart-dev_linux-aarch64-13.4.92-hae6cbe8_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cudart-static_linux-aarch64-13.4.92-hae6cbe8_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cudart_linux-aarch64-13.4.92-hae6cbe8_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-nvvm-dev_linux-aarch64-13.4.92-h579c4fd_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-version-13.4-hfacf21a_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cccl_linux-aarch64-12.9.27-h579c4fd_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-crt-dev_linux-aarch64-12.9.86-h579c4fd_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cudart-dev_linux-aarch64-12.9.79-h3ae8b8a_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cudart-static_linux-aarch64-12.9.79-h3ae8b8a_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cudart_linux-aarch64-12.9.79-h3ae8b8a_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-nvvm-dev_linux-aarch64-12.9.86-h579c4fd_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-version-12.9-h4f385c5_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.3-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-9_cp314.conda - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-84.0.0-pyh332efcf_0.conda @@ -16281,44 +16849,44 @@ packages: - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.16.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/vcs_versioning-2.6.0-pyh5ded981_0.conda - - conda_source: cuda-pathfinder[a51836e4] @ ../cuda_pathfinder -- conda_source: cuda-bindings[e3183a23] @ . + - conda_source: cuda-pathfinder[81b61b10] @ ../cuda_pathfinder +- conda_source: cuda-bindings[f3b12d4f] @ . variants: c_stdlib: sysroot c_stdlib_version: '2.28' - cuda_version: 12.* - python: 3.14.* + cuda_version: 13.4.* + python: 3.12.* target_platform: linux-aarch64 depends: - - __glibc >=2.28,<3.0.a0 + - python + - python >=3.11 + - cuda-version + - cuda-pathfinder + - libnvjitlink - cuda-nvrtc - - cuda-nvrtc >=12.9.86,<13.0a0 + - cuda-nvrtc >=13.4.92,<14.0a0 - cuda-nvvm - - cuda-pathfinder - - cuda-version + - libnvfatbin - libcufile - - libcufile >=1.14.1.1,<2.0a0 + - libcufile >=1.19.1.55,<2.0a0 - libgcc >=16 - libgcc >=16 - - libnvfatbin - - libnvjitlink - libstdcxx >=16 - - python - - python >=3.11 - - python_abi 3.14.* *_cp314 + - __glibc >=2.28,<3.0.a0 + - python_abi 3.12.* *_cp312 license: Apache-2.0 source_depends: cuda-pathfinder: path: ../cuda_pathfinder build_packages: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-20_gnu.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/binutils_impl_linux-aarch64-2.46.1-default_h5f4c503_102.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/binutils_linux-aarch64-2.46.1-default_hf1166c9_102.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/binutils_impl_linux-aarch64-2.46.1-default_h5f4c503_103.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/binutils_linux-aarch64-2.46.1-default_hf1166c9_103.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gcc_impl_linux-aarch64-16.2.0-h5425ead_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gcc_linux-aarch64-16.2.0-h25cc031_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gxx_impl_linux-aarch64-16.2.0-h1e3c31f_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gxx_linux-aarch64-16.2.0-h423111d_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.46.1-default_h1979696_102.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.46.1-default_h1979696_103.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-16.2.0-h205dda4_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-16.2.0-h8acb6b2_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsanitizer-16.2.0-h73cac2c_7.conda @@ -16329,70 +16897,104 @@ packages: - conda: https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_linux-aarch64-16.2.0-hc0c2482_107.conda - conda: https://conda.anaconda.org/conda-forge/noarch/libstdcxx-devel_linux-aarch64-16.2.0-h082e5f6_107.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-aarch64-2.28-h585391f_9.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026e-h5d301ff_0.conda host_packages: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-20_gnu.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h4777abc_10.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-cudart-12.9.79-h3ae8b8a_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-cudart-dev-12.9.79-h3ae8b8a_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-cudart-static-12.9.79-h3ae8b8a_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-nvrtc-12.9.86-h8f3c8d4_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-nvrtc-dev-12.9.86-h8f3c8d4_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-nvvm-12.9.86-he9431aa_106.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-nvvm-impl-12.9.86-h7b14b0b_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-nvvm-tools-12.9.86-h7b14b0b_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-profiler-api-12.9.79-h16bee8c_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cython-3.2.9-py314hc6b4731_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.46.1-default_h1979696_102.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcap-2.78-hfcc8634_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcufile-1.14.1.1-had8bf56_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcufile-dev-1.14.1.1-he38c790_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-cudart-13.4.92-hae6cbe8_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-cudart-dev-13.4.92-hae6cbe8_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-cudart-static-13.4.92-hae6cbe8_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-nvrtc-13.4.92-hae6cbe8_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-nvrtc-dev-13.4.92-hae6cbe8_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-nvvm-13.4.92-he9431aa_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-nvvm-impl-13.4.92-hbe86820_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-nvvm-tools-13.4.92-hbe86820_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cuda-profiler-api-13.4.92-h16bee8c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cython-3.2.9-py312hbda70bc_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.46.1-default_h1979696_103.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcap-2.78-hfcc8634_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcufile-1.19.1.55-hc7dfe37_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcufile-dev-1.19.1.55-hc1d3098_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.8.5-h4154aff_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.7.0-hdaad0be_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-16.2.0-h205dda4_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-16.2.0-h8acb6b2_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblzma-5.8.3-he30d5cf_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libmpdec-4.0.0-he30d5cf_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libnl-3.11.0-he30d5cf_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libpython-3.14.10-h150030a_100_cp314.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.54.1-hd26f1b6_101.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libnsl-2.0.1-h86ecc28_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libpython-3.12.16-h3cfa5a6_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.54.1-hd26f1b6_100.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-16.2.0-hef695bb_7.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsystemd0-262-hd1ea486_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libudev1-262-hd1ea486_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsystemd0-262.1-hd1ea486_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libudev1-262.1-hd1ea486_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.42.4-hd6fdeab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxcrypt-4.4.38-h80f16a2_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.3.2-hdc9db2a_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.6-h2b6f883_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.5-he6ad1d5_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.14.10-hbec3b18_100_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.12.16-h94ad73b_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rdma-core-65.0-h807d763_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.3-ha7194a6_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-noxft_hf03c496_4.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/uv-0.13.5-h779c035_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.7-h9d15635_7.conda - conda: https://conda.anaconda.org/conda-forge/noarch/arm-variant-1.2.0-sbsa.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.10.19-hbd8a1cb_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cccl_linux-aarch64-12.9.27-h579c4fd_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-crt-dev_linux-aarch64-12.9.86-h579c4fd_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cudart-dev_linux-aarch64-12.9.79-h3ae8b8a_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cudart-static_linux-aarch64-12.9.79-h3ae8b8a_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cudart_linux-aarch64-12.9.79-h3ae8b8a_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-nvvm-dev_linux-aarch64-12.9.86-h579c4fd_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-version-12.9-h4f385c5_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.10.23-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cccl_linux-aarch64-13.3.4.3.1-h579c4fd_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-crt-dev_linux-aarch64-13.4.92-h579c4fd_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cudart-dev_linux-aarch64-13.4.92-hae6cbe8_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cudart-static_linux-aarch64-13.4.92-hae6cbe8_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-cudart_linux-aarch64-13.4.92-hae6cbe8_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-nvvm-dev_linux-aarch64-13.4.92-h579c4fd_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-version-13.4-hfacf21a_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.3-pyhc364b38_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-9_cp314.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-84.0.0-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-9_cp312.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-84.2.1-pyhe730653_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-scm-10.3.4-pyh5ded981_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.5.0-pyh5ded981_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.16.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026e-h5d301ff_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/vcs_versioning-2.6.0-pyh5ded981_0.conda - - conda_source: cuda-pathfinder[a51836e4] @ ../cuda_pathfinder -- conda_source: cuda-pathfinder[9b57eb00] @ ../cuda_pathfinder + - conda_source: cuda-pathfinder[4653f308] @ ../cuda_pathfinder +- conda_source: cuda-pathfinder[06f93f27] @ ../cuda_pathfinder variants: target_platform: noarch depends: + - python >=3.11 - python * + license: Apache-2.0 + host_packages: + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.10.19-h4c7d964_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.3-pyhc364b38_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.15-9_cp315.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-84.2.1-pyhe730653_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-scm-10.3.4-pyh5ded981_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.5.0-pyh5ded981_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.16.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/vcs_versioning-2.6.0-pyh5ded981_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_10.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.8.5-hac47afa_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libffi-3.7.0-h3d046cb_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/liblzma-5.8.3-hfd05255_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libmpdec-4.0.0-hfd05255_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.54.1-hf5d6505_100.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.3.2-hfd05255_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.6.5-hf411b9b_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.15.2-h53f6dd8_100_cp315.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h967ab96_4.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/uv-0.13.5-hf7a7c96_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.5-ha367084_41.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.51.36247-habf1de7_41.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vcomp14-14.51.36247-habf1de7_41.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.7-h534d264_7.conda +- conda_source: cuda-pathfinder[1065009d] @ ../cuda_pathfinder + variants: + target_platform: noarch + depends: - python >=3.11 + - python * license: Apache-2.0 host_packages: - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda @@ -16424,12 +17026,82 @@ packages: - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.16.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/vcs_versioning-2.6.0-pyh5ded981_0.conda -- conda_source: cuda-pathfinder[a51836e4] @ ../cuda_pathfinder +- conda_source: cuda-pathfinder[1083a6c1] @ ../cuda_pathfinder + variants: + target_platform: noarch + depends: + - python >=3.11 + - python * + license: Apache-2.0 + host_packages: + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.10.23-h4c7d964_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.3-pyhc364b38_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.15-9_cp315.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-84.2.1-pyhe730653_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-scm-10.3.4-pyh5ded981_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.5.0-pyh5ded981_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.16.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026e-h5d301ff_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/vcs_versioning-2.6.0-pyh5ded981_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_10.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.8.5-hac47afa_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libffi-3.7.0-h3d046cb_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/liblzma-5.8.3-hfd05255_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libmpdec-4.0.0-hfd05255_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.54.1-hf5d6505_100.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.3.2-hfd05255_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.6.5-hf411b9b_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.15.2-h53f6dd8_100_cp315.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h967ab96_4.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/uv-0.13.5-hf7a7c96_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.5-ha367084_41.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.51.36247-habf1de7_41.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vcomp14-14.51.36247-habf1de7_41.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.7-h534d264_7.conda +- conda_source: cuda-pathfinder[224d4d31] @ ../cuda_pathfinder variants: target_platform: noarch depends: + - python >=3.11 - python * + license: Apache-2.0 + host_packages: + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_10.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.46.1-default_hbd61a6d_103.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20260512-pl5321h373387f_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.8.5-hd2095e1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.7.0-h81df57d_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-16.2.0-ha9f2e26_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-16.2.0-he0feb66_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-hb03c661_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb03c661_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.54.1-h0737f62_100.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-16.2.0-h934c35e_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42.4-hcfc3c73_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.5-h781a0a9_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.15.2-h6e52b48_100_cp315.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h1df4ec4_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/uv-0.13.5-h535ca38_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_7.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.10.23-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.3-pyhc364b38_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.15-9_cp315.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-84.2.1-pyhe730653_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-scm-10.3.4-pyh5ded981_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.5.0-pyh5ded981_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.16.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026e-h5d301ff_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/vcs_versioning-2.6.0-pyh5ded981_0.conda +- conda_source: cuda-pathfinder[4653f308] @ ../cuda_pathfinder + variants: + target_platform: noarch + depends: - python >=3.11 + - python * license: Apache-2.0 host_packages: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-20_gnu.conda @@ -16452,24 +17124,44 @@ packages: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-noxft_hf03c496_4.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/uv-0.13.5-h779c035_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.7-h9d15635_7.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.10.19-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.10.23-hbd8a1cb_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.3-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.15-9_cp315.conda - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-84.2.1-pyhe730653_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-scm-10.3.4-pyh5ded981_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.5.0-pyh5ded981_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.16.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026e-h5d301ff_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/vcs_versioning-2.6.0-pyh5ded981_0.conda -- conda_source: cuda-pathfinder[f6abc7c0] @ ../cuda_pathfinder +- conda_source: cuda-pathfinder[81b61b10] @ ../cuda_pathfinder variants: target_platform: noarch depends: - - python * - python >=3.11 + - python * license: Apache-2.0 host_packages: - - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.10.19-h4c7d964_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-20_gnu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h4777abc_10.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.46.1-default_h1979696_103.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libedit-3.1.20260512-pl5321hc48eb74_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.8.5-h4154aff_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.7.0-hdaad0be_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-16.2.0-h205dda4_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-16.2.0-h8acb6b2_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblzma-5.8.3-he30d5cf_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libmpdec-4.0.0-he30d5cf_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.54.1-hd26f1b6_100.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-16.2.0-hef695bb_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.42.4-hd6fdeab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.3.2-hdc9db2a_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.6-h2b6f883_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.5-he6ad1d5_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.15.2-h0c7c799_100_cp315.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-noxft_hf03c496_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/uv-0.13.5-h779c035_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.7-h9d15635_7.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.10.19-hbd8a1cb_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.3-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.15-9_cp315.conda - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-84.2.1-pyhe730653_0.conda @@ -16478,22 +17170,6 @@ packages: - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.16.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/vcs_versioning-2.6.0-pyh5ded981_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_10.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.8.5-hac47afa_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libffi-3.7.0-h3d046cb_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/liblzma-5.8.3-hfd05255_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libmpdec-4.0.0-hfd05255_2.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.54.1-hf5d6505_100.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.3.2-hfd05255_3.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.6.5-hf411b9b_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.15.2-h53f6dd8_100_cp315.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h967ab96_4.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/uv-0.13.5-hf7a7c96_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.5-ha367084_41.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.51.36247-habf1de7_41.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/vcomp14-14.51.36247-habf1de7_41.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.7-h534d264_7.conda - pypi: ../cuda_python_test_helpers name: cuda-python-test-helpers requires_dist: @@ -16507,3 +17183,95 @@ packages: - sphinx>=7.1 - pydata-sphinx-theme>=0.15 requires_python: '>=3.10' +- conda: https://conda.anaconda.org/conda-forge/win-64/python-3.15.2-h53f6dd8_100_cp315.conda + build_number: 100 + sha256: 75ce979442c5a5cd4f38ced72c5060c35e3b3d4539d92d2cb8bae5e3b6043fa4 + md5: 969c2999f8e4cc1da50ec1930cc7f3a5 + depends: + - bzip2 >=1.0.8,<2.0a0 + - libexpat >=2.8.5,<3.0a0 + - libffi >=3.7.0,<3.8.0a0 + - liblzma >=5.8.3,<6.0a0 + - libmpdec >=4.0.0,<5.0a0 + - libsqlite >=3.54.1,<4.0a0 + - libzlib >=1.3.2,<2.0a0 + - openssl >=3.5.9,<4.0a0 + - python_abi 3.15.* *_cp315 + - tk >=8.6.13,<8.7.0a0 + - tzdata + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - zstd >=1.5.7,<1.6.0a0 + license: Python-2.0 + run_exports: + weak: + - python_abi 3.15.* *_cp315 + noarch: + - python + size: 18579162 + timestamp: 1793015037227 + python_site_packages_path: lib/python/site-packages +- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.15.2-h6e52b48_100_cp315.conda + build_number: 100 + sha256: dd6fdef748df5636029673a834ca3632ce44c86d71e4986d70bcdb2ae5607a25 + md5: 38c3edc23439db3ca383be02ae2b702e + depends: + - __glibc >=2.17,<3.0.a0 + - bzip2 >=1.0.8,<2.0a0 + - ld_impl_linux-64 >=2.36.1 + - libedit >=3.1.20260512,<3.2.0a0 + - libexpat >=2.8.5,<3.0a0 + - libffi >=3.7.0,<3.8.0a0 + - libgcc >=15 + - liblzma >=5.8.3,<6.0a0 + - libmpdec >=4.0.0,<5.0a0 + - libsqlite >=3.54.1,<4.0a0 + - libuuid >=2.42.4,<3.0a0 + - libzlib >=1.3.2,<2.0a0 + - ncurses >=6.6,<7.0a0 + - openssl >=3.5.9,<4.0a0 + - python_abi 3.15.* *_cp315 + - tk >=8.6.13,<8.7.0a0 + - tzdata + - zstd >=1.5.7,<1.6.0a0 + license: Python-2.0 + run_exports: + weak: + - python_abi 3.15.* *_cp315 + noarch: + - python + size: 29327137 + timestamp: 1793015518763 + python_site_packages_path: lib/python3.15/site-packages +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.15.2-h0c7c799_100_cp315.conda + build_number: 100 + sha256: 788a8c701af3fb86e7e7d8f40335804959e796c705b7b7e9a409de2eea8ded18 + md5: 9874b7ceebe929da370eddcc23314fa3 + depends: + - bzip2 >=1.0.8,<2.0a0 + - ld_impl_linux-aarch64 >=2.36.1 + - libedit >=3.1.20260512,<3.2.0a0 + - libexpat >=2.8.5,<3.0a0 + - libffi >=3.7.0,<3.8.0a0 + - libgcc >=15 + - liblzma >=5.8.3,<6.0a0 + - libmpdec >=4.0.0,<5.0a0 + - libsqlite >=3.54.1,<4.0a0 + - libuuid >=2.42.4,<3.0a0 + - libzlib >=1.3.2,<2.0a0 + - ncurses >=6.6,<7.0a0 + - openssl >=3.5.9,<4.0a0 + - python_abi 3.15.* *_cp315 + - tk >=8.6.13,<8.7.0a0 + - tzdata + - zstd >=1.5.7,<1.6.0a0 + license: Python-2.0 + run_exports: + weak: + - python_abi 3.15.* *_cp315 + noarch: + - python + size: 27765007 + timestamp: 1793015442708 + python_site_packages_path: lib/python3.15/site-packages diff --git a/cuda_bindings_13/pixi.toml b/cuda_bindings_13/pixi.toml index 0c7c58c2050..99bf5e3ca64 100644 --- a/cuda_bindings_13/pixi.toml +++ b/cuda_bindings_13/pixi.toml @@ -28,7 +28,8 @@ cuda-python-test-helpers = { path = "../cuda_python_test_helpers", editable = tr # Keep this dependency set aligned with cuda_python/docs/environment-docs.yml. [feature.docs.dependencies] -cuda-bindings = "13.2.*" +# Document the checkout's API, including modules absent from published packages. +cuda-bindings = { path = "." } python = "3.12.*" cython = ">=3.2.5,<3.3" enum_tools = "*" diff --git a/cuda_python/docs/environment-docs.yml b/cuda_python/docs/environment-docs.yml index 3152f0a3a93..a82fd02aa5e 100644 --- a/cuda_python/docs/environment-docs.yml +++ b/cuda_python/docs/environment-docs.yml @@ -19,6 +19,8 @@ dependencies: - sphinx-copybutton - myst-nb - enum_tools + # cuda_bindings_12/docs/source/conf.py uses the Furo theme. + - furo - sphinx-toolbox - pyclibrary - pip: diff --git a/toolshed/setup-docs-env.sh b/toolshed/setup-docs-env.sh index 9acbaa8e391..73afbbf06f9 100755 --- a/toolshed/setup-docs-env.sh +++ b/toolshed/setup-docs-env.sh @@ -51,6 +51,7 @@ conda create -y -n "${ENV_NAME}" \ sphinx-copybutton \ myst-nb \ enum_tools \ + furo \ sphinx-toolbox \ pyclibrary From 1bfdf64400ae73f84d064bcb7c849480c98395be Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sun, 1 Nov 2026 19:29:46 -0800 Subject: [PATCH 2/2] fix: select one docs metapackage for dependent tags [skip ci] Signed-off-by: Ralf W. Grosse-Kunstleve --- ci/tools/download-wheels | 4 +++- ci/tools/tests/test_download_wheels.py | 15 +++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/ci/tools/download-wheels b/ci/tools/download-wheels index 28b2da21bb2..d5062968152 100755 --- a/ci/tools/download-wheels +++ b/ci/tools/download-wheels @@ -87,10 +87,12 @@ else ARTIFACT_PATTERN="${COMPONENT}*" fi +# Dependent-tag docs also select one metapackage using the resolved toolkit. IS_BINDINGS_RELEASE=false if [[ "$COMPONENT" != "all" \ && "$COMPONENT" =~ ^cuda-(bindings|python)$ \ - && "$GIT_TAG" == v* ]]; then + && ( "$GIT_TAG" == v* \ + || ( "$COMPONENT" == "cuda-python" && -n "$RESOLVED_BINDINGS_PACKAGE_JSON" ) ) ]]; then IS_BINDINGS_RELEASE=true fi diff --git a/ci/tools/tests/test_download_wheels.py b/ci/tools/tests/test_download_wheels.py index 5eba0ec224f..ae80e87efb7 100644 --- a/ci/tools/tests/test_download_wheels.py +++ b/ci/tools/tests/test_download_wheels.py @@ -79,6 +79,21 @@ def test_release_stages_only_wheels_for_its_exact_toolkit(tmp_path, component, m assert {path.name for path in (tmp_path / "dist").iterdir()} == {f"{expected}.whl"} +@pytest.mark.parametrize("tag", ["cuda-core-v1.3.0", "cuda-pathfinder-v1.5.0"]) +@pytest.mark.agent_authored(model="gpt-6") +def test_dependent_tag_docs_stage_one_metapackage_for_resolved_toolkit(tmp_path, tag): + expected = "cuda-python-wheel-cuda13.4.2" + result = run_download( + tmp_path, + ["cuda-python-wheel-cuda12.9.1", expected], + "cuda-python", + package={"toolkit_version": "13.4.2"}, + tag=tag, + ) + assert result.returncode == 0, result.stderr + assert {path.name for path in (tmp_path / "dist").iterdir()} == {f"{expected}.whl"} + + @pytest.mark.parametrize("component", ["cuda-bindings", "cuda-python"]) @pytest.mark.agent_authored(model="gpt-6.1-sol") def test_release_cannot_stage_another_toolkit_or_test_artifacts(tmp_path, component):