|
12 | 12 | from git import Repo # type: ignore
|
13 | 13 | import html
|
14 | 14 | import github
|
| 15 | +import json |
15 | 16 | import os
|
16 | 17 | import re
|
17 | 18 | import requests
|
@@ -299,6 +300,60 @@ def run(self) -> bool:
|
299 | 300 | return True
|
300 | 301 |
|
301 | 302 |
|
| 303 | +class PRMergeOnBehalfInformation: |
| 304 | + COMMENT_TAG = "<!--LLVM MERGE ON BEHALF INFORMATION COMMENT-->\n" |
| 305 | + |
| 306 | + def __init__( |
| 307 | + self, token: str, repo: str, pr_number: int, author: str, reviewer: str |
| 308 | + ): |
| 309 | + self.repo = github.Github(token).get_repo(repo) |
| 310 | + self.pr = self.repo.get_issue(pr_number).as_pull_request() |
| 311 | + self.author = author |
| 312 | + self.reviewer = reviewer |
| 313 | + |
| 314 | + def can_merge(self, user: str) -> bool: |
| 315 | + try: |
| 316 | + return self.repo.get_collaborator_permission(user) in ["admin", "write"] |
| 317 | + # There is a UnknownObjectException for this scenario, but this method |
| 318 | + # does not use it. |
| 319 | + except github.GithubException as e: |
| 320 | + # 404 means the author was not found in the collaborator list, so we |
| 321 | + # know they don't have push permissions. Anything else is a real API |
| 322 | + # issue, raise it so it is visible. |
| 323 | + if e.status != 404: |
| 324 | + raise e |
| 325 | + return False |
| 326 | + |
| 327 | + def run(self) -> bool: |
| 328 | + # Check this first because it only costs 1 API point. |
| 329 | + if self.can_merge(self.author): |
| 330 | + return |
| 331 | + |
| 332 | + # A review can be approved more than once, only comment the first time. |
| 333 | + for comment in self.pr.as_issue().get_comments(): |
| 334 | + if self.COMMENT_TAG in comment.body: |
| 335 | + return |
| 336 | + |
| 337 | + # This text is using Markdown formatting. |
| 338 | + if self.can_merge(self.reviewer): |
| 339 | + comment = f"""\ |
| 340 | +{self.COMMENT_TAG} |
| 341 | +@{self.reviewer} the PR author does not have permission to merge their own PRs yet. Please merge on their behalf.""" |
| 342 | + else: |
| 343 | + comment = f"""\ |
| 344 | +{self.COMMENT_TAG} |
| 345 | +@{self.reviewer} the author of this PR does not have permission to merge and neither do you. |
| 346 | +Please find someone who has merge permissions who can merge it on the author's behalf. This could be one of the other reviewers or you can ask on [Discord](https://discord.com/invite/xS7Z362).""" |
| 347 | + |
| 348 | + # This command will run on PRs which means the initial workflow can't |
| 349 | + # write to the PR. Instead write the comment to a file that will be |
| 350 | + # picked up by issue-write. |
| 351 | + with open("comments", "w") as f: |
| 352 | + json.dump({"body": comment}) |
| 353 | + |
| 354 | + return True |
| 355 | + |
| 356 | + |
302 | 357 | def setup_llvmbot_git(git_dir="."):
|
303 | 358 | """
|
304 | 359 | Configure the git repo in `git_dir` with the llvmbot account so
|
@@ -664,6 +719,17 @@ def execute_command(self) -> bool:
|
664 | 719 | pr_buildbot_information_parser.add_argument("--issue-number", type=int, required=True)
|
665 | 720 | pr_buildbot_information_parser.add_argument("--author", type=str, required=True)
|
666 | 721 |
|
| 722 | +pr_merge_on_behalf_information_parser = subparsers.add_parser( |
| 723 | + "pr-merge-on-behalf-information" |
| 724 | +) |
| 725 | +pr_merge_on_behalf_information_parser.add_argument( |
| 726 | + "--issue-number", type=int, required=True |
| 727 | +) |
| 728 | +pr_merge_on_behalf_information_parser.add_argument("--author", type=str, required=True) |
| 729 | +pr_merge_on_behalf_information_parser.add_argument( |
| 730 | + "--reviewer", type=str, required=True |
| 731 | +) |
| 732 | + |
667 | 733 | release_workflow_parser = subparsers.add_parser("release-workflow")
|
668 | 734 | release_workflow_parser.add_argument(
|
669 | 735 | "--llvm-project-dir",
|
@@ -723,6 +789,11 @@ def execute_command(self) -> bool:
|
723 | 789 | args.token, args.repo, args.issue_number, args.author
|
724 | 790 | )
|
725 | 791 | pr_buildbot_information.run()
|
| 792 | +elif args.command == "pr-merge-on-behalf-information": |
| 793 | + pr_merge_on_behalf_information = PRMergeOnBehalfInformation( |
| 794 | + args.token, args.repo, args.issue_number, args.author, args.reviewer |
| 795 | + ) |
| 796 | + pr_merge_on_behalf_information.run() |
726 | 797 | elif args.command == "release-workflow":
|
727 | 798 | release_workflow = ReleaseWorkflow(
|
728 | 799 | args.token,
|
|
0 commit comments