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

mozilla / relman-auto-nag / #4848

07 Dec 2023 02:35PM CUT coverage: 21.938%. Remained the same
#4848

push

coveralls-python

suhaibmujahid
Use `product::component` to refer to components in all emails

716 of 3588 branches covered (0.0%)

0 of 7 new or added lines in 7 files covered. (0.0%)

1924 of 8770 relevant lines covered (21.94%)

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
from datetime import datetime
×
6

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

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

16

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

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

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

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

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

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

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

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

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

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

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

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

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

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

96
        return None
×
97

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

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

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

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

277
        # TODO: the following code can be removed in 2024.
278
        # https://github.com/mozilla/bugbot/issues/1596
279
        # Almost 500 old bugs have no severity set. The intent of the following
280
        # is to have them triaged in batches where every week we include more
281
        # bugs. Once the list of old bugs are reduced, we could safely remove
282
        # the following code.
283
        passed_time = datetime.now() - datetime.fromisoformat("2023-06-09")
×
284
        oldest_bug_months = 56 + passed_time.days
×
285
        n = utils.get_last_field_num(params)
×
286
        params.update(
×
287
            {
288
                f"f{n}": "creation_ts",
289
                f"o{n}": "greaterthan",
290
                f"v{n}": f"-{oldest_bug_months}m",
291
            }
292
        )
293

294
        return params
×
295

296

297
if __name__ == "__main__":
×
298
    NoSeverity("first").run()
×
299
    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