Skip to content

Commit 7a21ea4

Browse files
Andy-Jostclaude
andcommitted
Merge main into ajost/fix-790-host-func-trampoline
Co-Authored-By: Claude Fable 5.1 <[email protected]>
2 parents 2273419 + df752de commit 7a21ea4

316 files changed

Lines changed: 35717 additions & 10853 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
#
3+
# SPDX-License-Identifier: Apache-2.0
4+
5+
name: Download artifact (with retry)
6+
7+
description: >-
8+
Wrapper around actions/download-artifact that retries once after a short
9+
delay when the first attempt fails. Designed to absorb transient
10+
infrastructure flakes such as "other side closed" without failing the job.
11+
12+
inputs:
13+
name:
14+
description: "Name of the artifact to download"
15+
required: true
16+
path:
17+
description: "Destination path for the downloaded artifact"
18+
required: true
19+
run-id:
20+
description: >-
21+
The run ID of the workflow run that uploaded the artifact. Only used
22+
together with github-token; leave empty to download from the current run.
23+
required: false
24+
default: ""
25+
github-token:
26+
description: >-
27+
Token used to download from another run or repository. Leave empty (the
28+
default) to download from the current run, which uses
29+
actions/download-artifact's internal download path. That path is not the
30+
same as the one used when a token is given, so do not default this to
31+
github.token.
32+
required: false
33+
default: ""
34+
retry-delay-seconds:
35+
description: "Seconds to wait between the first failure and the retry"
36+
required: false
37+
default: "15"
38+
39+
runs:
40+
using: composite
41+
steps:
42+
- name: Download artifact (attempt 1)
43+
id: attempt1
44+
continue-on-error: true
45+
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
46+
with:
47+
name: ${{ inputs.name }}
48+
path: ${{ inputs.path }}
49+
run-id: ${{ inputs.run-id }}
50+
github-token: ${{ inputs.github-token }}
51+
52+
- name: Wait before retry
53+
if: ${{ steps.attempt1.outcome == 'failure' }}
54+
shell: bash --noprofile --norc -euo pipefail {0}
55+
env:
56+
# Pass through env instead of interpolating the input into the shell
57+
# script, so a non-numeric value cannot inject commands.
58+
RETRY_DELAY_SECONDS: ${{ inputs.retry-delay-seconds }}
59+
run: |
60+
echo "::warning::Artifact download failed (attempt 1); retrying in ${RETRY_DELAY_SECONDS}s"
61+
sleep "$RETRY_DELAY_SECONDS"
62+
63+
- name: Download artifact (attempt 2)
64+
if: ${{ steps.attempt1.outcome == 'failure' }}
65+
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
66+
with:
67+
name: ${{ inputs.name }}
68+
path: ${{ inputs.path }}
69+
run-id: ${{ inputs.run-id }}
70+
github-token: ${{ inputs.github-token }}

‎.github/labeler.yml‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,15 @@
77

88
cuda.bindings:
99
- changed-files:
10-
- any-glob-to-any-file: 'cuda_bindings/**'
10+
- any-glob-to-any-file:
11+
- 'cuda_bindings/**'
12+
- 'samples/cuda_bindings/**'
1113

1214
cuda.core:
1315
- changed-files:
14-
- any-glob-to-any-file: 'cuda_core/**'
16+
- any-glob-to-any-file:
17+
- 'cuda_core/**'
18+
- 'samples/cuda_core/**'
1519

1620
cuda.pathfinder:
1721
- changed-files:

‎.github/workflows/ci-pixi-lockfile-freshness-check.yml‎

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@
66
# its bytes are not what the pinned pixi version generates. Pull requests also
77
# check stale workspaces at the base SHA so diagnostics can distinguish changes
88
# introduced by the PR from maintenance already needed on the base branch.
9-
# Attribution changes remediation only; the aggregate job remains strict for
10-
# every stale classification. See #2298 and #2926.
9+
# Attribution changes remediation only. A temporary, exact-match exception
10+
# covers Pixi 0.73.0 pruning the samples environment's local source references;
11+
# every other stale classification remains strict. See #2298 and #2926.
1112

1213
name: "CI: pixi lockfile freshness check"
1314

@@ -28,6 +29,8 @@ on:
2829
- "**/pixi.lock"
2930
- "**/pyproject.toml"
3031
- "ci/tools/classify_pixi_lockfile_freshness.py"
32+
- "ci/tools/check_pixi_samples_source_pruning.py"
33+
- "ci/tools/tests/test_check_pixi_samples_source_pruning.py"
3134
- "ci/tools/list_pixi_workspaces.py"
3235
- "ci/pixi-version.env"
3336
- ".github/actions/setup-pixi/action.yml"
@@ -195,7 +198,35 @@ jobs:
195198
continue
196199
fi
197200
201+
known_samples_pruning=0
202+
if [[ "${manifest}" == "cuda_core" ]]; then
203+
defect_status=0
204+
python3 ci/tools/check_pixi_samples_source_pruning.py \
205+
--original-blob "${candidate_original}" \
206+
--lockfile "${lockfile}" \
207+
--manifest-path "${manifest}/pixi.toml" \
208+
--pixi-version "${PIXI_VERSION}" \
209+
--check-status "${check_status}" \
210+
|| defect_status=$?
211+
if ((defect_status == 0)); then
212+
known_samples_pruning=1
213+
elif ((defect_status != 1)); then
214+
echo "::error::Could not determine whether '${lockfile}' matches the known Pixi samples-source pruning defect. Resolve the detector error above and rerun."
215+
echo "| \`${manifest}\` | Operational error: known-defect detector failed. |" >> "${GITHUB_STEP_SUMMARY}"
216+
failed=1
217+
echo "::endgroup::"
218+
continue
219+
fi
220+
fi
221+
198222
if [[ "${EVENT_NAME}" != "pull_request" ]]; then
223+
if ((known_samples_pruning != 0)); then
224+
echo "::warning title=Known Pixi samples lockfile bug::Pixi ${PIXI_VERSION} removed only the nine samples local-source references. Keeping the committed references; all other lockfile changes remain strict. Remove this temporary exception once the upstream fix is released and verified."
225+
echo "| \`${manifest}\` | Known Pixi samples-source pruning bug: warning only; committed local-source references retained. |" >> "${GITHUB_STEP_SUMMARY}"
226+
git cat-file blob "${candidate_original}" > "${lockfile}"
227+
echo "::endgroup::"
228+
continue
229+
fi
199230
echo "::error title=Stale Pixi lockfile::Lockfile '${lockfile}' is stale. Regenerate and commit it with pixi ${PIXI_VERSION}: pixi lock --manifest-path ${manifest}."
200231
echo "| \`${manifest}\` | Stale: regenerate and commit the lockfile. |" >> "${GITHUB_STEP_SUMMARY}"
201232
failed=1
@@ -256,6 +287,19 @@ jobs:
256287
python3 ci/tools/classify_pixi_lockfile_freshness.py "${classifier_args[@]}"
257288
)"
258289
290+
# Do not let a matching solver result hide PR-specific manifest
291+
# changes, even if they happen to produce the same lockfile blobs.
292+
if ((known_samples_pruning != 0)) && \
293+
[[ "${classification}" == "base-maintenance" ]] && \
294+
git diff --quiet "${BASE_SHA}" HEAD -- \
295+
':(glob)**/pixi.toml' ':(glob)**/pyproject.toml' ci/pixi-version.env; then
296+
echo "::warning title=Known inherited Pixi samples lockfile bug::Base and candidate reproduce the same nine-reference samples-source pruning defect, with no PR changes to lock inputs. Keeping the committed local-source references; all other lockfile changes remain strict. Remove this temporary exception once the upstream fix is released and verified."
297+
echo "| \`${manifest}\` | Known inherited Pixi samples-source pruning bug: warning only; no lock-input changes in this PR. Committed local-source references retained. |" >> "${GITHUB_STEP_SUMMARY}"
298+
git cat-file blob "${candidate_original}" > "${lockfile}"
299+
echo "::endgroup::"
300+
continue
301+
fi
302+
259303
case "${classification}" in
260304
pr-induced)
261305
echo "::error title=PR-induced Pixi lockfile change::Lockfile '${lockfile}' became stale in this PR. Regenerate and commit it with pixi ${PIXI_VERSION}: pixi lock --manifest-path ${manifest}."

‎.github/workflows/ci-pixi-source-test.yml‎

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,13 @@ defaults:
6262
shell: bash --noprofile --norc -xeuo pipefail {0}
6363

6464
env:
65-
# Install from the committed lockfile only. Covers nested `pixi run` calls
66-
# from root pixi.toml tasks; a stale lock must fail rather than being
67-
# refreshed in CI (#2298). Equivalent to `pixi run --locked`.
68-
PIXI_LOCKED: "true"
65+
# Temporarily bypass Pixi's workspace-wide freshness check: the unrelated
66+
# samples environment oscillates because excluded PyPI dependencies are
67+
# still checked. Frozen mode keeps the committed solution and source builds,
68+
# including nested `pixi run` calls. The separate freshness workflow rejects
69+
# every change except the exact known samples-source pruning defect.
70+
# Restore PIXI_LOCKED after the upstream fix is released and verified.
71+
PIXI_FROZEN: "true"
6972

7073
jobs:
7174
# ── PR guard: CPU-only build + import + placement smoke ──

‎.github/workflows/ci.yml‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -631,6 +631,9 @@ jobs:
631631
permissions:
632632
contents: read
633633
steps:
634+
- name: Enable Git symlinks (Windows, must precede checkout)
635+
run: git config --global core.symlinks true
636+
634637
- name: Checkout repository
635638
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
636639
with:

‎.github/workflows/coverage.yml‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,9 @@ jobs:
232232
CUDA_PYTHON_COVERAGE: "1"
233233
CUDA_VER: ${{ needs.coverage-vars.outputs.CUDA_VER }}
234234
steps:
235+
- name: Enable Git symlinks (Windows, must precede checkout)
236+
run: git config --global core.symlinks true
237+
235238
- name: Checkout ${{ github.event.repository.name }}
236239
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
237240
with:
@@ -348,6 +351,9 @@ jobs:
348351
run:
349352
shell: bash --noprofile --norc -xeuo pipefail {0}
350353
steps:
354+
- name: Enable Git symlinks (Windows, must precede checkout)
355+
run: git config --global core.symlinks true
356+
351357
- name: Checkout ${{ github.event.repository.name }}
352358
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
353359
with:

‎.github/workflows/pre-commit.yml‎

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@ on:
99
types: [opened, reopened, synchronize]
1010
push:
1111
# PR events cover draft and fork PRs without also checking copy-pr-bot's
12-
# pull-request/N mirrors. Only main needs a push check.
12+
# pull-request/N mirrors. Only the default branch needs a push check, and
13+
# it is the only ref that refreshes the saved cache (see the save step).
1314
branches:
1415
- "main"
16+
- "ctk-next"
1517
workflow_dispatch: {}
1618

1719
concurrency:
@@ -42,6 +44,8 @@ jobs:
4244
# Link checks have their own Linux workflow. The installation reminder
4345
# is for developer machines; CI does not install a Git commit hook.
4446
SKIP: lychee,check-precommit-installed
47+
# Minor version used by setup-python and as the cache restore-key prefix.
48+
PYTHON_VERSION: "3.14"
4549
steps:
4650
- name: Checkout repository
4751
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
@@ -53,19 +57,40 @@ jobs:
5357
id: python
5458
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
5559
with:
56-
python-version: '3.14'
60+
python-version: ${{ env.PYTHON_VERSION }}
5761

5862
- name: Set pre-commit cache location
5963
run: echo "PRE_COMMIT_HOME=${RUNNER_TEMP}/pre-commit" >> "${GITHUB_ENV}"
6064

61-
- name: Cache pre-commit environments
62-
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
65+
- name: Restore pre-commit cache
66+
id: precommit-cache
67+
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
6368
with:
6469
path: ${{ env.PRE_COMMIT_HOME }}
65-
key: pre-commit-${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{ hashFiles('.pre-commit-config.yaml') }}
70+
# The full patch version keeps the key exact, so a patch bump misses
71+
# and re-saves. The minor-version restore-key still partially hits on
72+
# that bump, so hooks rebuild from a warm cache instead of cold. The
73+
# prefix stops at the minor with no trailing separator, so it is a
74+
# prefix of "py3.14.<patch>-..." regardless of the separator that
75+
# follows the resolved version.
76+
key: pre-commit-${{ runner.os }}-py${{ steps.python.outputs.python-version }}-${{ hashFiles('.pre-commit-config.yaml') }}
77+
restore-keys: |
78+
pre-commit-${{ runner.os }}-py${{ env.PYTHON_VERSION }}
6679
6780
- name: Install pre-commit
6881
run: python -m pip install --upgrade pip pre-commit
6982

7083
- name: Run pre-commit
7184
run: pre-commit run --all-files --show-diff-on-failure
85+
86+
- name: Save pre-commit cache
87+
# Only the default branch saves, so per-PR merge refs don't store their
88+
# own duplicate copies. !cancelled() keeps a push that fails lint from
89+
# discarding the valid hook environments. Skipping on an exact key hit
90+
# avoids re-saving identical content; a patch-bump partial hit still
91+
# saves because cache-hit is only 'true' on an exact match.
92+
if: ${{ !cancelled() && github.ref_name == github.event.repository.default_branch && steps.precommit-cache.outputs.cache-hit != 'true' }}
93+
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
94+
with:
95+
path: ${{ env.PRE_COMMIT_HOME }}
96+
key: pre-commit-${{ runner.os }}-py${{ steps.python.outputs.python-version }}-${{ hashFiles('.pre-commit-config.yaml') }}

‎.github/workflows/test-sdist-linux.yml‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ jobs:
6868
6969
- name: Download cuda.pathfinder wheel
7070
if: ${{ env.BUILD_PATHFINDER != 'true' && (env.BUILD_BINDINGS == 'true' || env.BUILD_CORE == 'true') }}
71-
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
71+
uses: ./.github/actions/download-artifact-retry
7272
with:
7373
name: cuda-pathfinder-wheel
7474
path: cuda_pathfinder/dist
@@ -131,7 +131,7 @@ jobs:
131131
132132
- name: Download cuda.bindings wheel
133133
if: ${{ env.BUILD_BINDINGS != 'true' && env.BUILD_CORE == 'true' }}
134-
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
134+
uses: ./.github/actions/download-artifact-retry
135135
with:
136136
name: cuda-bindings-python312-cuda${{ inputs.cuda-version }}-${{ inputs.host-platform }}-${{ github.sha }}
137137
path: cuda_bindings/dist

‎.github/workflows/test-sdist-windows.yml‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ jobs:
8181
8282
- name: Download cuda.pathfinder wheel
8383
if: ${{ env.BUILD_PATHFINDER != 'true' && (env.BUILD_BINDINGS == 'true' || env.BUILD_CORE == 'true') }}
84-
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
84+
uses: ./.github/actions/download-artifact-retry
8585
with:
8686
name: cuda-pathfinder-wheel
8787
path: cuda_pathfinder/dist
@@ -122,7 +122,7 @@ jobs:
122122
123123
- name: Download cuda.bindings wheel
124124
if: ${{ env.BUILD_BINDINGS != 'true' && env.BUILD_CORE == 'true' }}
125-
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
125+
uses: ./.github/actions/download-artifact-retry
126126
with:
127127
name: cuda-bindings-python312-cuda${{ inputs.cuda-version }}-${{ inputs.host-platform }}-${{ github.sha }}
128128
path: cuda_bindings/dist

‎.github/workflows/test-wheel-linux.yml‎

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ jobs:
177177

178178
- name: Download cuda-pathfinder build artifacts
179179
if: ${{ env.TEST_PATHFINDER == 'true' || env.TEST_BINDINGS == 'true' || env.TEST_CORE == 'true' || env.TEST_PYTHON == 'true' }}
180-
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
180+
uses: NVIDIA/cuda-python/.github/actions/download-artifact-retry@f20d661666a5c92b757748ca237d3592ac3e942f # introduced in #3037
181181
with:
182182
name: cuda-pathfinder-wheel
183183
path: ./cuda_pathfinder
@@ -186,7 +186,7 @@ jobs:
186186

187187
- name: Download cuda-python build artifacts
188188
if: ${{ env.TEST_PYTHON == 'true' && env.BINDINGS_SOURCE == 'main' }}
189-
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
189+
uses: NVIDIA/cuda-python/.github/actions/download-artifact-retry@f20d661666a5c92b757748ca237d3592ac3e942f # introduced in #3037
190190
with:
191191
name: cuda-python-wheel
192192
path: .
@@ -196,7 +196,7 @@ jobs:
196196
- name: Download cuda.bindings build artifacts
197197
if: ${{ (env.TEST_BINDINGS == 'true' || env.TEST_CORE == 'true' || env.TEST_PYTHON == 'true') &&
198198
env.BINDINGS_SOURCE == 'main' }}
199-
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
199+
uses: NVIDIA/cuda-python/.github/actions/download-artifact-retry@f20d661666a5c92b757748ca237d3592ac3e942f # introduced in #3037
200200
with:
201201
name: ${{ env.CUDA_BINDINGS_ARTIFACT_NAME }}
202202
path: ${{ env.CUDA_BINDINGS_ARTIFACTS_DIR }}
@@ -267,7 +267,7 @@ jobs:
267267
268268
- name: Download cuda.bindings Cython tests
269269
if: ${{ env.TEST_BINDINGS == 'true' && env.SKIP_CYTHON_TEST == '0' }}
270-
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
270+
uses: NVIDIA/cuda-python/.github/actions/download-artifact-retry@f20d661666a5c92b757748ca237d3592ac3e942f # introduced in #3037
271271
with:
272272
name: ${{ env.CUDA_BINDINGS_ARTIFACT_NAME }}-tests
273273
path: ${{ env.CUDA_BINDINGS_CYTHON_TESTS_DIR }}
@@ -282,7 +282,7 @@ jobs:
282282
283283
- name: Download cuda.core build artifacts
284284
if: ${{ env.TEST_CORE == 'true' }}
285-
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
285+
uses: NVIDIA/cuda-python/.github/actions/download-artifact-retry@f20d661666a5c92b757748ca237d3592ac3e942f # introduced in #3037
286286
with:
287287
name: ${{ env.CUDA_CORE_ARTIFACT_NAME }}
288288
path: ${{ env.CUDA_CORE_ARTIFACTS_DIR }}
@@ -297,7 +297,7 @@ jobs:
297297
298298
- name: Download cuda.core Cython tests
299299
if: ${{ env.TEST_CORE == 'true' && env.SKIP_CYTHON_TEST == '0' }}
300-
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
300+
uses: NVIDIA/cuda-python/.github/actions/download-artifact-retry@f20d661666a5c92b757748ca237d3592ac3e942f # introduced in #3037
301301
with:
302302
name: ${{ env.CUDA_CORE_ARTIFACT_NAME }}-tests
303303
path: ${{ env.CUDA_CORE_CYTHON_TESTS_DIR }}
@@ -312,7 +312,7 @@ jobs:
312312
313313
- name: Download cuda.core test binaries
314314
if: ${{ env.TEST_CORE == 'true' }}
315-
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
315+
uses: NVIDIA/cuda-python/.github/actions/download-artifact-retry@f20d661666a5c92b757748ca237d3592ac3e942f # introduced in #3037
316316
with:
317317
name: ${{ env.CUDA_CORE_ARTIFACT_NAME }}-test-binaries
318318
path: ${{ env.CUDA_CORE_TEST_BINARIES_DIR }}

0 commit comments

Comments
 (0)