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

mozilla / relman-auto-nag / #5178

25 Jul 2024 08:29PM UTC coverage: 21.692% (+0.01%) from 21.68%
#5178

push

coveralls-python

web-flow
Removed code for triaging old bugs with no severity set (#2454)

Fixes #1596

585 of 3503 branches covered (16.7%)

1933 of 8911 relevant lines covered (21.69%)

0.22 hits per line

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

0.0
/bugbot/rules/workflow/no_severity.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

6
import numpy
×
7
from libmozdata import utils as lmdutils
×
8

9
from bugbot import utils
×
10
from bugbot.bzcleaner import BzCleaner
×
11
from bugbot.escalation import Escalation
×
12
from bugbot.nag_me import Nag
×
13
from bugbot.round_robin import RoundRobin
×
14

15

16
class NoSeverity(BzCleaner, Nag):
×
17
    def __init__(self, typ, inactivity_days: int = 4):
×
18
        """Constructor
19

20
        Args:
21
            typ: the mode that the rule should run with (first or second). Nag
22
                emails will be sent only if `typ` is second.
23
            inactivity_days: number of days that a bug should be inactive before
24
                being considered.
25
        """
26
        super(NoSeverity, self).__init__()
×
27
        assert typ in {"first", "second"}
×
28
        self.typ = typ
×
29
        self.lookup_first = utils.get_config(self.name(), "first-step", 2)
×
30
        self.lookup_second = utils.get_config(self.name(), "second-step", 4)
×
31
        self.escalation = Escalation(
×
32
            self.people,
33
            data=utils.get_config(self.name(), "escalation-{}".format(typ)),
34
            skiplist=utils.get_config("workflow", "supervisor_skiplist", []),
35
        )
36
        self.round_robin = RoundRobin.get_instance()
×
37
        self.components_skiplist = utils.get_config("workflow", "components_skiplist")
×
38
        self.activity_date = str(
×
39
            numpy.busday_offset(lmdutils.get_date("today"), -inactivity_days)
40
        )
41

42
    def description(self):
×
43
        return "Bugs without a severity or statuses set"
×
44

45
    def nag_template(self):
×
46
        return self.template()
×
47

48
    def nag_preamble(self):
×
49
        return """<p>
×
50
  <ul>
51
    <li><a href="https://firefox-source-docs.mozilla.org/bug-mgmt/policies/triage-bugzilla.html#why-triage">Why triage?</a></li>
52
    <li><a href="https://firefox-source-docs.mozilla.org/bug-mgmt/policies/triage-bugzilla.html#what-do-you-triage">What do you triage?</a></li>
53
    <li><a href="https://firefox-source-docs.mozilla.org/bug-mgmt/guides/priority.html">Priority definitions</a></li>
54
    <li><a href="https://firefox-source-docs.mozilla.org/bug-mgmt/guides/severity.html">Severity definitions</a></li>
55
  </ul>
56
</p>"""
57

58
    def get_extra_for_template(self):
×
59
        return {
×
60
            "nweeks": self.lookup_first if self.typ == "first" else self.lookup_second
61
        }
62

63
    def get_extra_for_needinfo_template(self):
×
64
        return self.get_extra_for_template()
×
65

66
    def get_extra_for_nag_template(self):
×
67
        return self.get_extra_for_template()
×
68

69
    def has_product_component(self):
×
70
        return True
×
71

72
    def ignore_meta(self):
×
73
        return True
×
74

75
    def columns(self):
×
76
        return ["product", "component", "id", "summary"]
×
77

78
    def handle_bug(self, bug, data):
×
79
        if (
×
80
            # check if the product::component is in the list
81
            utils.check_product_component(self.components_skiplist, bug)
82
            or utils.get_last_no_bot_comment_date(bug) > self.activity_date
83
        ):
84
            return None
×
85
        return bug
×
86

87
    def get_mail_to_auto_ni(self, bug):
×
88
        if self.typ == "second":
×
89
            return None
×
90

91
        mail, nick = self.round_robin.get(bug, self.date)
×
92
        if mail and nick:
×
93
            return {"mail": mail, "nickname": nick}
×
94

95
        return None
×
96

97
    def set_people_to_nag(self, bug, buginfo):
×
98
        priority = "default"
×
99
        if not self.filter_bug(priority):
×
100
            return None
×
101

102
        # don't nag in the first step (just a ni is enough)
103
        if self.typ == "first":
×
104
            return bug
×
105

106
        owners = self.round_robin.get(bug, self.date, only_one=False, has_nick=False)
×
107
        real_owner = bug["triage_owner"]
×
108
        self.add_triage_owner(owners, real_owner=real_owner)
×
109
        if not self.add(owners, buginfo, priority=priority):
×
110
            self.add_no_manager(buginfo["id"])
×
111
        return bug
×
112

113
    def get_bz_params(self, date):
×
114
        fields = [
×
115
            "triage_owner",
116
            "flags",
117
            "comments.creator",
118
            "comments.creation_time",
119
        ]
120
        params = {
×
121
            "include_fields": fields,
122
            "keywords": "intermittent-failure",
123
            "keywords_type": "nowords",
124
            "email2": "wptsync@mozilla.bugs",
125
            "emailreporter2": "1",
126
            "emailtype2": "notequals",
127
            "resolution": "---",
128
            "f31": "bug_type",
129
            "o31": "equals",
130
            "v31": "defect",
131
            "f32": "flagtypes.name",
132
            "o32": "notsubstring",
133
            "v32": "needinfo?",
134
            "f33": "bug_severity",
135
            "o33": "anyexact",
136
            "v33": "--, n/a",
137
        }
138
        self.date = lmdutils.get_date_ymd(date)
×
139
        first = f"-{self.lookup_first * 7}d"
×
140
        second = f"-{self.lookup_second * 7}d"
×
141
        if self.typ == "first":
×
142
            # TODO: change this when https://bugzilla.mozilla.org/1543984 will be fixed
143
            # Here we have to get bugs where product/component have been set (bug has been triaged)
144
            # between 4 and 2 weeks
145
            # If the product/component never changed after bug creation, we need to get them too
146
            # (second < p < first && c < first) ||
147
            # (second < c < first && p < first) ||
148
            # ((second < creation < first) && pc never changed)
149
            params.update(
×
150
                {
151
                    "f2": "flagtypes.name",
152
                    "o2": "notequals",
153
                    "v2": "needinfo?",
154
                    "j3": "OR",
155
                    "f3": "OP",
156
                    "j4": "AND",
157
                    "f4": "OP",
158
                    "n5": 1,  # we use a negation here to be sure that no change after first
159
                    "f5": "product",
160
                    "o5": "changedafter",
161
                    "v5": first,
162
                    "f6": "product",  # here the bug has changed
163
                    "o6": "changedafter",
164
                    "v6": second,
165
                    "n7": 1,
166
                    "f7": "component",
167
                    "o7": "changedafter",
168
                    "v7": first,
169
                    "f8": "CP",
170
                    "j9": "AND",
171
                    "f9": "OP",
172
                    "n10": 1,
173
                    "f10": "component",
174
                    "o10": "changedafter",
175
                    "v10": first,
176
                    "f11": "component",
177
                    "o11": "changedafter",
178
                    "v11": second,
179
                    "n12": 1,
180
                    "f12": "product",
181
                    "o12": "changedafter",
182
                    "v12": first,
183
                    "f13": "CP",
184
                    "j14": "AND",
185
                    "f14": "OP",
186
                    "f15": "creation_ts",
187
                    "o15": "lessthaneq",
188
                    "v15": first,
189
                    "f16": "creation_ts",
190
                    "o16": "greaterthan",
191
                    "v16": second,
192
                    "n17": 1,
193
                    "f17": "product",
194
                    "o17": "everchanged",
195
                    "n18": 1,
196
                    "f18": "component",
197
                    "o18": "everchanged",
198
                    "f19": "CP",
199
                    "j20": "OR",
200
                    "f20": "OP",
201
                    "f21": "bug_severity",
202
                    "o21": "changedfrom",
203
                    "v21": "critical",
204
                    "f22": "bug_severity",
205
                    "o22": "changedfrom",
206
                    "v22": "major",
207
                    "f23": "bug_severity",
208
                    "o23": "changedfrom",
209
                    "v23": "blocker",
210
                    "f24": "CP",
211
                    "f30": "CP",
212
                }
213
            )
214
        else:
215
            params.update(
×
216
                {
217
                    "j2": "OR",
218
                    "f2": "OP",
219
                    "j3": "AND",
220
                    "f3": "OP",
221
                    "f4": "product",
222
                    "o4": "changedbefore",
223
                    "v4": second,
224
                    "n5": 1,
225
                    "f5": "product",
226
                    "o5": "changedafter",
227
                    "v5": second,
228
                    "n6": 1,
229
                    "f6": "component",
230
                    "o6": "changedafter",
231
                    "v6": second,
232
                    "f7": "CP",
233
                    "j8": "AND",
234
                    "f8": "OP",
235
                    "f9": "component",
236
                    "o9": "changedbefore",
237
                    "v9": second,
238
                    "n10": 1,
239
                    "f10": "product",
240
                    "o10": "changedafter",
241
                    "v10": second,
242
                    "n11": 1,
243
                    "f11": "component",
244
                    "o11": "changedafter",
245
                    "v11": second,
246
                    "f12": "CP",
247
                    "j13": "AND",
248
                    "f13": "OP",
249
                    "f14": "creation_ts",
250
                    "o14": "lessthaneq",
251
                    "v14": second,
252
                    "n15": 1,
253
                    "f15": "product",
254
                    "o15": "everchanged",
255
                    "n16": 1,
256
                    "f16": "component",
257
                    "o16": "everchanged",
258
                    "f17": "CP",
259
                    "f18": "CP",
260
                    "n20": 1,
261
                    "j20": "OR",
262
                    "f20": "OP",
263
                    "f21": "bug_severity",
264
                    "o21": "changedfrom",
265
                    "v21": "critical",
266
                    "f22": "bug_severity",
267
                    "o22": "changedfrom",
268
                    "v22": "major",
269
                    "f23": "bug_severity",
270
                    "o23": "changedfrom",
271
                    "v23": "blocker",
272
                    "f30": "CP",
273
                }
274
            )
275

276
        return params
×
277

278

279
if __name__ == "__main__":
×
280
    NoSeverity("first").run()
×
281
    NoSeverity("second").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