Skip to content

Commit dd7ce37

Browse files
committed
release: validate tagged source, notes, and exact artifacts
Review-only narrative layer 5 of 6 for #2737. Read release configuration and exact-version nonempty notes from supported tagged source. Qualify release checkouts and archives as refs/tags, require exact-tag/exact-SHA successful CI, validate complete artifact matrices, exclude test wheels, and select explicit dependency sources. Include release checklist changes and behavior tests. Older pre-registry tags require compatible historical tooling; this layer provides no legacy fallback. Implementation source: 6c3de41 Review baseline: ab9e20f Read these commits in order. Shared files are assigned as complete files to one layer, so intermediate commits need not build or pass CI. Only the final Git tree matches the implementation. This branch is a reading aid, not an alternate merge or release path. Validation belongs to the implementation source above.
1 parent 2c66e8e commit dd7ce37

13 files changed

Lines changed: 1611 additions & 759 deletions

‎.github/ISSUE_TEMPLATE/release_checklist.yml‎

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,25 +10,26 @@ body:
1010
- type: markdown
1111
attributes:
1212
value: |
13-
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).
13+
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.
1414
1515
- type: checkboxes
1616
id: subpackage-tasks
1717
attributes:
1818
label: Tasks for cuda-core and cuda-bindings patch release
1919
options:
2020
- label: File an internal nvbug to communicate test plan & release schedule with QA
21-
- label: Ensure all pending PRs are reviewed, tested, and merged
21+
- label: Record the release scope and ensure all PRs selected for this release are reviewed, tested, and merged
2222
- label: Check (or update if needed) the dependency requirements
2323
- label: Sweep deprecations whose stated removal version has arrived (`grep -rn 'deprecated::' cuda_core/cuda`) and remove any that are due
2424
- label: "Finalize the doc update, including release notes (\"Note: Touching docstrings/type annotations in code is OK during code freeze, apply your best judgement!\")"
2525
- label: Update the docs for the new version
26-
- label: Create a public release tag
27-
- 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)
26+
- label: Record the exact source commit, workflow control revision, and selected package root before creating the approved public release tag
27+
- label: Wait for the exact tag-triggered CI run to pass and complete a release dry run before approving publication
2828
- label: Publish the release at https://github.com/NVIDIA/cuda-python/releases (this will trigger the conda package update)
2929
- label: Approve the conda-package update PR
3030
- label: Post-release QA
3131
- label: Finalize the announcement update
3232
- label: Send out the announcement internally (on `#swcuda-python`)
3333
- label: Send out the announcement externally (GitHub Release -> Announcement)
34-
- 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
34+
- 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
35+
- label: For a bindings stabilization or emergency branch, link the PRs returning applicable fixes to `main` and record their applicability to both bindings roots

‎.github/workflows/release-cuda-pathfinder.yml‎

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,15 +60,41 @@ jobs:
6060
echo "version=${version}"
6161
} >> "$GITHUB_OUTPUT"
6262
63-
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
63+
- name: Checkout release control plane
64+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
65+
with:
66+
ref: ${{ github.sha }}
67+
68+
- name: Checkout release source
69+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
6470
with:
6571
# The exact tag supplies the SHA for lookup-run-id; no other tags
6672
# or commit history are needed.
6773
fetch-depth: 1
6874
# Resolve only the exact tag ref; checkout fails if the tag does not exist.
6975
ref: refs/tags/${{ steps.vars.outputs.tag }}
76+
path: release-source
77+
78+
- name: Set up Python
79+
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
80+
with:
81+
python-version: "3.12"
82+
83+
- name: Install CI tool dependencies
84+
run: python -m pip install -e ./ci
85+
86+
- name: Validate tagged release registry
87+
env:
88+
RELEASE_TAG: ${{ steps.vars.outputs.tag }}
89+
run: |
90+
# Publication can proceed after a docs failure, so reject unsupported
91+
# release sources here before creating a draft or publishing artifacts.
92+
python -m ci.tools.bindings_config \
93+
--release-tag "$RELEASE_TAG" \
94+
--release-source-root release-source
7095
7196
- name: Check release notes exist
97+
working-directory: release-source
7298
env:
7399
VERSION: ${{ steps.vars.outputs.version }}
74100
run: |
@@ -81,11 +107,12 @@ jobs:
81107
82108
- name: Detect CI run ID
83109
id: detect-run
110+
working-directory: release-source
84111
env:
85112
GH_TOKEN: ${{ github.token }}
86113
TAG: ${{ steps.vars.outputs.tag }}
87114
run: |
88-
run_id=$(./ci/tools/lookup-run-id "${TAG}" "${{ github.repository }}")
115+
run_id=$(../ci/tools/lookup-run-id --tag "${TAG}" "${{ github.repository }}")
89116
echo "run-id=${run_id}" >> "$GITHUB_OUTPUT"
90117
91118
- name: Create draft release
@@ -165,7 +192,7 @@ jobs:
165192
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
166193
with:
167194
fetch-depth: 1
168-
ref: ${{ needs.prepare.outputs.tag }}
195+
ref: refs/tags/${{ needs.prepare.outputs.tag }}
169196

170197
- name: Create source archive
171198
run: |
@@ -175,7 +202,7 @@ jobs:
175202
--format=tar.gz \
176203
--prefix="${archive}/" \
177204
--output="release/${archive}.tar.gz" \
178-
"${TAG}"
205+
"refs/tags/${TAG}"
179206
sha256sum "release/${archive}.tar.gz" \
180207
| awk '{print $1}' > "release/${archive}.tar.gz.sha256sum"
181208

‎.github/workflows/release-upload.yml‎

Lines changed: 51 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,16 @@ on:
2323
type: boolean
2424
required: false
2525
default: false
26+
bindings-package:
27+
description: "Resolved CUDA bindings package JSON"
28+
type: string
29+
required: false
30+
default: ""
2631

2732
concurrency:
28-
# Concurrency group that uses the workflow name and PR number if available
29-
# or commit SHA as a fallback. If a new build is triggered under that
30-
# concurrency group while a previous build is running it will be canceled.
31-
# Repeated pushes to a PR will cancel all previous builds, while multiple
32-
# merges to main will not cancel.
33-
group: ${{ github.workflow }}-${{ github.ref_name || github.sha }}
33+
# A retry may replace an upload for the same release operation. Different
34+
# components, tags, and dry-run modes must not cancel one another.
35+
group: ${{ github.workflow }}-${{ inputs.component }}-${{ inputs.git-tag }}-${{ inputs.dry-run }}
3436
cancel-in-progress: true
3537

3638
permissions:
@@ -44,12 +46,30 @@ jobs:
4446
runs-on: ubuntu-latest
4547
env:
4648
ARCHIVE_NAME: ${{ github.event.repository.name }}-${{ inputs.git-tag }}
49+
RELEASE_COMPONENT: ${{ inputs.component }}
50+
RELEASE_GIT_TAG: ${{ inputs.git-tag }}
51+
RELEASE_REPOSITORY: ${{ github.repository }}
52+
RELEASE_RUN_ID: ${{ inputs.run-id }}
4753
steps:
48-
- name: Checkout Source
54+
- name: Checkout release control plane
4955
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
5056
with:
5157
fetch-depth: 1
52-
ref: ${{ inputs.git-tag }}
58+
fetch-tags: true
59+
60+
- name: Checkout release source
61+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
62+
with:
63+
ref: refs/tags/${{ inputs.git-tag }}
64+
path: release-source
65+
66+
- name: Set up Python
67+
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
68+
with:
69+
python-version: "3.12"
70+
71+
- name: Install CI tool dependencies
72+
run: python -m pip install -e ./ci
5373

5474
- name: Create Release Directory
5575
run: mkdir -p release
@@ -58,44 +78,56 @@ jobs:
5878
run: >
5979
git archive
6080
--format=tar.gz
61-
--prefix="${{ env.ARCHIVE_NAME }}/"
62-
--output="release/${{ env.ARCHIVE_NAME }}.tar.gz"
63-
${{ inputs.git-tag }}
81+
--prefix="$ARCHIVE_NAME/"
82+
--output="release/$ARCHIVE_NAME.tar.gz"
83+
"refs/tags/$RELEASE_GIT_TAG"
6484
6585
- name: Compute Checksum
6686
run: >
67-
sha256sum "release/${{ env.ARCHIVE_NAME }}.tar.gz"
87+
sha256sum "release/$ARCHIVE_NAME.tar.gz"
6888
| awk '{print $1}'
69-
> "release/${{ env.ARCHIVE_NAME }}.tar.gz.sha256sum"
89+
> "release/$ARCHIVE_NAME.tar.gz.sha256sum"
7090
7191
- name: Upload Archive
7292
if: ${{ !inputs.dry-run }}
7393
env:
7494
GH_TOKEN: ${{ github.token }}
7595
run: >
7696
gh release upload
77-
--clobber "${{ inputs.git-tag }}"
78-
--repo "${{ github.repository }}"
97+
--clobber "$RELEASE_GIT_TAG"
98+
--repo "$RELEASE_REPOSITORY"
7999
release/*
80100
81101
- name: Download and Validate Wheels
82102
env:
103+
BINDINGS_PACKAGE: ${{ inputs.bindings-package }}
83104
GH_TOKEN: ${{ github.token }}
84105
run: |
85106
# Use the shared script to download wheels
86-
./ci/tools/download-wheels "${{ inputs.run-id }}" "${{ inputs.component }}" "${{ github.repository }}" "release/wheels"
107+
./ci/tools/download-wheels \
108+
"$RELEASE_RUN_ID" \
109+
"$RELEASE_COMPONENT" \
110+
"$RELEASE_REPOSITORY" \
111+
"release/wheels" \
112+
"$RELEASE_GIT_TAG" \
113+
"$BINDINGS_PACKAGE"
87114
88115
# Validate that release wheels match the expected version from tag.
89-
./ci/tools/validate-release-wheels "${{ inputs.git-tag }}" "${{ inputs.component }}" "release/wheels"
116+
python -m ci.tools.validate_release_wheels \
117+
"$RELEASE_GIT_TAG" \
118+
"$RELEASE_COMPONENT" \
119+
"release/wheels" \
120+
--bindings-package "$BINDINGS_PACKAGE" \
121+
--release-source-root release-source
90122
91123
- name: Upload Wheels
92124
if: ${{ !inputs.dry-run }}
93125
env:
94126
GH_TOKEN: ${{ github.token }}
95127
run: |
96128
if [[ -d "release/wheels" && $(ls -A release/wheels 2>/dev/null | wc -l) -gt 0 ]]; then
97-
echo "Uploading wheels to release ${{ inputs.git-tag }}"
98-
gh release upload --clobber "${{ inputs.git-tag }}" --repo "${{ github.repository }}" release/wheels/*
129+
echo "Uploading wheels to release $RELEASE_GIT_TAG"
130+
gh release upload --clobber "$RELEASE_GIT_TAG" --repo "$RELEASE_REPOSITORY" release/wheels/*
99131
fi
100132
101133
- name: Upload dry-run release artifacts

0 commit comments

Comments
 (0)