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

mozilla / relman-auto-nag / #5336

13 Nov 2024 04:40PM UTC coverage: 21.321% (+0.02%) from 21.301%
#5336

push

coveralls-python

gmierz
Rework rule to gather comments/history in handle_bug.

426 of 2936 branches covered (14.51%)

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

1 existing line in 1 file now uncovered.

1943 of 9113 relevant lines covered (21.32%)

0.21 hits per line

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

0.0
/bugbot/rules/perfalert_resolved_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

5
from libmozdata import utils as lmdutils
×
NEW
6
from libmozdata.bugzilla import BugzillaUser
×
7

8
from bugbot.bzcleaner import BzCleaner
×
9
from bugbot.constants import BOT_MAIN_ACCOUNT
×
10

11
DEFAULT_RESOLUTION_COMMENT = "No resolution comment provided."
×
12

13

14
class PerfAlertResolvedRegression(BzCleaner):
×
15
    def __init__(self, *args, **kwargs):
×
16
        super().__init__(*args, **kwargs)
×
17
        self.extra_email_info = {}
×
18
        self.extra_ni = {}
×
19

20
    def description(self):
×
21
        return "PerfAlert regressions whose resolution has changed recently"
×
22

NEW
23
    def get_extra_for_template(self):
×
NEW
24
        return self.extra_email_info
×
25

NEW
26
    def get_extra_for_needinfo_template(self):
×
NEW
27
        return self.extra_ni
×
28

29
    def get_bz_params(self, date):
×
30
        fields = [
×
31
            "id",
32
            "history",
33
            "comments.text",
34
            "comments.creation_time",
35
            "comments.author",
36
        ]
37

38
        # Find all bugs that have perf-alert, and regression in their keywords. Search
39
        # for bugs that have been changed in the last day. Only look for bugs after
40
        # October 1st, 2024 to prevent triggering comments on older performance regressions
41
        params = {
×
42
            "include_fields": fields,
43
            "f3": "creation_ts",
44
            "o3": "greaterthan",
45
            "v3": "2024-10-01T00:00:00Z",
46
            "f1": "regressed_by",
47
            "o1": "isnotempty",
48
            "f2": "keywords",
49
            "o2": "allwords",
50
            "v2": ["regression", "perf-alert"],
51
            "f4": "resolution",
52
            "o4": "changedafter",
53
            "v4": date,
54
        }
55

56
        return params
×
57

NEW
58
    def get_resolution_history(self, bug):
×
NEW
59
        bug_info = {}
×
60

61
        # Get the last resolution change that was made in this bug
62
        for change in bug["history"][::-1]:
×
63
            # Get the most recent resolution change first, this is because
64
            # it could have changed since the status was changed and by who
65
            if not bug_info.get("resolution"):
×
66
                for specific_change in change["changes"]:
×
67
                    if specific_change["field_name"] == "resolution":
×
68
                        bug_info["resolution"] = specific_change["added"]
×
69
                        bug_info["resolution_previous"] = (
×
70
                            specific_change["removed"].strip() or "---"
71
                        )
72
                        bug_info["resolution_time"] = change["when"]
×
73
                        break
×
74

75
            if bug_info.get("resolution"):
×
76
                # Find the status that the bug was resolved to, and by who
77
                for specific_change in change["changes"]:
×
78
                    if specific_change["field_name"] == "status" and specific_change[
×
79
                        "added"
80
                    ] in ("RESOLVED", "REOPENED"):
81
                        bug_info["status"] = specific_change["added"]
×
82
                        bug_info["status_author"] = change["who"]
×
83
                        bug_info["status_time"] = change["when"]
×
84
                        break
×
85

86
            if bug_info.get("status"):
×
87
                break
×
88

NEW
89
        return bug_info
×
90

NEW
91
    def get_resolution_info(self, bug):
×
92
        # Match all the resolutions with resolution comments if they exist
NEW
93
        bug_id = str(bug["id"])
×
NEW
94
        bug_comments = bug["comments"]
×
NEW
95
        bug_history = self.get_resolution_history(bug)
×
96

97
        # Sometimes a resolution comment is not provided so use a default
NEW
98
        bug_history["resolution_comment"] = DEFAULT_RESOLUTION_COMMENT
×
NEW
99
        for comment in bug_comments[::-1]:
×
NEW
100
            if (
×
101
                comment["creation_time"] == bug_history["status_time"]
102
                and comment["author"] == bug_history["status_author"]
103
            ):
NEW
104
                bug_history["resolution_comment"] = comment["text"]
×
NEW
105
                break
×
106
        else:
107
            # Check if the bugbot has already needinfo'ed on the bug since
108
            # the last status change before making one
NEW
109
            skip_ni = False
×
NEW
110
            status_time = lmdutils.get_date_ymd(bug_history["status_time"])
×
NEW
111
            for comment in bug_comments[::-1]:
×
NEW
112
                if lmdutils.get_date_ymd(comment["creation_time"]) <= status_time:
×
NEW
113
                    break
×
114

NEW
115
                if comment["author"] == BOT_MAIN_ACCOUNT:
×
NEW
116
                    if (
×
117
                        "comment containing a reason for why"
118
                        "the performance regression"
119
                        in comment["text"]
120
                        or "could you provide a comment explaining the resolution?"
121
                        in comment["text"]
122
                    ):
123
                        # Bugbot has already commented on this bug since the last
124
                        # status change. No need to comment again since this was
125
                        # just a resolution change
NEW
126
                        skip_ni = True
×
127

NEW
128
            if not skip_ni:
×
NEW
129
                self.extra_ni[bug_id] = bug_history
×
130

NEW
131
        self.extra_email_info[bug_id] = bug_history
×
132

NEW
133
    def get_needinfo_nicks(self):
×
NEW
134
        if not self.extra_ni:
×
NEW
135
            return
×
136

NEW
137
        def _user_handler(user, data):
×
NEW
138
            data[user["name"]] = user.get("nick", "")
×
139

NEW
140
        user_emails_to_names = {}
×
NEW
141
        BugzillaUser(
×
142
            user_names=[bug_ni["status_author"] for bug_ni in self.extra_ni.values()],
143
            include_fields=["nick", "name"],
144
            user_handler=_user_handler,
145
            user_data=user_emails_to_names,
146
        ).wait()
147

NEW
148
        for bug_id, bug_info in self.extra_ni.items():
×
NEW
149
            if bug_info["status_author"] in user_emails_to_names:
×
NEW
150
                bug_info["nickname"] = user_emails_to_names[bug_info["status_author"]]
×
151

NEW
152
    def set_autofix(self):
×
153
        for bug_id, bug_info in self.extra_ni.items():
×
154
            self.add_auto_ni(
×
155
                bug_id,
156
                {
157
                    "mail": bug_info["status_author"],
158
                    "nickname": (
159
                        (":" + bug_info["nickname"])
160
                        if "nickname" in bug_info
161
                        else bug_info["status_author"]
162
                    ),
163
                },
164
            )
165

NEW
166
    def handle_bug(self, bug, data):
×
NEW
167
        self.get_resolution_info(bug)
×
NEW
168
        return bug
×
169

170
    def get_bugs(self, *args, **kwargs):
×
171
        bugs = super().get_bugs(*args, **kwargs)
×
NEW
172
        self.get_needinfo_nicks()
×
NEW
173
        self.set_autofix()
×
UNCOV
174
        return bugs
×
175

176

177
if __name__ == "__main__":
×
178
    PerfAlertResolvedRegression().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