Skip to content

Commit 33efe60

Browse files
rwgkleofang
andauthored
[no-ci] CI: Add restricted-paths-guard.yml (#1878)
* CI: add PR author organization check Report restricted-path author gating as its own workflow so contributors see the organization requirement as soon as a PR touches cuda_bindings/ or cuda_python/. Made-with: Cursor * CI: fix PR author org check file lookup Keep the lightweight PR check runnable on GitHub-hosted runners by avoiding the unsupported gh api --slurp --jq combination when scanning changed files. Made-with: Cursor * XXX DUMMY CHANGE XXX under cuda_bindings/ * CI: show matched restricted paths in PR check Include the exact restricted-path matches in the job summary so contributors and reviewers can see what triggered the author organization check. Made-with: Cursor * CI: triage inconclusive PR author org checks Query NVIDIA org membership directly for restricted-path PRs so the workflow can distinguish members, non-members, and inconclusive cases, label PRs that need manual review, and show the matched files. Keep the trigger on pull_request temporarily so the new check can be exercised before switching back to pull_request_target. Made-with: Cursor * Revert "CI: triage inconclusive PR author org checks" This reverts commit 42ba3f8. * CI: allow collaborators in PR author org check Treat repository collaborators as trusted for restricted-path changes so the workflow blocks only authors with no collaborator, member, or owner association. Made-with: Cursor * CI: label PRs without trusted author signals Use OWNER and MEMBER associations plus public NVIDIA membership as true-positive signals, and add a review label instead of failing when the workflow cannot confirm the author automatically. Made-with: Cursor * Revert "CI: label PRs without trusted author signals" This reverts commit 9dcf7b1. * CI: use checked-in PR author allowlist Replace the public-membership probe with a checked-in allowlist so restricted-path PRs can still get a known true positive during rollout while labeling authors that need manual review. Made-with: Cursor * CI: rename PR author trusted signal wording Replace the remaining "true positive" terminology with "trusted signal" so the workflow summary and implementation language match the current manual-review design. Made-with: Cursor * CI: clarify renamed restricted path matches Show both the previous and current path in the PR author check summary so rename-triggered matches are understandable during manual review. Made-with: Cursor * CI: trust collaborators in PR author check Remove the temporary checked-in allowlist and treat COLLABORATOR as a trusted author signal again so the workflow matches the team policy. Made-with: Cursor * CI: shorten restricted paths guard names Use shorter workflow and job names so the GitHub checks list is easier to scan while keeping the manual-review intent clear. Made-with: Cursor * CI: rename restricted paths review label Use a maintainer-facing label name that better describes the follow-up action required before merging inconclusive restricted-path changes. Made-with: Cursor * CI: rename restricted paths guard workflow Use workflow, job, and summary names that match the current restricted-paths guard behavior and read more clearly in the GitHub checks UI. Made-with: Cursor * Resolve TODO before merging: - undo cuda_bindings/pyproject.toml # XXX DUMMY CHANGE XXX - change trigger from pull_request (useful only for testing this PR) to pull_request_target * CI: harden restricted paths guard label handling Fetch live PR labels to avoid stale event data, use pull-request label edits, and keep the restricted-paths review label in place until a maintainer removes it manually. Made-with: Cursor * Revert "Resolve TODO before merging:" This reverts commit 02edff4. * Resolve TODO before merging: - undo cuda_bindings/pyproject.toml # XXX DUMMY CHANGE XXX - change trigger from pull_request (useful only for testing this PR) to pull_request_target * Fix Copyright year Co-authored-by: Leo Fang <leof@nvidia.com> --------- Co-authored-by: Leo Fang <leof@nvidia.com>
1 parent eb6a33a commit 33efe60

File tree

1 file changed

+173
-0
lines changed

1 file changed

+173
-0
lines changed
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
name: "CI: Restricted Paths Guard"
5+
6+
on:
7+
# Run on drafts too so maintainers get early awareness on WIP PRs.
8+
# Label updates on fork PRs require pull_request_target permissions.
9+
pull_request_target:
10+
types:
11+
- opened
12+
- synchronize
13+
- reopened
14+
- ready_for_review
15+
16+
jobs:
17+
restricted-paths-guard:
18+
name: Apply review label if needed
19+
if: github.repository_owner == 'NVIDIA'
20+
runs-on: ubuntu-latest
21+
permissions:
22+
pull-requests: write
23+
steps:
24+
- name: Inspect PR author signals for restricted paths
25+
env:
26+
# PR metadata inputs
27+
AUTHOR_ASSOCIATION: ${{ github.event.pull_request.author_association || 'NONE' }}
28+
PR_AUTHOR: ${{ github.event.pull_request.user.login }}
29+
PR_NUMBER: ${{ github.event.pull_request.number }}
30+
PR_URL: ${{ github.event.pull_request.html_url }}
31+
32+
# Workflow policy inputs
33+
REVIEW_LABEL: Needs-Restricted-Paths-Review
34+
35+
# API request context/auth
36+
GH_TOKEN: ${{ github.token }}
37+
REPO: ${{ github.repository }}
38+
run: |
39+
set -euo pipefail
40+
41+
if ! MATCHING_RESTRICTED_PATHS=$(
42+
gh api \
43+
--paginate \
44+
--jq '
45+
.[]
46+
| select(
47+
(.filename | startswith("cuda_bindings/"))
48+
or ((.previous_filename // "") | startswith("cuda_bindings/"))
49+
or (.filename | startswith("cuda_python/"))
50+
or ((.previous_filename // "") | startswith("cuda_python/"))
51+
)
52+
| if (.previous_filename // "") != "" then
53+
"\(.previous_filename) -> \(.filename)"
54+
else
55+
.filename
56+
end
57+
' \
58+
"repos/$REPO/pulls/$PR_NUMBER/files"
59+
); then
60+
echo "::error::Failed to inspect the PR file list."
61+
{
62+
echo "## Restricted Paths Guard Failed"
63+
echo ""
64+
echo "- **Error**: Failed to inspect the PR file list."
65+
echo "- **Author**: $PR_AUTHOR"
66+
echo "- **Author association**: $AUTHOR_ASSOCIATION"
67+
echo ""
68+
echo "Please update the PR at: $PR_URL"
69+
} >> "$GITHUB_STEP_SUMMARY"
70+
exit 1
71+
fi
72+
73+
# Fetch live PR labels to avoid stale event payload (race condition
74+
# when labels are changed shortly before the workflow runs).
75+
if ! LIVE_LABELS=$(
76+
gh pr view "${PR_NUMBER}" --repo "${REPO}" \
77+
--json labels \
78+
--jq '[.labels[].name]'
79+
); then
80+
echo "::error::Failed to inspect the current PR labels."
81+
{
82+
echo "## Restricted Paths Guard Failed"
83+
echo ""
84+
echo "- **Error**: Failed to inspect the current PR labels."
85+
echo "- **Author**: $PR_AUTHOR"
86+
echo "- **Author association**: $AUTHOR_ASSOCIATION"
87+
echo ""
88+
echo "Please update the PR at: $PR_URL"
89+
} >> "$GITHUB_STEP_SUMMARY"
90+
exit 1
91+
fi
92+
93+
TOUCHES_RESTRICTED_PATHS=false
94+
if [ -n "$MATCHING_RESTRICTED_PATHS" ]; then
95+
TOUCHES_RESTRICTED_PATHS=true
96+
fi
97+
98+
write_matching_restricted_paths() {
99+
echo "- **Matched restricted paths**:"
100+
echo '```text'
101+
printf '%s\n' "$MATCHING_RESTRICTED_PATHS"
102+
echo '```'
103+
}
104+
105+
HAS_TRUSTED_SIGNAL=false
106+
LABEL_ACTION="not needed (no restricted paths)"
107+
TRUSTED_SIGNALS="(none)"
108+
109+
if [ "$TOUCHES_RESTRICTED_PATHS" = "true" ]; then
110+
case "$AUTHOR_ASSOCIATION" in
111+
COLLABORATOR|MEMBER|OWNER)
112+
HAS_TRUSTED_SIGNAL=true
113+
LABEL_ACTION="not needed (author association is a trusted signal)"
114+
TRUSTED_SIGNALS="author_association:$AUTHOR_ASSOCIATION"
115+
;;
116+
esac
117+
fi
118+
119+
NEEDS_REVIEW_LABEL=false
120+
if [ "$TOUCHES_RESTRICTED_PATHS" = "true" ] && [ "$HAS_TRUSTED_SIGNAL" = "false" ]; then
121+
NEEDS_REVIEW_LABEL=true
122+
fi
123+
124+
LABEL_ALREADY_PRESENT=false
125+
if jq -e --arg label "$REVIEW_LABEL" '.[] == $label' <<<"$LIVE_LABELS" >/dev/null; then
126+
LABEL_ALREADY_PRESENT=true
127+
fi
128+
129+
if [ "$NEEDS_REVIEW_LABEL" = "true" ]; then
130+
if [ "$LABEL_ALREADY_PRESENT" = "true" ]; then
131+
LABEL_ACTION="already present"
132+
elif ! gh pr edit "$PR_NUMBER" --repo "$REPO" --add-label "$REVIEW_LABEL"; then
133+
echo "::error::Failed to add the $REVIEW_LABEL label."
134+
{
135+
echo "## Restricted Paths Guard Failed"
136+
echo ""
137+
echo "- **Error**: Failed to add the \`$REVIEW_LABEL\` label."
138+
echo "- **Author**: $PR_AUTHOR"
139+
echo "- **Author association**: $AUTHOR_ASSOCIATION"
140+
echo ""
141+
write_matching_restricted_paths
142+
echo ""
143+
echo "Please update the PR at: $PR_URL"
144+
} >> "$GITHUB_STEP_SUMMARY"
145+
exit 1
146+
else
147+
LABEL_ACTION="added"
148+
fi
149+
elif [ "$LABEL_ALREADY_PRESENT" = "true" ]; then
150+
LABEL_ACTION="left in place (manual removal required)"
151+
fi
152+
153+
{
154+
echo "## Restricted Paths Guard Completed"
155+
echo ""
156+
echo "- **Author**: $PR_AUTHOR"
157+
echo "- **Author association**: $AUTHOR_ASSOCIATION"
158+
echo "- **Touches restricted paths**: $TOUCHES_RESTRICTED_PATHS"
159+
echo "- **Restricted paths**: \`cuda_bindings/\`, \`cuda_python/\`"
160+
echo "- **Trusted signals**: $TRUSTED_SIGNALS"
161+
echo "- **Label action**: $LABEL_ACTION"
162+
if [ "$TOUCHES_RESTRICTED_PATHS" = "true" ]; then
163+
echo ""
164+
write_matching_restricted_paths
165+
fi
166+
if [ "$NEEDS_REVIEW_LABEL" = "true" ]; then
167+
echo ""
168+
echo "- **Manual follow-up**: No trusted signal was found, so \`$REVIEW_LABEL\` is required."
169+
elif [ "$LABEL_ALREADY_PRESENT" = "true" ]; then
170+
echo ""
171+
echo "- **Manual follow-up**: Existing \`$REVIEW_LABEL\` was left in place intentionally because this workflow does not inspect every commit. Remove it manually after reviewing the PR for restricted-paths policy compliance."
172+
fi
173+
} >> "$GITHUB_STEP_SUMMARY"

0 commit comments

Comments
 (0)