Skip to content
Open
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
5c15180
CI: add PR author organization check
rwgk Apr 7, 2026
4b650ce
CI: fix PR author org check file lookup
rwgk Apr 7, 2026
ead62e7
XXX DUMMY CHANGE XXX under cuda_bindings/
rwgk Apr 7, 2026
f56a8d1
CI: show matched restricted paths in PR check
rwgk Apr 7, 2026
42ba3f8
CI: triage inconclusive PR author org checks
rwgk Apr 7, 2026
a4aa6f0
Revert "CI: triage inconclusive PR author org checks"
rwgk Apr 8, 2026
6f58858
CI: allow collaborators in PR author org check
rwgk Apr 8, 2026
9dcf7b1
CI: label PRs without trusted author signals
rwgk Apr 8, 2026
c09bb82
Merge branch 'main' into pr-author-org-check
rwgk Apr 8, 2026
bc16d97
Revert "CI: label PRs without trusted author signals"
rwgk Apr 8, 2026
539461f
CI: use checked-in PR author allowlist
rwgk Apr 8, 2026
c6753f7
CI: rename PR author trusted signal wording
rwgk Apr 8, 2026
4d4cb84
CI: clarify renamed restricted path matches
rwgk Apr 8, 2026
4563db8
CI: trust collaborators in PR author check
rwgk Apr 9, 2026
02eacfa
CI: shorten restricted paths guard names
rwgk Apr 9, 2026
3141d89
CI: rename restricted paths review label
rwgk Apr 9, 2026
16c3faa
CI: rename restricted paths guard workflow
rwgk Apr 9, 2026
71b76d7
Merge branch 'main' into pr-author-org-check
rwgk Apr 9, 2026
02edff4
Resolve TODO before merging:
rwgk Apr 10, 2026
d452d73
Merge branch 'main' into pr-author-org-check
rwgk Apr 11, 2026
66bd22e
CI: harden restricted paths guard label handling
rwgk Apr 11, 2026
9100985
Revert "Resolve TODO before merging:"
rwgk Apr 11, 2026
5a4c8e8
Resolve TODO before merging:
rwgk Apr 10, 2026
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
173 changes: 173 additions & 0 deletions .github/workflows/restricted-paths-guard.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
# SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

name: "CI: Restricted Paths Guard"

on:
# Run on drafts too so maintainers get early awareness on WIP PRs.
# Label updates on fork PRs require pull_request_target permissions.
pull_request_target:
types:
- opened
- synchronize
- reopened
- ready_for_review
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Unlike pr-metadata-check.yml which skips drafts, this workflow runs on draft PRs too. That's probably fine for early awareness, but worth noting if intentional — especially since the label could be confusing on a WIP draft.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Done: commit 66bd22e

The label is also for external PR authors, to alert them early.


jobs:
restricted-paths-guard:
name: Apply review label if needed
if: github.repository_owner == 'NVIDIA'
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- name: Inspect PR author signals for restricted paths
env:
# PR metadata inputs
AUTHOR_ASSOCIATION: ${{ github.event.pull_request.author_association || 'NONE' }}
PR_AUTHOR: ${{ github.event.pull_request.user.login }}
PR_NUMBER: ${{ github.event.pull_request.number }}
PR_URL: ${{ github.event.pull_request.html_url }}

# Workflow policy inputs
REVIEW_LABEL: Needs-Restricted-Paths-Review

# API request context/auth
GH_TOKEN: ${{ github.token }}
REPO: ${{ github.repository }}
run: |
set -euo pipefail

if ! MATCHING_RESTRICTED_PATHS=$(
gh api \
--paginate \
--jq '
.[]
| select(
(.filename | startswith("cuda_bindings/"))
or ((.previous_filename // "") | startswith("cuda_bindings/"))
or (.filename | startswith("cuda_python/"))
or ((.previous_filename // "") | startswith("cuda_python/"))
)
| if (.previous_filename // "") != "" then
"\(.previous_filename) -> \(.filename)"
else
.filename
end
' \
"repos/$REPO/pulls/$PR_NUMBER/files"
); then
echo "::error::Failed to inspect the PR file list."
{
echo "## Restricted Paths Guard Failed"
echo ""
echo "- **Error**: Failed to inspect the PR file list."
echo "- **Author**: $PR_AUTHOR"
echo "- **Author association**: $AUTHOR_ASSOCIATION"
echo ""
echo "Please update the PR at: $PR_URL"
} >> "$GITHUB_STEP_SUMMARY"
exit 1
fi

# Fetch live PR labels to avoid stale event payload (race condition
# when labels are changed shortly before the workflow runs).
if ! LIVE_LABELS=$(
gh pr view "${PR_NUMBER}" --repo "${REPO}" \
--json labels \
--jq '[.labels[].name]'
); then
echo "::error::Failed to inspect the current PR labels."
{
echo "## Restricted Paths Guard Failed"
echo ""
echo "- **Error**: Failed to inspect the current PR labels."
echo "- **Author**: $PR_AUTHOR"
echo "- **Author association**: $AUTHOR_ASSOCIATION"
echo ""
echo "Please update the PR at: $PR_URL"
} >> "$GITHUB_STEP_SUMMARY"
exit 1
fi

TOUCHES_RESTRICTED_PATHS=false
if [ -n "$MATCHING_RESTRICTED_PATHS" ]; then
TOUCHES_RESTRICTED_PATHS=true
fi

write_matching_restricted_paths() {
echo "- **Matched restricted paths**:"
echo '```text'
printf '%s\n' "$MATCHING_RESTRICTED_PATHS"
echo '```'
}

HAS_TRUSTED_SIGNAL=false
LABEL_ACTION="not needed (no restricted paths)"
TRUSTED_SIGNALS="(none)"

if [ "$TOUCHES_RESTRICTED_PATHS" = "true" ]; then
case "$AUTHOR_ASSOCIATION" in
COLLABORATOR|MEMBER|OWNER)
HAS_TRUSTED_SIGNAL=true
LABEL_ACTION="not needed (author association is a trusted signal)"
TRUSTED_SIGNALS="author_association:$AUTHOR_ASSOCIATION"
;;
esac
fi

NEEDS_REVIEW_LABEL=false
if [ "$TOUCHES_RESTRICTED_PATHS" = "true" ] && [ "$HAS_TRUSTED_SIGNAL" = "false" ]; then
NEEDS_REVIEW_LABEL=true
fi

LABEL_ALREADY_PRESENT=false
if jq -e --arg label "$REVIEW_LABEL" '.[] == $label' <<<"$LIVE_LABELS" >/dev/null; then
LABEL_ALREADY_PRESENT=true
fi

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

On synchronize, if the author pushes a new commit that removes all restricted-path changes, this block is skipped (since TOUCHES_RESTRICTED_PATHS becomes false) but the Needs-Restricted-Paths-Review label from the earlier run is never removed. Is this intentional (fail-safe, require manual removal)? If so, might be worth a comment here or in the PR description noting that label removal is always manual.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Done: commit 66bd22e

There is a message in the summary now:

+              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."

When I gave your feedback to Cursor, it actually added code to remove the label, but I requested to back it out again: I expect this situation to be very rare, and because we're not inspecting individual commits, it's safer to require manual removal. In such cases, we might also want to manually clean up the squash-merge commit message.

if [ "$NEEDS_REVIEW_LABEL" = "true" ]; then
if [ "$LABEL_ALREADY_PRESENT" = "true" ]; then
LABEL_ACTION="already present"
elif ! gh pr edit "$PR_NUMBER" --repo "$REPO" --add-label "$REVIEW_LABEL"; then
echo "::error::Failed to add the $REVIEW_LABEL label."
{
echo "## Restricted Paths Guard Failed"
echo ""
echo "- **Error**: Failed to add the \`$REVIEW_LABEL\` label."
echo "- **Author**: $PR_AUTHOR"
echo "- **Author association**: $AUTHOR_ASSOCIATION"
echo ""
write_matching_restricted_paths
echo ""
echo "Please update the PR at: $PR_URL"
} >> "$GITHUB_STEP_SUMMARY"
exit 1
else
LABEL_ACTION="added"
fi
elif [ "$LABEL_ALREADY_PRESENT" = "true" ]; then
LABEL_ACTION="left in place (manual removal required)"
fi

{
echo "## Restricted Paths Guard Completed"
echo ""
echo "- **Author**: $PR_AUTHOR"
echo "- **Author association**: $AUTHOR_ASSOCIATION"
echo "- **Touches restricted paths**: $TOUCHES_RESTRICTED_PATHS"
echo "- **Restricted paths**: \`cuda_bindings/\`, \`cuda_python/\`"
echo "- **Trusted signals**: $TRUSTED_SIGNALS"
echo "- **Label action**: $LABEL_ACTION"
if [ "$TOUCHES_RESTRICTED_PATHS" = "true" ]; then
echo ""
write_matching_restricted_paths
fi
if [ "$NEEDS_REVIEW_LABEL" = "true" ]; then
echo ""
echo "- **Manual follow-up**: No trusted signal was found, so \`$REVIEW_LABEL\` is required."
elif [ "$LABEL_ALREADY_PRESENT" = "true" ]; then
echo ""
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."
fi
} >> "$GITHUB_STEP_SUMMARY"
Loading