Skip to content

Commit 5bc5061

Browse files
committed
[GitHub] Add workflow to check author's commit access on new PRs
This workflow will run on every opened PR and add a label if the author does not have the required permissions to merge their own PR. The permission check is based on code from llvm#81142, which tried to do this when a review was approved. That had to be reverted in llvm#81722 because the event that it was triggered by did not have permissions to write to the PR. So we have a slight disadvantage that a label could be wrong by the time the review is approved but ok, the author can click the button themselves then anyway. Plus, you could search by the label to find anything waiting for someone to merge on behalf.
1 parent a16adaf commit 5bc5061

File tree

2 files changed

+64
-0
lines changed

2 files changed

+64
-0
lines changed

.github/workflows/new-prs.yml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,3 +73,31 @@ jobs:
7373
# workaround for https://github.com/actions/labeler/issues/112
7474
sync-labels: ''
7575
repo-token: ${{ secrets.ISSUE_SUBSCRIBER_TOKEN }}
76+
77+
check-commit-access:
78+
runs-on: ubuntu-latest
79+
permissions:
80+
pull-requests: write
81+
if: >-
82+
(github.repository == 'llvm/llvm-project') &&
83+
(github.event.action == 'opened')
84+
steps:
85+
- name: Checkout Automation Script
86+
uses: actions/checkout@v4
87+
with:
88+
sparse-checkout: llvm/utils/git/
89+
ref: main
90+
91+
- name: Setup Automation Script
92+
working-directory: ./llvm/utils/git/
93+
run: |
94+
pip install --require-hashes -r requirements.txt
95+
96+
- name: Check Commit Access
97+
working-directory: ./llvm/utils/git/
98+
run: |
99+
python3 ./github-automation.py \
100+
--token '${{ secrets.GITHUB_TOKEN }}' \
101+
check-commit-access \
102+
--issue-number "${{ github.event.pull_request.number }}" \
103+
--author "${{ github.event.pull_request.user.login }}"

llvm/utils/git/github-automation.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,33 @@ def run(self) -> bool:
290290
return True
291291

292292

293+
class CheckCommitAccess:
294+
def __init__(
295+
self, token: str, repo: str, pr_number: int, author: str):
296+
self.repo = github.Github(token).get_repo(repo)
297+
self.pr = self.repo.get_issue(pr_number).as_pull_request()
298+
self.author = author
299+
300+
def can_merge(self, user: str) -> bool:
301+
try:
302+
return self.repo.get_collaborator_permission(user) in ["admin", "write"]
303+
# There is a UnknownObjectException for this scenario, but this method
304+
# does not use it.
305+
except github.GithubException as e:
306+
# 404 means the author was not found in the collaborator list, so we
307+
# know they don't have push permissions. Anything else is a real API
308+
# issue, raise it so it is visible.
309+
if e.status != 404:
310+
raise e
311+
return False
312+
313+
def run(self) -> bool:
314+
if not self.can_merge(self.author):
315+
self.pr.as_issue().add_to_labels("no-commit-access")
316+
317+
return True
318+
319+
293320
def setup_llvmbot_git(git_dir="."):
294321
"""
295322
Configure the git repo in `git_dir` with the llvmbot account so
@@ -680,6 +707,10 @@ def request_release_note(token: str, repo_name: str, pr_number: int):
680707
pr_buildbot_information_parser.add_argument("--issue-number", type=int, required=True)
681708
pr_buildbot_information_parser.add_argument("--author", type=str, required=True)
682709

710+
check_commit_access_parser = subparsers.add_parser("check-commit-access")
711+
check_commit_access_parser.add_argument("--issue-number", type=int, required=True)
712+
check_commit_access_parser.add_argument("--author", type=str, required=True)
713+
683714
release_workflow_parser = subparsers.add_parser("release-workflow")
684715
release_workflow_parser.add_argument(
685716
"--llvm-project-dir",
@@ -751,6 +782,11 @@ def request_release_note(token: str, repo_name: str, pr_number: int):
751782
args.token, args.repo, args.issue_number, args.author
752783
)
753784
pr_buildbot_information.run()
785+
elif args.command == "check-commit-access":
786+
check_commit_access = CheckCommitAccess(
787+
args.token, args.repo, args.issue_number, args.author
788+
)
789+
check_commit_access.run()
754790
elif args.command == "release-workflow":
755791
release_workflow = ReleaseWorkflow(
756792
args.token,

0 commit comments

Comments
 (0)