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
78from bugbot import gcp
89from bugbot .bzcleaner import BzCleaner
910
1011
12+ @dataclass
13+ class Score :
14+ bucket : str
15+ score : str
16+
17+
1118class 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