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

mozilla / relman-auto-nag / #4077

pending completion
#4077

push

coveralls-python

suhaibmujahid
Merge remote-tracking branch 'upstream/master' into wiki-missed

549 of 3109 branches covered (17.66%)

615 of 615 new or added lines in 27 files covered. (100.0%)

1773 of 8016 relevant lines covered (22.12%)

0.22 hits per line

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

0.0
/auto_nag/scripts/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 auto_nag import logger
×
19
from auto_nag.bzcleaner import BzCleaner
×
20
from auto_nag.component_triagers import ComponentName, ComponentTriagers, TriageOwner
×
21

22

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

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

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

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

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

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

71
        return failures
×
72

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

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

90
        return [
×
91
            {
92
                "component": new_triager.component,
93
                "old_triage_owner": self.component_triagers.get_current_triage_owner(
94
                    new_triager.component
95
                ),
96
                "new_triage_owner": new_triager.bugzilla_email,
97
                "has_put_error": new_triager.component in failures,
98
            }
99
            for new_triager in new_triagers
100
        ]
101

102

103
if __name__ == "__main__":
×
104
    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