4
4
import sys
5
5
from datetime import datetime , timedelta , timezone
6
6
from enum import Enum
7
- from statistics import median
8
7
from typing import Dict , List , Tuple
9
8
10
9
import structlog
21
20
CodeLockdownConfig ,
22
21
IssueThresholds ,
23
22
)
24
- from buildscripts .monitor_build_status .evergreen_service import (
25
- EvergreenService ,
26
- TaskStatusCounts ,
27
- )
28
23
from buildscripts .monitor_build_status .issue_report import IssueCategory , IssueReport
29
24
from buildscripts .monitor_build_status .jira_service import JiraService
30
25
from buildscripts .resmokelib .utils .evergreen_conn import get_evergreen_api
40
35
DEFAULT_REPO = "10gen/mongo"
41
36
DEFAULT_BRANCH = "master"
42
37
SLACK_CHANNEL = "#10gen-mongo-code-lockdown"
43
- EVERGREEN_LOOKBACK_DAYS = 14
44
38
45
39
46
40
# filter 53085 is all issues in scope
@@ -77,44 +71,24 @@ class MonitorBuildStatusOrchestrator:
77
71
def __init__ (
78
72
self ,
79
73
jira_service : JiraService ,
80
- evg_service : EvergreenService ,
74
+ evg_api : EvergreenApi ,
81
75
code_lockdown_config : CodeLockdownConfig ,
82
76
) -> None :
83
77
self .jira_service = jira_service
84
- self .evg_service = evg_service
78
+ self .evg_api = evg_api
85
79
self .code_lockdown_config = code_lockdown_config
86
80
87
81
def evaluate_build_redness (self , repo : str , branch : str , notify : bool ) -> None :
88
- status_message = f"\n `[STATUS]` '{ repo } ' repo '{ branch } ' branch"
82
+ status_message = f"\n `[STATUS]` Issue count for '{ repo } ' repo '{ branch } ' branch"
89
83
scope_percentages : Dict [str , List [float ]] = {}
90
84
91
- LOGGER .info ("Getting Evergreen projects data" )
92
- evg_projects_info = self .evg_service .get_evg_project_info (repo , branch )
93
- evg_project_names = evg_projects_info .branch_to_projects_map [branch ]
94
- LOGGER .info ("Got Evergreen projects data" )
95
-
96
85
issue_report = self ._make_report ()
97
86
issue_count_status_msg , issue_count_percentages = self ._get_issue_counts_status (
98
87
issue_report , self .code_lockdown_config
99
88
)
100
89
status_message = f"{ status_message } \n { issue_count_status_msg } \n "
101
90
scope_percentages .update (issue_count_percentages )
102
91
103
- # We are looking for Evergreen versions that started before the beginning of yesterday
104
- # to give them time to complete
105
- window_end = datetime .utcnow ().replace (
106
- hour = 0 , minute = 0 , second = 0 , microsecond = 0 , tzinfo = timezone .utc
107
- ) - timedelta (days = 1 )
108
- window_start = window_end - timedelta (days = EVERGREEN_LOOKBACK_DAYS )
109
-
110
- waterfall_report = self ._make_waterfall_report (
111
- evg_project_names = evg_project_names , window_end = window_end
112
- )
113
- waterfall_failure_rate_status_msg = self ._get_waterfall_redness_status (
114
- waterfall_report = waterfall_report , window_start = window_start , window_end = window_end
115
- )
116
- status_message = f"{ status_message } \n { waterfall_failure_rate_status_msg } \n "
117
-
118
92
summary = self ._summarize (scope_percentages )
119
93
status_message = f"{ status_message } \n { summary } "
120
94
@@ -123,7 +97,7 @@ def evaluate_build_redness(self, repo: str, branch: str, notify: bool) -> None:
123
97
124
98
if notify :
125
99
LOGGER .info ("Notifying slack channel with results" , slack_channel = SLACK_CHANNEL )
126
- self .evg_service . evg_api .send_slack_message (
100
+ self .evg_api .send_slack_message (
127
101
target = SLACK_CHANNEL ,
128
102
msg = status_message .strip (),
129
103
)
@@ -148,7 +122,6 @@ def _get_issue_counts_status(
148
122
now = datetime .utcnow ().replace (tzinfo = timezone .utc )
149
123
percentages : Dict [str , List [float ]] = {}
150
124
151
- status_message = "`[STATUS]` The current issue count"
152
125
headers = ["Scope" , "Hot Issues" , "Cold Issues" ]
153
126
table_data = []
154
127
@@ -234,81 +207,9 @@ def _process_thresholds(
234
207
table_str = tabulate (
235
208
table_data , headers , tablefmt = "outline" , colalign = ("left" , "right" , "right" )
236
209
)
237
- status_message = f"{ status_message } \n ```\n { table_str } \n ```"
238
-
239
- return status_message , percentages
240
-
241
- def _make_waterfall_report (
242
- self , evg_project_names : List [str ], window_end : datetime
243
- ) -> Dict [str , List [TaskStatusCounts ]]:
244
- task_status_counts = []
245
- for day in range (EVERGREEN_LOOKBACK_DAYS ):
246
- day_window_end = window_end - timedelta (days = day )
247
- day_window_start = day_window_end - timedelta (days = 1 )
248
- LOGGER .info (
249
- "Getting Evergreen waterfall data" ,
250
- projects = evg_project_names ,
251
- window_start = day_window_start .isoformat (),
252
- window_end = day_window_end .isoformat (),
253
- )
254
- waterfall_status = self .evg_service .get_waterfall_status (
255
- evg_project_names = evg_project_names ,
256
- window_start = day_window_start ,
257
- window_end = day_window_end ,
258
- )
259
- task_status_counts .extend (
260
- self ._accumulate_project_statuses (evg_project_names , waterfall_status )
261
- )
210
+ message = f"```\n { table_str } \n ```"
262
211
263
- waterfall_report = {evg_project_name : [] for evg_project_name in evg_project_names }
264
- for task_status_count in task_status_counts :
265
- waterfall_report [task_status_count .project ].append (task_status_count )
266
-
267
- return waterfall_report
268
-
269
- @staticmethod
270
- def _accumulate_project_statuses (
271
- evg_project_names : List [str ], build_statuses : List [TaskStatusCounts ]
272
- ) -> List [TaskStatusCounts ]:
273
- project_statuses = []
274
-
275
- for evg_project_name in evg_project_names :
276
- project_status = TaskStatusCounts (project = evg_project_name )
277
- for build_status in build_statuses :
278
- if build_status .project == evg_project_name :
279
- project_status = project_status .add (build_status )
280
- project_statuses .append (project_status )
281
-
282
- return project_statuses
283
-
284
- @staticmethod
285
- def _get_waterfall_redness_status (
286
- waterfall_report : Dict [str , List [TaskStatusCounts ]],
287
- window_start : datetime ,
288
- window_end : datetime ,
289
- ) -> str :
290
- date_format = "%Y-%m-%d"
291
- status_message = (
292
- f"`[STATUS]` Evergreen waterfall red and purple boxes median count per day"
293
- f" between { window_start .strftime (date_format )} "
294
- f" and { window_end .strftime (date_format )} "
295
- )
296
-
297
- for evg_project_name , daily_task_status_counts in waterfall_report .items ():
298
- daily_per_project_red_box_counts = [
299
- task_status_counts .failed for task_status_counts in daily_task_status_counts
300
- ]
301
- LOGGER .info (
302
- "Daily per project red box counts" ,
303
- project = evg_project_name ,
304
- daily_red_box_counts = daily_per_project_red_box_counts ,
305
- )
306
- median_per_day_red_box_count = median (daily_per_project_red_box_counts )
307
- status_message = (
308
- f"{ status_message } \n { evg_project_name } : { median_per_day_red_box_count :.0f} "
309
- )
310
-
311
- return status_message
212
+ return message , percentages
312
213
313
214
@staticmethod
314
215
def _summarize (scope_percentages : Dict [str , List [float ]]) -> str :
@@ -344,18 +245,13 @@ def main(
344
245
] = False , # default to the more "quiet" setting
345
246
) -> None :
346
247
"""
347
- Analyze Jira BFs count and Evergreen redness data .
248
+ Analyze Jira BFs count for redness reports .
348
249
349
- For Jira API authentication please use `JIRA_AUTH_PAT` env variable.
250
+ For Jira API authentication, use `JIRA_AUTH_PAT` env variable.
350
251
More about Jira Personal Access Tokens (PATs) here:
351
252
352
253
- https://wiki.corp.mongodb.com/pages/viewpage.action?pageId=218995581
353
254
354
- For Evergreen API authentication please create `~/.evergreen.yml`.
355
- More about Evergreen auth here:
356
-
357
- - https://spruce.mongodb.com/preferences/cli
358
-
359
255
Example:
360
256
361
257
JIRA_AUTH_PAT=<auth-token> python buildscripts/monitor_build_status/cli.py --help
@@ -366,11 +262,10 @@ def main(
366
262
evg_api = get_evergreen_api ()
367
263
368
264
jira_service = JiraService (jira_client = jira_client )
369
- evg_service = EvergreenService (evg_api = evg_api )
370
265
code_lockdown_config = CodeLockdownConfig .from_yaml_config (CODE_LOCKDOWN_CONFIG )
371
266
orchestrator = MonitorBuildStatusOrchestrator (
372
267
jira_service = jira_service ,
373
- evg_service = evg_service ,
268
+ evg_api = evg_api ,
374
269
code_lockdown_config = code_lockdown_config ,
375
270
)
376
271
0 commit comments