diff --git a/gerrit_to_github_issues/engine.py b/gerrit_to_github_issues/engine.py index 6ad6012..19cf664 100644 --- a/gerrit_to_github_issues/engine.py +++ b/gerrit_to_github_issues/engine.py @@ -30,6 +30,9 @@ def update(gerrit_url: str, gerrit_project_name: str, github_project_name: str, if 'commitMessage' in change: process_change(gh, change, repo, skip_approvals) + # Handle the incoming issue assignment requests + github_issues.assign_issues(repo) + def process_change(gh: github.Github, change: dict, repo: Repository, skip_approvals: bool = False): issue_numbers_dict = github_issues.parse_issue_number(change['commitMessage']) diff --git a/gerrit_to_github_issues/github_issues.py b/gerrit_to_github_issues/github_issues.py index 3a9b1f7..0654baf 100644 --- a/gerrit_to_github_issues/github_issues.py +++ b/gerrit_to_github_issues/github_issues.py @@ -9,6 +9,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +from datetime import datetime import logging import re @@ -75,3 +76,52 @@ def get_bot_comment(issue: Issue, bot_name: str, ps_number: str) -> IssueComment for i in issue.get_comments(): if i.user.login == bot_name and ps_number in i.body: return i + + +def assign_issues(repo: github.Repository): + open_issues = [i for i in repo.get_issues() if i.state == 'open'] + for issue in open_issues: + try_assign(issue) + + +def try_assign(issue: github.Issue): + # find the most recent assignment request + assignment_request = None + for comment in issue.get_comments().reversed: + if '/assign' in comment.body: + assignment_request = comment + break + if not assignment_request: + # Looks like no one wants this issue + return + + if not issue.assignees: + # If no one has been assigned yet, let the user take the issue + issue.add_to_assignees(assignment_request.user) + issue.create_comment(f'assigned {assignment_request.user.login}') + return + + if issue_age(issue) > 30: + # If the issue is 1 months old and the original assignees haven't + # closed it yet, let's assume that they've stopped working on it and + # allow the new user to have this issue + old_assignees = issue.assignees + for assignee in old_assignees: + issue.remove_from_assignees(assignee) + issue.add_to_assignees(assignment_request.user) + comment_body = f'unassigned: {", ".join([a for a in old_assignees])}\n' + \ + f'assigned: {assignment_request.user.login}' + issue.create_comment(comment_body) + return + + # If we've made it here, a user has requested to be assigned to a non-stale + # issue which is already assigned. Just notify the core team and let them + # handle the conflict. + comment_body = f'Unable to assign {assignment_request.user.login}. Please ' + \ + f'contact a member of the @airshipit/airship-cores team for ' + \ + f'help with assignments.' + issue.create_comment(comment_body) + + +def issue_age(issue): + return (datetime.now() - issue.created_at).days