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

mozilla / relman-auto-nag / #4519

pending completion
#4519

push

coveralls-python

web-flow
[no_severity] Drop constraint on very old bugs (#2066)

641 of 3228 branches covered (19.86%)

1817 of 8043 relevant lines covered (22.59%)

0.23 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
import numpy
×
6
from libmozdata import utils as lmdutils
×
7

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

14

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

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

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

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

47
    def nag_preamble(self):
×
48
        return """<p>
×
49
  <ul>
50
    <li><a href="https://firefox-source-docs.mozilla.org/bug-mgmt/policies/triage-bugzilla.html#why-triage">Why triage?</a></li>
51
    <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>
52
    <li><a href="https://firefox-source-docs.mozilla.org/bug-mgmt/guides/priority.html">Priority definitions</a></li>
53
    <li><a href="https://firefox-source-docs.mozilla.org/bug-mgmt/guides/severity.html">Severty definitions</a></li>
54
  </ul>
55
</p>"""
56

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

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

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

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

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

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

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

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

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

94
        return None
×
95

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

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

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

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

280
        return params
×
281

282

283
if __name__ == "__main__":
×
284
    NoSeverity("first").run()
×
285
    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