Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clear inactive assignee for old high-priority bugs without needinfo #2517

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 61 additions & 3 deletions bugbot/rules/assignee_no_login.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 = {}

Expand Down Expand Up @@ -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
Expand All @@ -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()}
Expand Down Expand Up @@ -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."
Expand All @@ -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:
Expand Down