diff --git a/bugbot/rules/assignee_no_login.py b/bugbot/rules/assignee_no_login.py index 2ba4d0864..d9762c22d 100644 --- a/bugbot/rules/assignee_no_login.py +++ b/bugbot/rules/assignee_no_login.py @@ -3,8 +3,10 @@ # You can obtain one at http://mozilla.org/MPL/2.0/. import collections +from datetime import datetime, timedelta from libmozdata import utils as lmdutils +from libmozdata.bugzilla import Bugzilla from bugbot import logger, people, utils from bugbot.bzcleaner import BzCleaner @@ -23,6 +25,7 @@ def __init__(self): self.people = people.People.get_instance() self.unassign_count = collections.defaultdict(int) self.no_bugmail = True + self.one_year_ago = datetime.now() - timedelta(days=365) self.extra_ni = {} @@ -60,6 +63,13 @@ def get_max_actions(self): def get_bugs(self, *args, **kwargs): bugs = super().get_bugs(*args, **kwargs) + + bug_ids = list(bugs.keys()) + bug_histories = self.fetch_bug_histories(bug_ids) + + for bugid, bug in bugs.items(): + bug["history"] = bug_histories.get(bugid, []) + bugs = self.handle_inactive_assignees(bugs) # Resolving https://github.com/mozilla/bugbot/issues/1300 should clean this @@ -68,6 +78,34 @@ def get_bugs(self, *args, **kwargs): return bugs + def fetch_bug_histories(self, bug_ids): + bug_histories = {} + + def history_handler(bug): + bug_id = str(bug["id"]) + + history_entries = [] + for history in bug["history"]: + for change in history["changes"]: + history_entries.append( + { + "field_name": change["field_name"], + "removed": change["removed"], + "added": change["added"], + "when": history["when"], + "who": history["who"], + } + ) + + bug_histories[bug_id] = history_entries + + Bugzilla( + bugids=bug_ids, + historyhandler=history_handler, + ).get_data().wait() + + return bug_histories + def handle_inactive_assignees(self, bugs): user_activity = UserActivity() assignees = {bug["assigned_to"] for bug in bugs.values()} @@ -100,13 +138,22 @@ def add_action(self, bug): default_assignee = self.default_assignees[prod][comp] autofix = {"assigned_to": default_assignee} + priority_change_date = self.get_priority_change_date(bug) + is_old_priority = ( + priority_change_date and priority_change_date < self.one_year_ago + ) + # Avoid to ni if the bug has low priority and low severity. # It's not paramount for triage owners to make an explicit decision here, it's enough for them # to receive the notification about the unassignment from Bugzilla via email. if ( - bug["priority"] not in HIGH_PRIORITY - and bug["severity"] not in HIGH_SEVERITY - ) or "stalled" in bug["keywords"]: + ( + bug["priority"] not in HIGH_PRIORITY + and bug["severity"] not in HIGH_SEVERITY + ) + or "stalled" in bug["keywords"] + or (is_old_priority and bug["priority"] in HIGH_PRIORITY) + ): needinfo = None autofix["comment"] = { "body": "The bug assignee is inactive on Bugzilla, so the assignee is being reset." @@ -126,6 +173,17 @@ def add_action(self, bug): self.add_prioritized_action(bug, bug["triage_owner"], needinfo, autofix) + def get_priority_change_date(self, bug): + current_priority = bug["priority"] + + for change in reversed(bug["history"]): + if ( + change["field_name"] == "priority" + and change["added"] == current_priority + ): + return datetime.strptime(change["when"], "%Y-%m-%dT%H:%M:%SZ") + return None + def handle_bug(self, bug, data): bugid = str(bug["id"]) if "triage_owner_detail" not in bug: