|
1 | 1 | """Script for the GitHub issue self-assign bot.
|
2 | 2 |
|
3 |
| -It checks if a comment on an issue or PR includes the trigger |
4 |
| -phrase (as defined) and a mentioned user. |
5 |
| -If it does, it assigns the issue to the mentioned user. |
6 |
| -Users without write access can only have up to 2 open issues assigned. |
7 |
| -Users with write access (or admin) are exempt from this limit. |
8 |
| -If a non-write user already has 2 or more open issues, the bot |
9 |
| -comments on the issue with links to the currently assigned open issues. |
| 3 | +Checks if a comment on an issue or PR includes the trigger phrase and a mentioned user. |
| 4 | +If it does, it assigns or unassigns the issue to the mentioned user if they have |
| 5 | +permissions. |
10 | 6 | """
|
11 | 7 |
|
12 | 8 | import json
|
|
22 | 18 | repo = g.get_repo(repo)
|
23 | 19 | issue_number = context_dict["event"]["issue"]["number"]
|
24 | 20 | issue = repo.get_issue(number=issue_number)
|
25 |
| -comment_body = context_dict["event"]["comment"]["body"] |
| 21 | +issue_labels = {label.name.lower() for label in issue.labels} |
26 | 22 | pr = context_dict["event"]["issue"].get("pull_request")
|
| 23 | +comment_body = context_dict["event"]["comment"]["body"] |
27 | 24 | commenter = context_dict["event"]["comment"]["user"]["login"]
|
| 25 | +commenter_permission = repo.get_collaborator_permission(commenter) |
| 26 | +has_write_permission = commenter_permission not in ["admin", "write"] |
| 27 | + |
| 28 | +restricted_labels = {"meta-issue"} |
28 | 29 |
|
| 30 | +# Assign tagged used to the issue if the comment includes the trigger phrase |
29 | 31 | body = comment_body.lower()
|
30 |
| -if "@aeon-actions-bot" in body and not pr: |
31 |
| - # Assign commenter if comment includes "assign me" |
32 |
| - if "assign me" in body: |
33 |
| - issue.add_to_assignees(commenter) |
34 |
| - # Assign tagged used to the issue if the comment includes the trigger phrase |
35 |
| - elif "assign" in body: |
| 32 | +if "@aeon-actions-bot" in body and "assign" in body and not pr: |
| 33 | + # Check if the issue has any restricted labels for auto assignment |
| 34 | + label_intersect = issue_labels & restricted_labels |
| 35 | + if len(label_intersect) > 0: |
| 36 | + issue.create_comment( |
| 37 | + f"This issue contains the following restricted label(s): " |
| 38 | + f"{', '.join(label_intersect)}. Cannot assign to users." |
| 39 | + ) |
| 40 | + else: |
| 41 | + # collect any mentioned (@username) users |
36 | 42 | mentioned_users = re.findall(r"@[a-zA-Z0-9_-]+", comment_body)
|
37 | 43 | mentioned_users = [user[1:] for user in mentioned_users]
|
38 | 44 | mentioned_users.remove("aeon-actions-bot")
|
| 45 | + # Assign commenter if comment includes "assign me" |
| 46 | + if "assign me" in body: |
| 47 | + mentioned_users.append(commenter) |
| 48 | + mentioned_users = set(mentioned_users) |
39 | 49 |
|
| 50 | + access_error = False |
40 | 51 | for user in mentioned_users:
|
41 |
| - user_obj = g.get_user(user) |
42 |
| - permission = repo.get_collaborator_permission(user_obj) |
| 52 | + # Can only assign others if the commenter has write access |
| 53 | + if user != commenter and not has_write_permission: |
| 54 | + if not access_error: |
| 55 | + issue.create_comment( |
| 56 | + "Cannot assign other users to issues without write access." |
| 57 | + ) |
| 58 | + access_error = True |
| 59 | + continue |
| 60 | + |
| 61 | + # If the user is already assigned to this issue, remove them |
| 62 | + if user in [assignee.login for assignee in issue.assignees]: |
| 63 | + issue.remove_from_assignees(user) |
| 64 | + continue |
43 | 65 |
|
44 |
| - if permission in ["admin", "write"]: |
| 66 | + # If the commenter has write access, just assign |
| 67 | + if has_write_permission: |
45 | 68 | issue.add_to_assignees(user)
|
46 | 69 | else:
|
47 |
| - # First check if the user is already assigned to this issue |
48 |
| - if user in [assignee.login for assignee in issue.assignees]: |
49 |
| - continue |
50 |
| - |
51 | 70 | # search for open issues only
|
52 | 71 | query = f"repo:{repo.full_name} is:issue is:open assignee:{user}"
|
53 | 72 | issues_assigned_to_user = g.search_issues(query)
|
54 | 73 | assigned_count = issues_assigned_to_user.totalCount
|
55 | 74 |
|
56 |
| - if assigned_count >= 2: |
| 75 | + if assigned_count >= 3: |
57 | 76 | # link to issue
|
58 | 77 | assigned_issues_list = [
|
59 | 78 | f"[#{assigned_issue.number}]({assigned_issue.html_url})"
|
60 | 79 | for assigned_issue in issues_assigned_to_user
|
61 | 80 | ]
|
62 | 81 |
|
63 |
| - comment_message = ( |
64 |
| - f"@{user}, you already have {assigned_count} " |
65 |
| - f"open issues assigned." |
66 |
| - "Users without write access are limited to self-assigning two" |
67 |
| - "issues.\n\n" |
68 |
| - "Here are the open issues assigned to you:\n" |
| 82 | + issue.create_comment( |
| 83 | + f"@{user}, already has {assigned_count} open issues assigned." |
| 84 | + "Users without write access are limited to self-assigning " |
| 85 | + "three issues.\n\n" |
| 86 | + "Here are the open issues assigned:\n" |
69 | 87 | + "\n".join(
|
70 | 88 | f"- {issue_link}" for issue_link in assigned_issues_list
|
71 | 89 | )
|
72 | 90 | )
|
73 |
| - issue.create_comment(comment_message) |
74 | 91 | else:
|
75 | 92 | issue.add_to_assignees(user)
|
0 commit comments