• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mozilla / relman-auto-nag / #5309

01 Nov 2024 07:52PM CUT coverage: 21.516% (-0.2%) from 21.688%
#5309

push

coveralls-python

web-flow
Add bugbot rule to needinfo perf regression authors after period of inactivity (#2527)



Co-authored-by: Suhaib Mujahid <suhaibmujahid@gmail.com>

426 of 2894 branches covered (14.72%)

0 of 67 new or added lines in 1 file covered. (0.0%)

1 existing line in 1 file now uncovered.

1942 of 9026 relevant lines covered (21.52%)

0.22 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/bugbot/rules/perfalert_inactive_regression.py
1
# This Source Code Form is subject to the terms of the Mozilla Public
2
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
3
# You can obtain one at http://mozilla.org/MPL/2.0/.
4

NEW
5
import collections
×
6

NEW
7
from libmozdata.bugzilla import Bugzilla
×
8

NEW
9
from bugbot import logger, utils
×
NEW
10
from bugbot.bzcleaner import BzCleaner
×
NEW
11
from bugbot.user_activity import UserActivity, UserStatus
×
12

13

NEW
14
class PerfAlertInactiveRegression(BzCleaner):
×
NEW
15
    def __init__(self, nweeks=1):
×
NEW
16
        super().__init__()
×
NEW
17
        self.nweeks = nweeks
×
NEW
18
        self.extra_ni = {"nweeks": self.nweeks}
×
NEW
19
        self.private_regressor_ids: set[str] = set()
×
20

NEW
21
    def description(self):
×
NEW
22
        return f"PerfAlert regressions with {self.nweeks} week(s) of inactivity"
×
23

NEW
24
    def handle_bug(self, bug, data):
×
NEW
25
        if len(bug["regressed_by"]) != 1:
×
26
            # either we don't have access to the regressor,
27
            # or there's more than one, either way leave things alone
NEW
28
            return
×
29

NEW
30
        data[str(bug["id"])] = {
×
31
            "regressor_id": bug["regressed_by"][0],
32
        }
33

NEW
34
        return bug
×
35

NEW
36
    def get_bz_params(self, date):
×
NEW
37
        start_date, _ = self.get_dates(date)
×
38

NEW
39
        fields = [
×
40
            "id",
41
            "regressed_by",
42
        ]
43

44
        # Find all bugs that have perf-alert, and regression in their keywords. Only
45
        # look for bugs after October 1st, 2024 to prevent triggering comments on older
46
        # performance regressions
NEW
47
        params = {
×
48
            "include_fields": fields,
49
            "f3": "creation_ts",
50
            "o3": "greaterthan",
51
            "v3": "2024-10-01T00:00:00Z",
52
            "f1": "regressed_by",
53
            "o1": "isnotempty",
54
            "f2": "keywords",
55
            "o2": "allwords",
56
            "v2": ["regression", "perf-alert"],
57
            "f9": "days_elapsed",
58
            "o9": "greaterthan",
59
            "v9": self.nweeks * 7,
60
            "status": ["UNCONFIRMED", "NEW", "REOPENED"],
61
            "resolution": ["---"],
62
        }
63

NEW
64
        return params
×
65

NEW
66
    def retrieve_regressors(self, bugs):
×
NEW
67
        regressor_to_bugs = collections.defaultdict(list)
×
NEW
68
        for bug in bugs.values():
×
NEW
69
            regressor_to_bugs[bug["regressor_id"]].append(bug)
×
70

NEW
71
        def bug_handler(regressor_bug):
×
NEW
72
            if regressor_bug.get("groups"):
×
NEW
73
                regressor_bug_id = str(regressor_bug["id"])
×
NEW
74
                self.private_regressor_ids.add(regressor_bug_id)
×
75

NEW
76
            for bug in regressor_to_bugs[regressor_bug["id"]]:
×
NEW
77
                bug["regressor_author_email"] = regressor_bug["assigned_to"]
×
NEW
78
                bug["regressor_author_nickname"] = regressor_bug["assigned_to_detail"][
×
79
                    "nick"
80
                ]
81

NEW
82
        Bugzilla(
×
83
            bugids={bug["regressor_id"] for bug in bugs.values()},
84
            bughandler=bug_handler,
85
            include_fields=["id", "assigned_to", "groups"],
86
        ).get_data().wait()
87

NEW
88
    def filter_bugs(self, bugs):
×
89
        # TODO: Attempt to needinfo the triage owner instead of ignoring the bugs
90
        # Exclude bugs whose regressor author is nobody.
NEW
91
        for bug in list(bugs.values()):
×
NEW
92
            if utils.is_no_assignee(bug["regressor_author_email"]):
×
NEW
93
                logger.warning(
×
94
                    "Bug {}, regressor of bug {}, doesn't have an author".format(
95
                        bug["regressor_id"], bug["id"]
96
                    )
97
                )
NEW
98
                del bugs[bug["id"]]
×
99

100
        # Exclude bugs where the regressor author is inactive or blocked needinfo.
101
        # TODO: We can drop this when https://github.com/mozilla/bugbot/issues/1465 is implemented.
NEW
102
        users_info = UserActivity(include_fields=["groups", "requests"]).check_users(
×
103
            set(bug["regressor_author_email"] for bug in bugs.values()),
104
            keep_active=True,
105
            fetch_employee_info=True,
106
        )
107

NEW
108
        for bug_id, bug in list(bugs.items()):
×
NEW
109
            user_info = users_info[bug["regressor_author_email"]]
×
NEW
110
            if (
×
111
                user_info["status"] != UserStatus.ACTIVE
112
                or user_info["requests"]["needinfo"]["blocked"]
113
            ):
NEW
114
                del bugs[bug_id]
×
115

NEW
116
        return bugs
×
117

NEW
118
    def get_extra_for_needinfo_template(self):
×
NEW
119
        return self.extra_ni
×
120

NEW
121
    def get_extra_for_template(self):
×
NEW
122
        return self.extra_ni
×
123

NEW
124
    def set_autofix(self, bugs):
×
NEW
125
        for bugid, info in bugs.items():
×
NEW
126
            self.extra_ni[bugid] = {"regressor_id": str(info["regressor_id"])}
×
NEW
127
            self.add_auto_ni(
×
128
                bugid,
129
                {
130
                    "mail": info["regressor_author_email"],
131
                    "nickname": info["regressor_author_nickname"],
132
                },
133
            )
134

NEW
135
    def get_bugs(self, *args, **kwargs):
×
NEW
136
        bugs = super().get_bugs(*args, **kwargs)
×
NEW
137
        self.retrieve_regressors(bugs)
×
NEW
138
        bugs = self.filter_bugs(bugs)
×
NEW
139
        self.set_autofix(bugs)
×
NEW
140
        return bugs
×
141

NEW
142
    def set_needinfo(self):
×
NEW
143
        res = super().set_needinfo()
×
NEW
144
        for bug_id, needinfo_action in res.items():
×
NEW
145
            needinfo_action["comment"]["is_private"] = (
×
146
                bug_id in self.private_regressor_ids
147
            )
148

NEW
149
        return res
×
150

151

NEW
152
if __name__ == "__main__":
×
NEW
153
    PerfAlertInactiveRegression().run()
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc