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

mozilla / relman-auto-nag / #5056

03 Jun 2024 08:07PM UTC coverage: 21.715% (-0.05%) from 21.762%
#5056

push

coveralls-python

benjaminmah
Updated function to find the author of the last action

716 of 3628 branches covered (19.74%)

0 of 20 new or added lines in 1 file covered. (0.0%)

1932 of 8897 relevant lines covered (21.72%)

0.22 hits per line

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

0.0
/bugbot/rules/inactive_revision.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 re
×
6

7
from dateutil.relativedelta import relativedelta
×
8
from libmozdata import utils as lmdutils
×
9
from libmozdata.phabricator import PhabricatorAPI
×
10

11
from bugbot import utils
×
12
from bugbot.bzcleaner import BzCleaner
×
13
from bugbot.user_activity import UserActivity
×
14

15
PHAB_FILE_NAME_PAT = re.compile(r"phabricator-D([0-9]+)-url\.txt")
×
16
PHAB_TABLE_PAT = re.compile(r"^\|\ \[D([0-9]+)\]\(h", flags=re.M)
×
17

18

19
class InactiveRevision(BzCleaner):
×
20
    """Bugs with patches that are waiting for review from inactive reviewers"""
21

22
    def __init__(self, old_patch_months: int = 6):
×
23
        """Constructor
24

25
        Args:
26
            old_patch_months: number of months since creation of the patch to be
27
                considered old. If the bug has an old patch, we will mention
28
                abandon the patch as an option.
29
        """
30
        super(InactiveRevision, self).__init__()
×
31
        self.phab = PhabricatorAPI(utils.get_login_info()["phab_api_key"])
×
32
        self.user_activity = UserActivity(include_fields=["nick"], phab=self.phab)
×
33
        self.ni_template = self.get_needinfo_template()
×
34
        self.old_patch_limit = (
×
35
            lmdutils.get_date_ymd("today") - relativedelta(months=old_patch_months)
36
        ).timestamp()
37

38
    def description(self):
×
39
        return "Bugs with inactive patch reviewers"
×
40

41
    def columns(self):
×
42
        return ["id", "summary", "revisions"]
×
43

44
    def get_bugs(self, date="today", bug_ids=[], chunk_size=None):
×
45
        bugs = super().get_bugs(date, bug_ids, chunk_size)
×
46

47
        rev_ids = {rev_id for bug in bugs.values() for rev_id in bug["rev_ids"]}
×
48
        revisions = self._get_revisions_with_inactive_action(list(rev_ids))
×
49

50
        for bugid, bug in list(bugs.items()):
×
51
            inactive_revs = [
×
52
                revisions[rev_id] for rev_id in bug["rev_ids"] if rev_id in revisions
53
            ]
54
            if inactive_revs:
×
55
                bug["revisions"] = inactive_revs
×
56
                self._add_needinfo(bugid, inactive_revs)
×
57
            else:
58
                del bugs[bugid]
×
59

60
        self.query_url = utils.get_bz_search_url({"bug_id": ",".join(bugs.keys())})
×
61

62
        return bugs
×
63

64
    def _add_needinfo(self, bugid: str, inactive_revs: list) -> None:
×
65
        for revision in inactive_revs:
×
66
            last_action_by, _ = self._find_last_action(revision["rev_id"])
×
67

68
            if last_action_by == "author":
×
69
                ni_mail = revision["reviewers"][0]["phab_username"]
×
70
                summary = (
×
71
                    "The last action was by the author, so needinfoing the reviewer."
72
                )
73
            elif last_action_by == "reviewer":
×
74
                ni_mail = revision["author"]["phab_username"]
×
75
                summary = (
×
76
                    "The last action was by the reviewer, so needinfoing the author."
77
                )
78
            else:
79
                continue
×
80

81
            comment = self.ni_template.render(
×
82
                revisions=[revision],
83
                nicknames=revision["author"]["nick"],
84
                reviewers_status_summary=summary,
85
                has_old_patch=revision["created_at"] < self.old_patch_limit,
86
                plural=utils.plural,
87
                documentation=self.get_documentation(),
88
            )
89

90
            self.autofix_changes[bugid] = {
×
91
                "comment": {"body": comment},
92
                "flags": [
93
                    {
94
                        "name": "needinfo",
95
                        "requestee": ni_mail,
96
                        "status": "?",
97
                        "new": "true",
98
                    }
99
                ],
100
            }
101

102
    def _find_last_action(self, revision_id):
×
NEW
103
        details = self._fetch_revision_details(revision_id)
×
104

NEW
105
        if not details:
×
NEW
106
            return None, None
×
107

NEW
108
        revision = details[0]
×
NEW
109
        author_phid = revision["fields"]["authorPHID"]
×
NEW
110
        reviewers = [
×
111
            reviewer["reviewerPHID"]
112
            for reviewer in revision["attachments"]["reviewers"]["reviewers"]
113
        ]
114

NEW
115
        transactions = self._fetch_revision_transactions(revision["phid"])
×
116

NEW
117
        last_transaction = None
×
NEW
118
        for transaction in transactions:
×
NEW
119
            if (
×
120
                last_transaction is None
121
                or transaction["dateCreated"] > last_transaction["dateCreated"]
122
            ):
NEW
123
                last_transaction = transaction
×
124

NEW
125
        if last_transaction:
×
NEW
126
            last_action_by_phid = last_transaction["authorPHID"]
×
NEW
127
            if last_action_by_phid == author_phid:
×
NEW
128
                last_action_by = "author"
×
NEW
129
            elif last_action_by_phid in reviewers:
×
NEW
130
                last_action_by = "reviewer"
×
131
            else:
NEW
132
                last_action_by = "other"
×
133
        else:
NEW
134
            last_action_by = "unknown"
×
135

NEW
136
        return last_action_by, last_transaction
×
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