Skip to content

Commit 40632ad

Browse files
authored
Merge branch 'main' into nvbug6084457
2 parents fb740c9 + 46818dc commit 40632ad

File tree

24 files changed

+1646
-1307
lines changed

24 files changed

+1646
-1307
lines changed

.github/actionlint.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
#
3+
# SPDX-License-Identifier: Apache-2.0
4+
5+
# Self-hosted runner labels used in CI workflows.
6+
# Without this config, actionlint rejects non-GitHub-hosted labels.
7+
self-hosted-runner:
8+
labels:
9+
- linux-amd64-cpu8

.github/labeler.yml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
#
3+
# SPDX-License-Identifier: Apache-2.0
4+
5+
# Configuration for https://github.com/actions/labeler
6+
# Auto-applies labels based on which files a PR changes.
7+
8+
cuda.bindings:
9+
- changed-files:
10+
- any-glob-to-any-file: 'cuda_bindings/**'
11+
12+
cuda.core:
13+
- changed-files:
14+
- any-glob-to-any-file: 'cuda_core/**'
15+
16+
cuda.pathfinder:
17+
- changed-files:
18+
- any-glob-to-any-file: 'cuda_pathfinder/**'
19+
20+
CI/CD:
21+
- changed-files:
22+
- any-glob-to-any-file:
23+
- '.github/**'
24+
- 'ci/**'

.github/workflows/ci.yml

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,37 @@ jobs:
286286
cuda-version: ${{ needs.ci-vars.outputs.CUDA_BUILD_VER }}
287287
prev-cuda-version: ${{ needs.ci-vars.outputs.CUDA_PREV_BUILD_VER }}
288288

289+
# NOTE: test-sdist jobs are split by platform (mirroring build-* and test-wheel-*)
290+
# so platform-specific sources (e.g. cuda_bindings/*_windows.pyx selected by
291+
# build_hooks.py) are exercised on their target OS. Keep these job definitions
292+
# textually identical except for:
293+
# - host-platform value
294+
# - uses: (test-sdist-linux.yml vs test-sdist-windows.yml)
295+
test-sdist-linux:
296+
needs:
297+
- ci-vars
298+
- should-skip
299+
name: Test sdist linux-64
300+
if: ${{ github.repository_owner == 'nvidia' && !fromJSON(needs.should-skip.outputs.skip) && !fromJSON(needs.should-skip.outputs.doc-only) }}
301+
secrets: inherit
302+
uses: ./.github/workflows/test-sdist-linux.yml
303+
with:
304+
host-platform: linux-64
305+
cuda-version: ${{ needs.ci-vars.outputs.CUDA_BUILD_VER }}
306+
307+
# See test-sdist-linux for why sdist test jobs are split by platform.
308+
test-sdist-windows:
309+
needs:
310+
- ci-vars
311+
- should-skip
312+
name: Test sdist win-64
313+
if: ${{ github.repository_owner == 'nvidia' && !fromJSON(needs.should-skip.outputs.skip) && !fromJSON(needs.should-skip.outputs.doc-only) }}
314+
secrets: inherit
315+
uses: ./.github/workflows/test-sdist-windows.yml
316+
with:
317+
host-platform: win-64
318+
cuda-version: ${{ needs.ci-vars.outputs.CUDA_BUILD_VER }}
319+
289320
# NOTE: Test jobs are split by platform for the same reason as build jobs (see
290321
# build-linux-64). Keep these job definitions textually identical except for:
291322
# - host-platform value
@@ -388,6 +419,8 @@ jobs:
388419
needs:
389420
- should-skip
390421
- detect-changes
422+
- test-sdist-linux
423+
- test-sdist-windows
391424
- test-linux-64
392425
- test-linux-aarch64
393426
- test-windows
@@ -427,6 +460,12 @@ jobs:
427460
if ${{ needs.doc.result == 'cancelled' || needs.doc.result == 'failure' }}; then
428461
exit 1
429462
fi
463+
if ${{ needs.test-sdist-linux.result == 'cancelled' ||
464+
needs.test-sdist-linux.result == 'failure' ||
465+
needs.test-sdist-windows.result == 'cancelled' ||
466+
needs.test-sdist-windows.result == 'failure' }}; then
467+
exit 1
468+
fi
430469
if [[ "${doc_only}" != "true" ]]; then
431470
if ${{ needs.test-linux-64.result == 'cancelled' ||
432471
needs.test-linux-64.result == 'failure' ||
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
#
3+
# SPDX-License-Identifier: Apache-2.0
4+
5+
name: "CI: Auto-label PRs by path"
6+
7+
on:
8+
pull_request_target:
9+
types:
10+
- opened
11+
- synchronize
12+
13+
jobs:
14+
auto-label:
15+
name: Auto-label by changed paths
16+
if: github.repository_owner == 'NVIDIA'
17+
runs-on: ubuntu-latest
18+
permissions:
19+
contents: read
20+
pull-requests: write
21+
steps:
22+
- name: Apply labels
23+
uses: actions/labeler@634933edcd8ababfe52f92936142cc22ac488b1b # v6.0.1

.github/workflows/restricted-paths-guard.yml

Lines changed: 54 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,13 @@ jobs:
1919
if: github.repository_owner == 'NVIDIA'
2020
runs-on: ubuntu-latest
2121
permissions:
22+
contents: write # needed for collaborator permission check
2223
pull-requests: write
2324
steps:
2425
- name: Inspect PR author signals for restricted paths
2526
env:
26-
# PR metadata inputs
27-
AUTHOR_ASSOCIATION: ${{ github.event.pull_request.author_association || 'NONE' }}
27+
# PR metadata inputs (author_association from event payload is
28+
# unreliable for fork PRs, so we query the collaborator API directly)
2829
PR_AUTHOR: ${{ github.event.pull_request.user.login }}
2930
PR_NUMBER: ${{ github.event.pull_request.number }}
3031
PR_URL: ${{ github.event.pull_request.html_url }}
@@ -38,6 +39,9 @@ jobs:
3839
run: |
3940
set -euo pipefail
4041
42+
COLLABORATOR_PERMISSION="not checked"
43+
COLLABORATOR_PERMISSION_API_ERROR=""
44+
4145
if ! MATCHING_RESTRICTED_PATHS=$(
4246
gh api \
4347
--paginate \
@@ -63,7 +67,7 @@ jobs:
6367
echo ""
6468
echo "- **Error**: Failed to inspect the PR file list."
6569
echo "- **Author**: $PR_AUTHOR"
66-
echo "- **Author association**: $AUTHOR_ASSOCIATION"
70+
echo "- **Collaborator permission**: $COLLABORATOR_PERMISSION"
6771
echo ""
6872
echo "Please update the PR at: $PR_URL"
6973
} >> "$GITHUB_STEP_SUMMARY"
@@ -83,7 +87,7 @@ jobs:
8387
echo ""
8488
echo "- **Error**: Failed to inspect the current PR labels."
8589
echo "- **Author**: $PR_AUTHOR"
86-
echo "- **Author association**: $AUTHOR_ASSOCIATION"
90+
echo "- **Collaborator permission**: $COLLABORATOR_PERMISSION"
8791
echo ""
8892
echo "Please update the PR at: $PR_URL"
8993
} >> "$GITHUB_STEP_SUMMARY"
@@ -102,16 +106,56 @@ jobs:
102106
echo '```'
103107
}
104108
109+
write_collaborator_permission_api_error() {
110+
echo "- **Collaborator permission API error**:"
111+
echo '```text'
112+
printf '%s\n' "$COLLABORATOR_PERMISSION_API_ERROR"
113+
echo '```'
114+
}
115+
105116
HAS_TRUSTED_SIGNAL=false
106117
LABEL_ACTION="not needed (no restricted paths)"
107118
TRUSTED_SIGNALS="(none)"
108119
109120
if [ "$TOUCHES_RESTRICTED_PATHS" = "true" ]; then
110-
case "$AUTHOR_ASSOCIATION" in
111-
COLLABORATOR|MEMBER|OWNER)
121+
# Distinguish a legitimate 404 "not a collaborator" response from
122+
# actual API failures. The former is an expected untrusted case;
123+
# the latter fails the workflow so it can be rerun later.
124+
if COLLABORATOR_PERMISSION_RESPONSE=$(
125+
gh api "repos/$REPO/collaborators/$PR_AUTHOR/permission" \
126+
--jq '.permission' 2>&1
127+
); then
128+
COLLABORATOR_PERMISSION="$COLLABORATOR_PERMISSION_RESPONSE"
129+
elif [[ "$COLLABORATOR_PERMISSION_RESPONSE" == *"(HTTP 404)"* ]]; then
130+
COLLABORATOR_PERMISSION="none"
131+
else
132+
COLLABORATOR_PERMISSION="unknown"
133+
COLLABORATOR_PERMISSION_API_ERROR="$COLLABORATOR_PERMISSION_RESPONSE"
134+
echo "::error::Failed to inspect collaborator permission for $PR_AUTHOR."
135+
{
136+
echo "## Restricted Paths Guard Failed"
137+
echo ""
138+
echo "- **Error**: Failed to inspect collaborator permission."
139+
echo "- **Author**: $PR_AUTHOR"
140+
echo "- **Collaborator permission**: $COLLABORATOR_PERMISSION"
141+
echo ""
142+
write_matching_restricted_paths
143+
echo ""
144+
write_collaborator_permission_api_error
145+
echo ""
146+
echo "Please retry this workflow. If the failure persists, inspect the collaborator permission API error above."
147+
} >> "$GITHUB_STEP_SUMMARY"
148+
exit 1
149+
fi
150+
151+
case "$COLLABORATOR_PERMISSION" in
152+
admin|maintain|write)
112153
HAS_TRUSTED_SIGNAL=true
113-
LABEL_ACTION="not needed (author association is a trusted signal)"
114-
TRUSTED_SIGNALS="author_association:$AUTHOR_ASSOCIATION"
154+
LABEL_ACTION="not needed (collaborator permission is a trusted signal)"
155+
TRUSTED_SIGNALS="collaborator_permission:$COLLABORATOR_PERMISSION"
156+
;;
157+
*)
158+
# triage, read, or none: not a trusted signal
115159
;;
116160
esac
117161
fi
@@ -136,7 +180,7 @@ jobs:
136180
echo ""
137181
echo "- **Error**: Failed to add the \`$REVIEW_LABEL\` label."
138182
echo "- **Author**: $PR_AUTHOR"
139-
echo "- **Author association**: $AUTHOR_ASSOCIATION"
183+
echo "- **Collaborator permission**: $COLLABORATOR_PERMISSION"
140184
echo ""
141185
write_matching_restricted_paths
142186
echo ""
@@ -154,7 +198,7 @@ jobs:
154198
echo "## Restricted Paths Guard Completed"
155199
echo ""
156200
echo "- **Author**: $PR_AUTHOR"
157-
echo "- **Author association**: $AUTHOR_ASSOCIATION"
201+
echo "- **Collaborator permission**: $COLLABORATOR_PERMISSION"
158202
echo "- **Touches restricted paths**: $TOUCHES_RESTRICTED_PATHS"
159203
echo "- **Restricted paths**: \`cuda_bindings/\`, \`cuda_python/\`"
160204
echo "- **Trusted signals**: $TRUSTED_SIGNALS"
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
#
3+
# SPDX-License-Identifier: Apache-2.0
4+
5+
on:
6+
workflow_call:
7+
inputs:
8+
host-platform:
9+
required: true
10+
type: string
11+
cuda-version:
12+
required: true
13+
type: string
14+
15+
defaults:
16+
run:
17+
shell: bash --noprofile --norc -xeuo pipefail {0}
18+
19+
permissions:
20+
contents: read # This is required for actions/checkout
21+
22+
jobs:
23+
test-sdist:
24+
name: Test sdist builds
25+
runs-on: linux-amd64-cpu8
26+
steps:
27+
- name: Checkout ${{ github.event.repository.name }}
28+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
29+
with:
30+
fetch-depth: 0
31+
32+
- name: Set up Python
33+
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
34+
with:
35+
python-version: "3.12"
36+
37+
- name: Install build tools
38+
run: pip install build
39+
40+
# Pure Python packages -- no CTK needed.
41+
- name: Build cuda.pathfinder sdist and wheel-from-sdist
42+
run: |
43+
python -m build --sdist cuda_pathfinder/
44+
pip wheel --no-deps --wheel-dir cuda_pathfinder/dist cuda_pathfinder/dist/*.tar.gz
45+
46+
- name: Build cuda-python sdist and wheel-from-sdist
47+
run: |
48+
python -m build --sdist cuda_python/
49+
pip wheel --no-deps --wheel-dir cuda_python/dist cuda_python/dist/*.tar.gz
50+
51+
# Cython packages need CTK + sccache.
52+
# The env vars ACTIONS_CACHE_SERVICE_V2, ACTIONS_RESULTS_URL, and ACTIONS_RUNTIME_TOKEN
53+
# are exposed by this action.
54+
- name: Enable sccache
55+
uses: mozilla-actions/sccache-action@7d986dd989559c6ecdb630a3fd2557667be217ad # 0.0.9
56+
with:
57+
disable_annotations: 'true'
58+
59+
# xref: https://github.com/orgs/community/discussions/42856#discussioncomment-7678867
60+
- name: Adding additional GHA cache-related env vars
61+
uses: actions/github-script@v8
62+
with:
63+
script: |
64+
core.exportVariable('ACTIONS_CACHE_URL', process.env['ACTIONS_CACHE_URL'])
65+
core.exportVariable('ACTIONS_RUNTIME_URL', process.env['ACTIONS_RUNTIME_URL'])
66+
67+
- name: Setup proxy cache
68+
uses: nv-gha-runners/setup-proxy-cache@main
69+
continue-on-error: true
70+
with:
71+
enable-apt: true
72+
73+
- name: Set up mini CTK
74+
uses: ./.github/actions/fetch_ctk
75+
continue-on-error: false
76+
with:
77+
host-platform: ${{ inputs.host-platform }}
78+
cuda-version: ${{ inputs.cuda-version }}
79+
80+
# cuda_bindings/setup.py parses CUDA headers at import time, so CUDA_PATH
81+
# (set by fetch_ctk) must be available for both sdist and wheel builds.
82+
- name: Build cuda.bindings sdist and wheel-from-sdist
83+
run: |
84+
export CUDA_PYTHON_PARALLEL_LEVEL=$(nproc)
85+
export CC="sccache cc"
86+
export CXX="sccache c++"
87+
export PIP_FIND_LINKS="$(pwd)/cuda_pathfinder/dist"
88+
python -m build --sdist cuda_bindings/
89+
pip wheel --no-deps --wheel-dir cuda_bindings/dist cuda_bindings/dist/*.tar.gz
90+
91+
# cuda_core sdist delegates to setuptools (no CTK needed), but
92+
# wheel-from-sdist needs CTK and cuda-bindings (dynamic build dep via
93+
# get_requires_for_build_wheel in build_hooks.py).
94+
- name: Build cuda.core sdist and wheel-from-sdist
95+
run: |
96+
export CUDA_PYTHON_PARALLEL_LEVEL=$(nproc)
97+
export CUDA_CORE_BUILD_MAJOR="$(echo '${{ inputs.cuda-version }}' | cut -d. -f1)"
98+
export CC="sccache cc"
99+
export CXX="sccache c++"
100+
export PIP_FIND_LINKS="$(pwd)/cuda_bindings/dist $(pwd)/cuda_pathfinder/dist"
101+
python -m build --sdist cuda_core/
102+
pip wheel --no-deps --wheel-dir cuda_core/dist cuda_core/dist/*.tar.gz
103+
104+
- name: Show sccache stats
105+
if: always()
106+
run: sccache --show-stats

0 commit comments

Comments
 (0)