Skip to content

Commit 7beccf8

Browse files
authored
Add the computed webcompat score to the user story (#2666)
This allows easilly assessing the actual computed impact score for each webcompat bug, without either needing to install the extension or go to BigQuery/ReDash and look at an SQL query.
1 parent d45fd04 commit 7beccf8

File tree

1 file changed

+70
-11
lines changed

1 file changed

+70
-11
lines changed

bugbot/rules/webcompat_score.py

Lines changed: 70 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,19 @@
22
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
33
# You can obtain one at http://mozilla.org/MPL/2.0/.
44

5-
from typing import Any, Optional
5+
from dataclasses import dataclass
6+
from typing import Any, Iterator, Optional, cast
67

78
from bugbot import gcp
89
from bugbot.bzcleaner import BzCleaner
910

1011

12+
@dataclass
13+
class Score:
14+
bucket: str
15+
score: str
16+
17+
1118
class WebcompatScore(BzCleaner):
1219
def __init__(self):
1320
super().__init__()
@@ -22,25 +29,74 @@ def filter_no_nag_keyword(self) -> bool:
2229
def has_default_products(self) -> bool:
2330
return False
2431

32+
def parse_user_story(self, user_story: str) -> Iterator[tuple[str, str]]:
33+
"""Parse the user story assuming it's lines of the form key: value.
34+
35+
If there isn't a colon in the line we simply set value to the full line."""
36+
37+
for line in user_story.splitlines():
38+
parts = line.split(":", 1)
39+
if len(parts) == 1:
40+
yield "", parts[0]
41+
yield cast(tuple[str, str], tuple(parts))
42+
43+
def updated_user_story(self, user_story: str, score: str) -> Optional[str]:
44+
new_user_story = []
45+
has_user_impact_score = False
46+
updated_user_impact_score = False
47+
48+
for key, value in self.parse_user_story(user_story):
49+
if not key:
50+
new_user_story.append(value)
51+
continue
52+
53+
if key.strip() == "user-impact-score":
54+
if has_user_impact_score:
55+
continue
56+
has_user_impact_score = True
57+
if value.strip() != score:
58+
value = score
59+
updated_user_impact_score = True
60+
new_user_story.append(f"{key}:{value}")
61+
62+
if not has_user_impact_score:
63+
new_user_story.append(f"user-impact-score:{score}")
64+
updated_user_impact_score = True
65+
66+
if updated_user_impact_score:
67+
return "\n".join(new_user_story)
68+
69+
return None
70+
2571
def handle_bug(
2672
self, bug: dict[str, Any], data: dict[str, Any]
2773
) -> Optional[dict[str, Any]]:
2874
scored_bugs_key = bug["id"]
2975
bug_id = str(bug["id"])
3076

31-
if (
32-
scored_bugs_key in self.scored_bugs
33-
and bug["cf_webcompat_score"] != self.scored_bugs[scored_bugs_key]
34-
):
35-
self.autofix_changes[bug_id] = {
36-
"cf_webcompat_score": self.scored_bugs[scored_bugs_key]
37-
}
77+
changes = {}
78+
if scored_bugs_key in self.scored_bugs:
79+
bug_score = self.scored_bugs[scored_bugs_key]
80+
81+
if bug["cf_webcompat_score"] != bug_score.bucket:
82+
changes["cf_webcompat_score"] = bug_score.bucket
83+
84+
updated_user_story = self.updated_user_story(
85+
bug["cf_user_story"], bug_score.score
86+
)
87+
88+
if updated_user_story:
89+
changes["cf_user_story"] = updated_user_story
90+
91+
if changes:
92+
self.autofix_changes[bug_id] = changes
3893
return bug
3994

4095
return None
4196

4297
def get_bz_params(self, date) -> dict[str, Any]:
4398
fields = ["id", "cf_webcompat_score"]
99+
fields = ["id", "cf_webcompat_score", "cf_user_story"]
44100
self.scored_bugs = self.get_bug_scores()
45101
return {
46102
"include_fields": fields,
@@ -64,19 +120,22 @@ def get_bz_params(self, date) -> dict[str, Any]:
64120
"f8": "CP",
65121
}
66122

67-
def get_bug_scores(self) -> dict[int, str]:
123+
def get_bug_scores(self) -> dict[int, Score]:
68124
project = "moz-fx-dev-dschubert-wckb"
69125
dataset = "webcompat_knowledge_base"
70126

71127
client = gcp.get_bigquery_client(project, ["cloud-platform", "drive"])
72128
query = f"""
73-
SELECT bugs.number, cast(buckets.score_bucket as string) as score_bucket FROM `{project}.{dataset}.site_reports_bugzilla_buckets` as buckets
129+
SELECT bugs.number,
130+
cast(buckets.score as string) as score,
131+
cast(buckets.score_bucket as string) as bucket FROM `{project}.{dataset}.site_reports_bugzilla_buckets` as buckets
74132
JOIN `{project}.{dataset}.bugzilla_bugs` as bugs ON bugs.number = buckets.number
75133
WHERE bugs.resolution = ""
76134
"""
77135

78136
return {
79-
row["number"]: row["score_bucket"] for row in client.query(query).result()
137+
row["number"]: Score(score=row["score"], bucket=row["bucket"])
138+
for row in client.query(query).result()
80139
}
81140

82141

0 commit comments

Comments
 (0)