Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ closes <!-- Link issue here -->
<!-- TODO: - [ ] I am familiar with the [Contributing Guidelines](). -->
- [ ] New or existing tests cover these changes.
- [ ] The documentation is up to date with these changes.
- [ ] A release note is added (or the `skip-release-note` label is applied if none is needed).
33 changes: 28 additions & 5 deletions .github/RELEASE-core.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,32 @@ functions, classes, or features were added and whether they have complete
docstrings. Add or edit docstrings as needed — touching docstrings and
type annotations in code is OK during code freeze.

Write the release notes in `cuda_core/docs/source/release/`. Look at
historical release notes for guidance on format and structure. Balance all
entries for length, specificity, tone, and consistency. Highlight a few
notable items in the highlights section, keeping their full entries in the
appropriate sections below.
Release notes are not written at release time. Since 1.3.0 they are
per-change note files, added by each PR under `cuda_core/releasenotes/` (see "Release notes" in
[CONTRIBUTING.md](../CONTRIBUTING.md#release-notes)). The docs build generates
the page for each release from the notes in git: a minor release lists the
notes added since the previous minor release, and a patch release lists those
added since the previous release of the same `X.Y` line. Earlier releases keep
their hand-written pages in `cuda_core/docs/source/release/`.

So the work here is to review and polish the notes, and to do it *before* the
tag is cut, because the page is built from the tagged commit:

- Read the "In development" page of the latest docs, which shows the notes that
will go into the next release (or build the docs locally from a full clone).
Balance all entries for length, specificity, tone, and consistency, and edit
the note files in a PR. Edits to notes that already shipped in an earlier
release also change that release's page the next time the docs are published
from `main`, so older notes can be corrected too.
- Highlight a few notable items by adding a note of type `prelude`. All
preludes in the release are combined at the top of its page, so the full
notes stay in their own sections below.
- Check the known issues (`issue` notes). They are listed on every release
until their note is deleted, so delete the ones that this release resolves
and make sure the remaining ones are still true.
- Make sure the notes make it to `main`. The release workflow fails if no note
was added in the release's range, but that does not mean every PR had one
(the PR check allows a `skip-release-note` label); skim the list of PRs.

---

Expand All @@ -126,6 +147,8 @@ certain the tag points to the correct commit before pushing.

Tags should be GPG-signed. The tag name format is `cuda-core-v<VERSION>`
(e.g. `cuda-core-v0.6.0`). The tag must point to a commit on `main`.
All release notes and docstring edits must already be merged, because the
release notes page is generated from the tagged commit.

```bash
git checkout main
Expand Down
28 changes: 28 additions & 0 deletions .github/actions/fetch-release-history/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#
# SPDX-License-Identifier: Apache-2.0

name: Fetch release history

description: >-
Complete a shallow checkout with the git history needed to build release
notes (see cuda_python/docs/exts/release_notes.py): the history of the
checked-out commit and of every tag. No branches are fetched, which also
leaves out the large gh-pages branch that holds only built docs.

runs:
using: composite
steps:
- name: Fetch the checked-out commit's history and all tags
shell: bash --noprofile --norc -xeuo pipefail {0}
run: |
# Run after actions/checkout with its default fetch-depth of 1.
# Release notes are read from the history reachable from release tags
# (patch tags may sit on maintenance branches) and from the commit being
# built, so no branch names are needed.
refspecs=("$(git rev-parse HEAD)" '+refs/tags/*:refs/tags/*')
if [[ "$(git rev-parse --is-shallow-repository)" == "true" ]]; then
git fetch --unshallow --no-tags origin "${refspecs[@]}"
else
git fetch --no-tags origin "${refspecs[@]}"
fi
4 changes: 4 additions & 0 deletions .github/workflows/build-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ jobs:
fetch-depth: 1
ref: ${{ inputs.git-tag }}

# The release notes are built from the git history between release tags.
- name: Fetch release history
uses: ./.github/actions/fetch-release-history

- name: Read build CTK version
run: |
if [[ -f ci/versions.yml ]]; then
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci-nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ jobs:

- name: Run CI tools unit tests
run: |
python -m pip install pytest pyyaml==6.0.3
python -m pip install -r ci/tools/tests/requirements.txt
# Standalone CI tool tests; skip repo-root conftest.py (imports cuda.pathfinder).
python -m pytest -v --noconftest ci/tools/tests

Expand Down
36 changes: 30 additions & 6 deletions .github/workflows/pr-metadata-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ on:
- ready_for_review

permissions:
contents: read
pull-requests: read

jobs:
Expand All @@ -26,7 +27,17 @@ jobs:
if: github.repository_owner == 'NVIDIA'
runs-on: ubuntu-latest
steps:
- name: Check metadata and blocking labels
# pull_request_target checks out the base branch, never the PR's code, so
# the scripts that run below are the trusted ones.
- name: Checkout check scripts
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
sparse-checkout: |
ci/tools
cuda_python/docs/exts
persist-credentials: false

- name: Check metadata, blocking labels, and release notes
env:
PR_URL: ${{ github.event.pull_request.html_url }}
PR_NUMBER: ${{ github.event.pull_request.number }}
Expand Down Expand Up @@ -72,14 +83,27 @@ jobs:
ERRORS="${ERRORS}- **Blocked label detected**: label \`$label\` prevents merging. Remove it when the PR is ready.\n"
done <<<"$BLOCKED_LABELS"

# Release notes are required for every PR that changes package sources.
set +e
RELEASE_NOTE_PROBLEMS=$(python3 ci/tools/check_pr_release_notes.py \
--repo "$GH_REPO" --pr "$PR_NUMBER" --labels-json "$LABELS")
RELEASE_NOTE_STATUS=$?
set -e
if [ "$RELEASE_NOTE_STATUS" -eq 3 ]; then
ERRORS="${ERRORS}${RELEASE_NOTE_PROBLEMS}\n"
elif [ "$RELEASE_NOTE_STATUS" -ne 0 ]; then
echo "::error::The release-note check itself failed (exit status ${RELEASE_NOTE_STATUS})."
exit "$RELEASE_NOTE_STATUS"
fi

# Bots cannot provide positive metadata such as an assignee or
# milestone. Once blocking labels have been checked, exempt them
# from the remaining requirements.
# milestone. Once blocking labels and release notes have been
# checked, exempt them from the remaining requirements.
if [ "$IS_BOT" = "true" ]; then
if [ -n "$ERRORS" ]; then
echo "::error::This PR has a label that prevents merging. See the job summary for details."
echo "::error::This PR has a label that prevents merging or is missing a release note. See the job summary for details."
{
echo "## PR Blocking Label Check Failed"
echo "## PR Check Failed"
echo ""
printf '%b' "$ERRORS"
echo ""
Expand All @@ -89,7 +113,7 @@ jobs:
fi

{
echo "## PR Blocking Label Check Passed"
echo "## PR Blocking Label and Release Note Check Passed"
echo ""
echo "Bot-authored PR; positive metadata requirements are exempt."
} >> "$GITHUB_STEP_SUMMARY"
Expand Down
19 changes: 12 additions & 7 deletions .github/workflows/release-cuda-pathfinder.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,16 +68,21 @@ jobs:
# Resolve only the exact tag ref; checkout fails if the tag does not exist.
ref: refs/tags/${{ steps.vars.outputs.tag }}

# The release notes are found from the git history between release tags.
- name: Fetch release history
uses: ./.github/actions/fetch-release-history

- name: Set up Python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.12"

# Hand-written notes (before 1.9.0) or note files added in the release's range.
- name: Check release notes exist
env:
VERSION: ${{ steps.vars.outputs.version }}
TAG: ${{ steps.vars.outputs.tag }}
run: |
notes="cuda_pathfinder/docs/source/release/${VERSION}-notes.rst"
if [[ ! -f "${notes}" ]]; then
echo "::error::Release notes not found: ${notes}"
echo "Create the release notes file before running this workflow."
exit 1
fi
python ci/tools/check_release_notes.py --git-tag "${TAG}" --component cuda-pathfinder

- name: Detect CI run ID
id: detect-run
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,10 @@ jobs:
with:
ref: ${{ inputs.git-tag }}

# The release notes are found from the git history between release tags.
- name: Fetch release history
uses: ./.github/actions/fetch-release-history

Comment on lines +167 to +170

@coderabbitai coderabbitai Bot Oct 19, 2026 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🔎 Supported by static analysis

🏁 Script executed:

set -eu
printf '%s\n' '--- release.yml relevant blocks ---'
nl -ba .github/workflows/release.yml | sed -n '120,205p'
printf '%s\n' '--- build-docs.yml relevant block ---'
nl -ba .github/workflows/build-docs.yml | sed -n '35,90p'
printf '%s\n' '--- release-cuda-pathfinder.yml relevant block ---'
nl -ba .github/workflows/release-cuda-pathfinder.yml | sed -n '40,95p'
printf '%s\n' '--- local action files ---'
find .github/actions/fetch-release-history -maxdepth 2 -type f -print -exec nl -ba {} \;
printf '%s\n' '--- PR diff for the workflows and action ---'
git diff --stat 9d903cdcaee82731618dd56e8c76bcd528918592 c99c5bd07318359595e5f76b0722b91b6855b3b4 -- .github/workflows .github/actions/fetch-release-history
git diff --unified=20 9d903cdcaee82731618dd56e8c76bcd528918592 c99c5bd07318359595e5f76b0722b91b6855b3b4 -- .github/workflows/release.yml .github/workflows/build-docs.yml .github/workflows/release-cuda-pathfinder.yml .github/actions/fetch-release-history
printf '%s\n' '--- release routing references ---'
rg -n -F -e 'backport_branch' -e 'validate_backport_decision' -e 'release_ranges' -e 'git-tag' ci .github | head -200 || true

Repository: NVIDIA/cuda-python

Length of output: 34102


🏁 Script executed:

set -eu
printf '%s\n' '--- base and head file presence ---'
for rev in 9d903cdcaee82731618dd56e8c76bcd528918592 c99c5bd07318359595e5f76b0722b91b6855b3b4; do
  echo "REV $rev"
  for path in .github/actions/fetch-release-history/action.yml ci/tools/check_release_notes.py ci/tools/release_ranges.py cuda_python/docs/exts/release_notes.py .github/workflows/release.yml .github/workflows/build-docs.yml .github/workflows/release-cuda-pathfinder.yml; do
    if git cat-file -e "$rev:$path" 2>/dev/null; then echo "  present $path"; else echo "  absent  $path"; fi
  done
done
printf '%s\n' '--- relevant release workflow header and inputs ---'
nl -ba .github/workflows/release.yml | sed -n '1,120p'
printf '%s\n' '--- release ranges and versions ---'
nl -ba ci/release_ranges.py 2>/dev/null | sed -n '1,180p' || true
nl -ba ci/versions.yml | sed -n '1,40p'
printf '%s\n' '--- tags and action presence for representative release tags ---'
git tag --list | grep -E '^(cuda-bindings-v|cuda-core-v|cuda-pathfinder-v|v)' | tail -80 || true
for tag in $(git tag --list | grep -E '^(cuda-bindings-v|cuda-core-v|cuda-pathfinder-v|v)' | tail -20); do
  if git cat-file -e "$tag:.github/actions/fetch-release-history/action.yml" 2>/dev/null; then state=present; else state=absent; fi
  echo "$tag action=$state"
done
printf '%s\n' '--- changed files outside workflow scope relevant to compatibility ---'
git diff --name-status 9d903cdcaee82731618dd56e8c76bcd528918592 c99c5bd07318359595e5f76b0722b91b6855b3b4 | sed -n '1,160p'

Repository: NVIDIA/cuda-python

Length of output: 12970


🏁 Script executed:

set -eu
printf '%s\n' '--- release package ranges ---'
rg -n -F -e 'cuda-pathfinder' -e '1.8' -e 'PACKAGES' cuda_python/docs/exts/release_ranges.py
nl -ba cuda_python/docs/exts/release_ranges.py | sed -n '1,180p'
printf '%s\n' '--- backport validation and release workflow routing ---'
nl -ba ci/tools/check_release_notes.py | sed -n '210,285p'
nl -ba .github/workflows/backport.yml | sed -n '1,90p'

Repository: NVIDIA/cuda-python

Length of output: 13451


important: Keep release-history fetching independent of the checked-out release tag.

Each workflow checks out the release tag before it invokes ./.github/actions/fetch-release-history. Tags created before this PR do not contain action.yml, so the release can stop with Can't find 'action.yml' before the release-note check. This affects the configured maintenance-branch backport flow and older cuda-pathfinder 1.8.x tags.

Inline the fetch command in all three workflows:

-      - name: Fetch release history
-        uses: ./.github/actions/fetch-release-history
+      - name: Fetch release history
+        run: |
+          refspecs=("$(git rev-parse HEAD)" '+refs/tags/*:refs/tags/*')
+          if [[ "$(git rev-parse --is-shallow-repository)" == "true" ]]; then
+            git fetch --unshallow --no-tags origin "${refspecs[@]}"
+          else
+            git fetch --no-tags origin "${refspecs[@]}"
+          fi

Apply this change to .github/workflows/release.yml, .github/workflows/build-docs.yml, and .github/workflows/release-cuda-pathfinder.yml.

🧰 Tools
🪛 zizmor (1.30.1)

[warning] 162-167: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)


[warning] 5-285: overly broad permissions (excessive-permissions): default permissions used due to no permissions: block

(excessive-permissions)


[warning] 158-181: overly broad permissions (excessive-permissions): default permissions used due to no permissions: block

(excessive-permissions)


[warning] 169-169: use GitHub's dedicated self-repository syntax (self-repository): use '$/...' instead of './...'

(self-repository)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I follow. The action should be available from every commit it is called from. Can you describe the scenario in which this would fail?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mdboom important: The workflow definition and the checked-out files can come from different commits.

The failure scenario is:

  1. This PR merges into main.
  2. A maintainer dispatches the release workflow from main, with git-tag set to a tag created before this PR.
  3. actions/checkout checks out that tag because the step sets ref: ${{ inputs.git-tag }}.
  4. The next step invokes ./.github/actions/fetch-release-history.

GitHub resolves a ./ action from the checked-out workspace, not from the commit that supplied the workflow definition. If the selected tag lacks .github/actions/fetch-release-history/action.yml, the action cannot load.

The action is available in the commit that defines the workflow, as you describe. The preceding checkout replaces the workspace with a different commit.

If releases only target tags that contain this action, this failure does not occur. My concern is running the updated workflow against older tags or maintenance-branch tags that do not contain it.

You are interacting with an AI system.

- name: Set up Python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
Expand Down
9 changes: 8 additions & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ repos:
language: python
additional_dependencies:
- https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl
exclude: '(.*pixi\.lock)|(\.git_archival\.txt)|(.*\.patch$)|(^cuda_core/cuda/core/_vendored/)|(^cuda_core/third_party/)'
exclude: '(.*pixi\.lock)|(\.git_archival\.txt)|(.*\.patch$)|(^cuda_core/cuda/core/_vendored/)|(^cuda_core/third_party/)|(^|/)releasenotes/'
args: ["--fix"]

- id: check-cython-not-none
Expand All @@ -79,6 +79,13 @@ repos:
files: '^(ci/versions\.yml|cuda_bindings/pixi\.toml|cuda_core/pixi\.toml)$'
pass_filenames: false

- id: release-notes-lint
name: Lint release notes
entry: python ./ci/tools/lint_release_notes.py
language: python
files: '^(cuda_bindings|cuda_core|cuda_pathfinder|cuda_python)/releasenotes/'
pass_filenames: false

- id: check-mempool-hygiene
name: Check tests do not create uncapped memory pools
entry: python ./ci/tools/check_mempool_hygiene.py
Expand Down
105 changes: 105 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,12 @@ Thank you for your interest in contributing to CUDA Python! Based on the type of
- [Enabling git symlinks](#enabling-git-symlinks)
- [Type stubs for cuda.core](#type-stubs-for-cudacore)
- [Pre-commit](#pre-commit)
- [Release notes](#release-notes)
- [Writing a release note](#writing-a-release-note)
- [Known issues](#known-issues)
- [How release notes are assembled](#how-release-notes-are-assembled)
- [Pixi lockfiles](#pixi-lockfiles)
- [Secret Scanning](#secret-scanning)
- [Signing Your Work](#signing-your-work)
- [Code signing](#code-signing)
- [Developer Certificate of Origin (DCO)](#developer-certificate-of-origin-dco)
Expand Down Expand Up @@ -235,6 +240,106 @@ between commits, leaving stale headers or out-of-date stubs in the history.
If the hook isn't installed, `pre-commit run` will print a visible warning
reminding you to run `pre-commit install`.

## Release notes

Release notes are one small reStructuredText file per change, kept next to the code in the
PR that makes the change. (The design is inspired by
[reno](https://docs.openstack.org/reno/latest/), but behaves quite differently.)
All four packages work this way: `cuda-bindings` and
`cuda-python` (13.5.0 and later), `cuda-core` (1.3.0 and later) and
`cuda-pathfinder` (1.9.0 and later), with notes in
`<package>/releasenotes/`. Earlier releases keep their hand-written pages
under `<package>/docs/source/release/`.

### Writing a release note

Every pull request that changes the sources of one of these packages needs a
release note for it, or an edit to an existing one (a PR touching multiple
packages needs one for each). Changes to docs, tests, examples, and CI do not
need one. A CI check enforces this. If a PR touches the sources but truly needs
no note, a maintainer can apply the `skip-release-note` label.

Create a note with the `add_note.py` script. It can be run from any directory,
and takes the package, the type of note and a few words describing the change:

```bash
python toolshed/add_note.py cuda-core fix "Fix the thing" [--edit]
```

The package is one of `cuda-bindings`, `cuda-core`, `cuda-pathfinder` and
`cuda-python` (the `cuda-` prefix is optional). The type is one of the values in
the table below. The new file is created in `<package>/releasenotes/` and named
`<type>-<short-description>-<hash>.rst`. `--edit` opens it in `$VISUAL` or
`$EDITOR`.

Edit the new file and replace the `TODO` text. A note is reStructuredText,
written for users of the package, and has exactly one type, which is the start
of its file name. A change that needs two kinds of entry, such as a bug fix that
is also a breaking change, gets two notes. A pre-commit hook checks the notes
for obvious mistakes, such as an unknown type or leftover `TODO` text.

| Type | Use for |
|---|---|
| `feature` | New functionality, including experimental APIs (say so in the text) |
| `upgrade` | Changes users may need to act on, including behavior changes |
| `deprecation` | Newly deprecated functionality |
| `critical` | Critical issues users must know about |
| `security` | Security issues |
| `fix` | Bug fixes |
| `issue` | Known issues (see below) |
| `other` | Anything else |
| `prelude` | An introduction to a release's notes. Useful to highlight important themes in a release. |

Some details:

* You do not need to add a link to the pull request: one is added automatically,
taken from the `(#N)` in the squash-merge commit that introduced the note.
* To name the pull request(s) yourself instead, write `(#1234)` or
`(#1234, #1235)` anywhere in a note, usually at the end. Each marker is
replaced with links, and the automatic lookup is skipped for that note. This
is rarely needed. It is for a note whose file is added by a different PR than
the one that made the change, for example a note written afterwards or notes
moved in from another place. The marker can go anywhere in ordinary text. A
`(#N)` inside backquoted text, such as an inline literal, is left alone, so
it can be used in an example. Do not put a marker inside a literal block, or
the rows of a table or other directive content, where the link text could
break the markup.
* Do not rename or move a note after it is merged.
* Which releases list a note is decided from git, so a note shows up in a local
docs build only once it is committed.
* You can fix a note that is already part of a release (a typo, or a clearer
wording). The docs are published from `main`, and every page shows a note's
current text, so the fix appears on the pages of the releases that list it
the next time the docs are published. Editing a note never moves it to
another release.

### Known issues

Unlike the other types, which appear only on the release that first contains
them, known issues are listed on **every** release until they are resolved. To
record one, add a note of type `issue`. To resolve it, delete that note in the
PR that fixes the problem, and describe the fix in a new `fix` note. The pages of releases that were already
tagged keep listing the issue, with the text it had when its note was deleted.

### How release notes are assembled

The docs build generates a page for every release from the notes in git,
with a final "In development" page for notes that are not in any release yet.
Only plain `vX.Y.Z` tags count as releases. Pre-release tags (`rc`, `a`, `b`)
are ignored, and their notes roll into the final release.
Comment on lines +328 to +329

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

suggestion: Fix the tag format in the release-tag rule. Line 328 says only plain vX.Y.Z tags count as releases. That is true only for cuda-bindings and cuda-python. release_ranges.PACKAGES uses cuda-core-v and cuda-pathfinder-v as the tag prefixes for the other two packages. A cuda-core release manager who reads this line can conclude that cuda-core-v1.3.0 tags are ignored. State the rule as <prefix>X.Y.Z, and list the per-package prefixes.

--- "a/CONTRIBUTING.md"
+++ "b/CONTRIBUTING.md"
@@ -325,7 +325,8 @@
 
 The docs build generates a page for every release from the notes in git,
 with a final "In development" page for notes that are not in any release yet.
-Only plain `vX.Y.Z` tags count as releases. Pre-release tags (`rc`, `a`, `b`)
+Only plain `<prefix>X.Y.Z` release tags count (`v` for `cuda-bindings` and
+`cuda-python`, `cuda-core-v` and `cuda-pathfinder-v` for the others). Pre-release tags (`rc`, `a`, `b`)
 are ignored, and their notes roll into the final release.
 
 * A minor release (`X.Y.0`) lists the notes added since the previous minor
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Only plain `vX.Y.Z` tags count as releases. Pre-release tags (`rc`, `a`, `b`)
are ignored, and their notes roll into the final release.
Only plain `<prefix>X.Y.Z` release tags count (`v` for `cuda-bindings` and
`cuda-python`, `cuda-core-v` and `cuda-pathfinder-v` for the others). Pre-release tags (`rc`, `a`, `b`)
are ignored, and their notes roll into the final release.


* A minor release (`X.Y.0`) lists the notes added since the previous minor
release.
* A patch release lists the notes added since the previous release of the same
`X.Y` line.
* A note that is backported appears on the patch release page and again on the
page of the next minor release that contains it. This is intentional.

Building the docs needs the history of the checked-out commit and of every release
tag (no branches), and the build fails on a shallow clone rather than produce incomplete
pages. In CI, the `.github/actions/fetch-release-history` action does this. The
rules are documented in `cuda_python/docs/exts/release_notes.py`.

## Pixi lockfiles

The repository checks in a `pixi.lock` next to each `pixi.toml`. Those lockfiles
Expand Down
Loading
Loading