44name : " CI: Check PR author organization for restricted paths"
55
66on :
7- # TODO BEFORE MERGING: change to pull_request_target
87 pull_request :
98 types :
109 - opened
@@ -18,37 +17,32 @@ jobs:
1817 if : github.repository_owner == 'NVIDIA'
1918 runs-on : ubuntu-latest
2019 permissions :
21- issues : write
2220 pull-requests : read
2321 steps :
2422 - name : Check PR author organization for restricted paths
2523 env :
2624 # PR metadata inputs
2725 AUTHOR_ASSOCIATION : ${{ github.event.pull_request.author_association || 'NONE' }}
28- LABELS : ${{ toJson(github.event.pull_request.labels) }}
2926 PR_AUTHOR : ${{ github.event.pull_request.user.login }}
3027 PR_NUMBER : ${{ github.event.pull_request.number }}
3128 PR_URL : ${{ github.event.pull_request.html_url }}
3229
3330 # API request context/auth
3431 GH_TOKEN : ${{ github.token }}
35- ORG_NAME : NVIDIA
36- ORG_REVIEW_LABEL : Check-PR-Author-ORG
3732 REPO : ${{ github.repository }}
3833 run : |
3934 if ! MATCHING_RESTRICTED_PATHS=$(
4035 gh api \
4136 --paginate \
4237 --jq '
4338 .[]
44- | if (.filename | startswith("cuda_bindings/"))
39+ | select(
40+ (.filename | startswith("cuda_bindings/"))
41+ or ((.previous_filename // "") | startswith("cuda_bindings/"))
4542 or (.filename | startswith("cuda_python/"))
46- then .filename
47- elif ((.previous_filename // "") | startswith("cuda_bindings/"))
4843 or ((.previous_filename // "") | startswith("cuda_python/"))
49- then "\(.previous_filename) -> \(.filename)"
50- else empty
51- end
44+ )
45+ | .filename
5246 ' \
5347 "repos/$REPO/pulls/$PR_NUMBER/files"
5448 ); then
@@ -70,161 +64,47 @@ jobs:
7064 TOUCHES_RESTRICTED_PATHS=true
7165 fi
7266
73- HAS_ORG_REVIEW_LABEL=false
74- while IFS= read -r label; do
75- [ -n "$label" ] || continue
76- if [ "$label" = "$ORG_REVIEW_LABEL" ]; then
77- HAS_ORG_REVIEW_LABEL=true
78- break
79- fi
80- done < <(echo "$LABELS" | jq -r '.[].name')
81-
82- REVIEW_LABEL_ACTION="none"
83-
8467 write_matching_restricted_paths() {
8568 echo "- **Matched restricted paths**:"
8669 echo '```text'
8770 printf '%s\n' "$MATCHING_RESTRICTED_PATHS"
8871 echo '```'
8972 }
9073
91- write_review_label_action() {
92- [ "$REVIEW_LABEL_ACTION" != "none" ] || return 0
93- echo "- **Review label action**: $REVIEW_LABEL_ACTION \`$ORG_REVIEW_LABEL\`"
94- }
95-
96- ensure_org_review_label_present() {
97- if [ "$HAS_ORG_REVIEW_LABEL" = "false" ]; then
98- if ! gh issue edit "$PR_NUMBER" --repo "$REPO" --add-label "$ORG_REVIEW_LABEL" >/dev/null; then
99- echo "::error::Failed to add label $ORG_REVIEW_LABEL."
100- exit 1
101- fi
102- HAS_ORG_REVIEW_LABEL=true
103- REVIEW_LABEL_ACTION="added"
104- fi
105- }
106-
107- ensure_org_review_label_absent() {
108- if [ "$HAS_ORG_REVIEW_LABEL" = "true" ]; then
109- if ! gh issue edit "$PR_NUMBER" --repo "$REPO" --remove-label "$ORG_REVIEW_LABEL" >/dev/null; then
110- echo "::error::Failed to remove label $ORG_REVIEW_LABEL."
111- exit 1
112- fi
113- HAS_ORG_REVIEW_LABEL=false
114- REVIEW_LABEL_ACTION="removed"
115- fi
116- }
117-
118- if [ "$TOUCHES_RESTRICTED_PATHS" = "false" ]; then
119- ensure_org_review_label_absent
120- {
121- echo "## PR Author Organization Check Passed"
122- echo ""
123- echo "- **Author**: $PR_AUTHOR"
124- echo "- **Author association**: $AUTHOR_ASSOCIATION"
125- echo "- **Touches restricted paths**: false"
126- echo "- **Restricted paths**: \`cuda_bindings/\`, \`cuda_python/\`"
127- write_review_label_action
128- } >> "$GITHUB_STEP_SUMMARY"
129- exit 0
130- fi
74+ IS_ALLOWED=false
75+ case "$AUTHOR_ASSOCIATION" in
76+ MEMBER|OWNER)
77+ IS_ALLOWED=true
78+ ;;
79+ esac
13180
132- # Use curl here because the 204/404/302 HTTP status is the signal we
133- # need. gh api treats 404 as a command failure, but 404 is an expected
134- # "not a member" outcome for this check.
135- if ! MEMBERSHIP_STATUS=$(
136- curl --silent --show-error --output /dev/null --write-out '%{http_code}' \
137- -H "Authorization: Bearer $GH_TOKEN" \
138- -H "Accept: application/vnd.github+json" \
139- -H "X-GitHub-Api-Version: 2022-11-28" \
140- "https://api.github.com/orgs/$ORG_NAME/members/$PR_AUTHOR"
141- ); then
142- echo "::error::Failed to query organization membership."
81+ if [ "$TOUCHES_RESTRICTED_PATHS" = "true" ] && [ "$IS_ALLOWED" = "false" ]; then
82+ echo "::error::This PR failed the author organization check. See the job summary for details."
14383 {
14484 echo "## PR Author Organization Check Failed"
14585 echo ""
146- echo "- **Error**: Failed to query organization membership."
14786 echo "- **Author**: $PR_AUTHOR"
14887 echo "- **Author association**: $AUTHOR_ASSOCIATION"
149- echo "- **Organization membership query**: failed"
15088 echo "- **Restricted paths**: \`cuda_bindings/\`, \`cuda_python/\`"
15189 echo ""
15290 write_matching_restricted_paths
15391 echo ""
92+ echo "- **Policy**: See \`cuda_bindings/LICENSE\` and \`cuda_python/LICENSE\`. Only NVIDIA organization members may modify files under \`cuda_bindings/\` or \`cuda_python/\`."
93+ echo ""
15494 echo "Please update the PR at: $PR_URL"
15595 } >> "$GITHUB_STEP_SUMMARY"
15696 exit 1
15797 fi
15898
159- case "$MEMBERSHIP_STATUS" in
160- 204)
161- ensure_org_review_label_absent
162- {
163- echo "## PR Author Organization Check Passed"
164- echo ""
165- echo "- **Author**: $PR_AUTHOR"
166- echo "- **Author association**: $AUTHOR_ASSOCIATION"
167- echo "- **Organization membership query**: \`204\` (member)"
168- echo "- **Restricted paths**: \`cuda_bindings/\`, \`cuda_python/\`"
169- echo ""
170- write_matching_restricted_paths
171- write_review_label_action
172- } >> "$GITHUB_STEP_SUMMARY"
173- ;;
174- 302)
175- ensure_org_review_label_present
176- echo "::warning::Could not determine conclusively whether $PR_AUTHOR is a member of $ORG_NAME. Added label $ORG_REVIEW_LABEL for manual review."
177- {
178- echo "## PR Author Organization Check Inconclusive"
179- echo ""
180- echo "- **Author**: $PR_AUTHOR"
181- echo "- **Author association**: $AUTHOR_ASSOCIATION"
182- echo "- **Organization membership query**: \`302\` (inconclusive)"
183- echo "- **Restricted paths**: \`cuda_bindings/\`, \`cuda_python/\`"
184- echo ""
185- write_matching_restricted_paths
186- write_review_label_action
187- echo ""
188- echo "- **Next step**: Review whether the PR author should be allowed to modify these restricted paths."
189- echo ""
190- echo "Please update the PR at: $PR_URL"
191- } >> "$GITHUB_STEP_SUMMARY"
192- ;;
193- 404)
194- ensure_org_review_label_absent
195- echo "::error::This PR failed the author organization check. See the job summary for details."
196- {
197- echo "## PR Author Organization Check Failed"
198- echo ""
199- echo "- **Author**: $PR_AUTHOR"
200- echo "- **Author association**: $AUTHOR_ASSOCIATION"
201- echo "- **Organization membership query**: \`404\` (not a member)"
202- echo "- **Restricted paths**: \`cuda_bindings/\`, \`cuda_python/\`"
203- echo ""
204- write_matching_restricted_paths
205- write_review_label_action
206- echo ""
207- echo "- **Policy**: See \`cuda_bindings/LICENSE\` and \`cuda_python/LICENSE\`. Only NVIDIA organization members may modify files under \`cuda_bindings/\` or \`cuda_python/\`."
208- echo ""
209- echo "Please update the PR at: $PR_URL"
210- } >> "$GITHUB_STEP_SUMMARY"
211- exit 1
212- ;;
213- *)
214- echo "::error::Unexpected response from organization membership query: HTTP $MEMBERSHIP_STATUS."
215- {
216- echo "## PR Author Organization Check Failed"
217- echo ""
218- echo "- **Error**: Unexpected response from organization membership query."
219- echo "- **Author**: $PR_AUTHOR"
220- echo "- **Author association**: $AUTHOR_ASSOCIATION"
221- echo "- **Organization membership query**: \`$MEMBERSHIP_STATUS\`"
222- echo "- **Restricted paths**: \`cuda_bindings/\`, \`cuda_python/\`"
223- echo ""
224- write_matching_restricted_paths
225- echo ""
226- echo "Please update the PR at: $PR_URL"
227- } >> "$GITHUB_STEP_SUMMARY"
228- exit 1
229- ;;
230- esac
99+ {
100+ echo "## PR Author Organization Check Passed"
101+ echo ""
102+ echo "- **Author**: $PR_AUTHOR"
103+ echo "- **Author association**: $AUTHOR_ASSOCIATION"
104+ echo "- **Touches restricted paths**: $TOUCHES_RESTRICTED_PATHS"
105+ echo "- **Restricted paths**: \`cuda_bindings/\`, \`cuda_python/\`"
106+ if [ "$TOUCHES_RESTRICTED_PATHS" = "true" ]; then
107+ echo ""
108+ write_matching_restricted_paths
109+ fi
110+ } >> "$GITHUB_STEP_SUMMARY"
0 commit comments