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

mozilla / relman-auto-nag / #5000

09 May 2024 11:00PM CUT coverage: 21.85% (-0.002%) from 21.852%
#5000

push

coveralls-python

benjaminmah
Cleaned up code, component itself now is a link to the triage

716 of 3596 branches covered (19.91%)

1 of 7 new or added lines in 2 files covered. (14.29%)

2 existing lines in 2 files now uncovered.

1930 of 8833 relevant lines covered (21.85%)

0.22 hits per line

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

0.0
/bugbot/rules/triage_owner_rotations.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
from typing import List, Set
×
7

8
from libmozdata.bugzilla import BugzillaComponent
×
9
from requests import HTTPError
×
10
from tenacity import (
×
11
    RetryError,
12
    retry,
13
    retry_if_exception_message,
14
    stop_after_attempt,
15
    wait_exponential,
16
)
17

18
from bugbot import logger
×
19
from bugbot.bzcleaner import BzCleaner
×
20
from bugbot.component_triagers import ComponentName, ComponentTriagers, TriageOwner
×
21
from bugbot.utils import get_bug_bugdash_url
×
22

23

24
class TriageOwnerRotations(BzCleaner):
×
25
    def __init__(
×
26
        self,
27
        excluded_teams: List[str] = [
28
            "Layout",
29
            "GFX",
30
        ],
31
    ) -> None:
32
        """Constructor
33

34
        Args:
35
            excluded_teams: teams to excluded all of their components when
36
                performing the triage owner rotation.
37
        """
38
        super().__init__()
×
39
        self.component_triagers = ComponentTriagers(excluded_teams=excluded_teams)
×
40
        self.query_url = None
×
41
        self.has_put_errors = False
×
42

43
    def description(self) -> str:
×
44
        return "Triage owners that got updated"
×
45

46
    def get_extra_for_template(self):
×
47
        return {"has_put_errors": self.has_put_errors}
×
48

49
    def _update_triage_owners(
×
50
        self, new_triage_owners: List[TriageOwner]
51
    ) -> Set[ComponentName]:
52
        failures = set()
×
53
        for new_triager in new_triage_owners:
×
54
            logger.info(
×
55
                "The triage owner for '%s' will be: '%s'",
56
                new_triager.component,
57
                new_triager.bugzilla_email,
58
            )
59

60
            if not self.dryrun and not self.test_mode:
×
61
                try:
×
62
                    self._put_new_triage_owner(new_triager)
×
63
                except (HTTPError, RetryError) as err:
×
64
                    failures.add(new_triager.component)
×
65
                    logger.exception(
×
66
                        "Cannot update the triage owner for '%s' to be '%s': %s",
67
                        new_triager.component,
68
                        new_triager.bugzilla_email,
69
                        err,
70
                    )
71

72
        return failures
×
73

74
    @retry(
×
75
        retry=retry_if_exception_message(match=r"^\d{3} Server Error"),
76
        wait=wait_exponential(),
77
        stop=stop_after_attempt(3),
78
    )
79
    def _put_new_triage_owner(self, new_triager: TriageOwner) -> None:
×
80
        change = {"triage_owner": new_triager.bugzilla_email}
×
81
        BugzillaComponent(
×
82
            new_triager.component.product,
83
            new_triager.component.name,
84
        ).put(change)
85

86
    def get_email_data(self, date: str) -> List[dict]:
×
87
        new_triagers = self.component_triagers.get_new_triage_owners()
×
88
        failures = self._update_triage_owners(new_triagers)
×
89
        self.has_put_errors = len(failures) > 0
×
90

91
        return [
×
92
            {
93
                "component": new_triager.component,
94
                "old_triage_owner": self.component_triagers.get_current_triage_owner(
95
                    new_triager.component
96
                ),
97
                "new_triage_owner": new_triager.bugzilla_email,
98
                "has_put_error": new_triager.component in failures,
99
                "link_to_triage": get_bug_bugdash_url(
100
                    new_triager.component, tab_name="triage"
101
                ),
102
            }
103
            for new_triager in new_triagers
104
        ]
105

106
    def get_cc_emails(self, data: List[dict]) -> List[str]:
×
107
        cc_emails = set()
×
108
        for entry in data:
×
NEW
109
            cc_emails.add(entry.get("old_triage_owner", ""))
×
NEW
110
            cc_emails.add(entry.get("new_triage_owner", ""))
×
UNCOV
111
        return list(cc_emails)
×
112

113

114
if __name__ == "__main__":
×
115
    TriageOwnerRotations().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