Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(355)

Side by Side Diff: appengine/findit/handlers/build_failure.py

Issue 2361583002: [Findit] UI change and triage change for cl level trige. (Closed)
Patch Set: . Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | appengine/findit/handlers/test/build_failure_test.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright 2014 The Chromium Authors. All rights reserved. 1 # Copyright 2014 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 from collections import defaultdict 5 from collections import defaultdict
6 import copy
6 from datetime import datetime 7 from datetime import datetime
7 8
8 from google.appengine.api import users 9 from google.appengine.api import users
9 10
10 from common import constants 11 from common import constants
11 from common.base_handler import BaseHandler 12 from common.base_handler import BaseHandler
12 from common.base_handler import Permission 13 from common.base_handler import Permission
13 from common.waterfall import failure_type 14 from common.waterfall import failure_type
14 from handlers import handlers_util 15 from handlers import handlers_util
15 from handlers import result_status 16 from handlers import result_status
16 from handlers.result_status import NO_TRY_JOB_REASON_MAP 17 from handlers.result_status import NO_TRY_JOB_REASON_MAP
17 from model import analysis_status 18 from model import analysis_status
19 from model import result_status as analysis_result_status
20 from model import suspected_cl_status
21 from model.base_build_model import BaseBuildModel
22 from model.result_status import RESULT_STATUS_TO_DESCRIPTION
23 from model.suspected_cl_status import CL_STATUS_TO_DESCRIPTION
18 from model.wf_analysis import WfAnalysis 24 from model.wf_analysis import WfAnalysis
25 from model.wf_suspected_cl import WfSuspectedCL
19 from model.wf_try_job import WfTryJob 26 from model.wf_try_job import WfTryJob
20 from model.result_status import FOUND_INCORRECT
21 from model.result_status import RESULT_STATUS_TO_DESCRIPTION
22 from waterfall import build_failure_analysis_pipelines 27 from waterfall import build_failure_analysis_pipelines
23 from waterfall import buildbot 28 from waterfall import buildbot
24 from waterfall import waterfall_config 29 from waterfall import waterfall_config
25 30
26 31
27 NON_SWARMING = object() 32 NON_SWARMING = object()
28 33
29 34
35 _ANALYSIS_CL_STATUS_MAP = {
36 analysis_result_status.FOUND_CORRECT: suspected_cl_status.CORRECT,
37 analysis_result_status.FOUND_INCORRECT: suspected_cl_status.INCORRECT
38 }
39
40
30 def _FormatDatetime(dt): 41 def _FormatDatetime(dt):
31 if not dt: 42 if not dt:
32 return None 43 return None
33 else: 44 else:
34 return dt.strftime('%Y-%m-%d %H:%M:%S UTC') 45 return dt.strftime('%Y-%m-%d %H:%M:%S UTC')
35 46
36 47
48 def _GetCLDict(analysis, cl_info):
49 if not cl_info:
50 return {}
51
52 cl_keys = cl_info.split('/')
53 repo_name = cl_keys[0]
54 revision = cl_keys[1]
55 for cl in analysis.suspected_cls:
56 if cl['repo_name'] == repo_name and cl['revision'] == revision:
57 return cl
58 return {}
59
60
37 def _GetTriageHistory(analysis): 61 def _GetTriageHistory(analysis):
38 if (not users.is_current_user_admin() or 62 if (not users.is_current_user_admin() or
39 not analysis.completed or 63 not analysis.completed or
40 not analysis.triage_history): 64 not analysis.triage_history):
41 return None 65 return None
42 66
43 triage_history = [] 67 triage_history = []
44 for triage_record in analysis.triage_history: 68 for triage_record in analysis.triage_history:
45 cl_status = (FOUND_INCORRECT if triage_record.get('cl_status') == 1
46 else triage_record.get('cl_status'))
47 status = triage_record.get('result_status', cl_status)
48 triage_history.append({ 69 triage_history.append({
49 'triage_time': _FormatDatetime( 70 'triage_time': _FormatDatetime(
50 datetime.utcfromtimestamp(triage_record['triage_timestamp'])), 71 datetime.utcfromtimestamp(triage_record['triage_timestamp'])),
51 'user_name': triage_record['user_name'], 72 'user_name': triage_record['user_name'],
52 'result_status': RESULT_STATUS_TO_DESCRIPTION.get(status), 73 'triaged_cl': _GetCLDict(analysis, triage_record.get('triaged_cl')),
74 'result_status': (
75 RESULT_STATUS_TO_DESCRIPTION.get(triage_record.get('result_status'))
76 or CL_STATUS_TO_DESCRIPTION.get(triage_record.get('cl_status'))),
53 'version': triage_record.get('version'), 77 'version': triage_record.get('version'),
54 }) 78 })
55 79
56 return triage_history 80 return triage_history
57 81
58 82
59 def _GetOrganizedAnalysisResultBySuspectedCL(analysis_result): 83 def _GetOrganizedAnalysisResultBySuspectedCL(analysis_result):
60 """Group tests it they have the same suspected CLs.""" 84 """Group tests it they have the same suspected CLs."""
61 organized_results = defaultdict(list) 85 organized_results = defaultdict(list)
62 86
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after
298 compile_failure = None 322 compile_failure = None
299 for failure in analysis.result.get('failures', []): 323 for failure in analysis.result.get('failures', []):
300 if failure['step_name'] == constants.COMPILE_STEP_NAME: 324 if failure['step_name'] == constants.COMPILE_STEP_NAME:
301 compile_failure = failure 325 compile_failure = failure
302 if compile_failure: # pragma: no branch. 326 if compile_failure: # pragma: no branch.
303 data['first_failure'] = compile_failure['first_failure'] 327 data['first_failure'] = compile_failure['first_failure']
304 data['last_pass'] = compile_failure['last_pass'] 328 data['last_pass'] = compile_failure['last_pass']
305 data['suspected_cls_by_heuristic'] = compile_failure['suspected_cls'] 329 data['suspected_cls_by_heuristic'] = compile_failure['suspected_cls']
306 330
307 331
332 def _GetAllSuspectedCLsAndCheckStatus(
333 master_name, builder_name, build_number, analysis):
334 build_key = BaseBuildModel.CreateBuildId(
335 master_name, builder_name, build_number)
336 suspected_cls = copy.deepcopy(analysis.suspected_cls)
337 if not suspected_cls:
338 return []
339
340 for cl in suspected_cls:
341 cl['status'] = _ANALYSIS_CL_STATUS_MAP.get(analysis.result_status, None)
342 suspected_cl = WfSuspectedCL.Get(cl['repo_name'], cl['revision'])
343 if not suspected_cl:
344 continue
345
346 build = suspected_cl.builds.get(build_key)
347 if build:
348 cl['status'] = build['status']
349
350 return suspected_cls
351
352
308 class BuildFailure(BaseHandler): 353 class BuildFailure(BaseHandler):
309 PERMISSION_LEVEL = Permission.ANYONE 354 PERMISSION_LEVEL = Permission.ANYONE
310 355
311 def _ShowDebugInfo(self): 356 def _ShowDebugInfo(self):
312 # Show debug info only if the app is run locally during development, if the 357 # Show debug info only if the app is run locally during development, if the
313 # currently logged-in user is an admin, or if it is explicitly requested 358 # currently logged-in user is an admin, or if it is explicitly requested
314 # with parameter 'debug=1'. 359 # with parameter 'debug=1'.
315 return users.is_current_user_admin() or self.request.get('debug') == '1' 360 return users.is_current_user_admin() or self.request.get('debug') == '1'
316 361
317 def _ShowTriageHelpButton(self): 362 def _ShowTriageHelpButton(self):
(...skipping 18 matching lines...) Expand all
336 'triage_history': _GetTriageHistory(analysis), 381 'triage_history': _GetTriageHistory(analysis),
337 'show_triage_help_button': self._ShowTriageHelpButton(), 382 'show_triage_help_button': self._ShowTriageHelpButton(),
338 'triage_reference_analysis_master_name': 383 'triage_reference_analysis_master_name':
339 analysis.triage_reference_analysis_master_name, 384 analysis.triage_reference_analysis_master_name,
340 'triage_reference_analysis_builder_name': 385 'triage_reference_analysis_builder_name':
341 analysis.triage_reference_analysis_builder_name, 386 analysis.triage_reference_analysis_builder_name,
342 'triage_reference_analysis_build_number': 387 'triage_reference_analysis_build_number':
343 analysis.triage_reference_analysis_build_number 388 analysis.triage_reference_analysis_build_number
344 } 389 }
345 390
346 def _PrepareDataForCompileFailure(self, analysis): 391 def _PrepareDataForCompileFailure(self, analysis, data):
347 data = self._PrepareCommonDataForFailure(analysis)
348 392
349 # Check result from heuristic analysis. 393 # Check result from heuristic analysis.
350 _PopulateHeuristicDataForCompileFailure(analysis, data) 394 _PopulateHeuristicDataForCompileFailure(analysis, data)
351 # Check result from try job. 395 # Check result from try job.
352 data['try_job'] = _PrepareTryJobDataForCompileFailure(analysis) 396 data['try_job'] = _PrepareTryJobDataForCompileFailure(analysis)
353 397
354 return data 398 def _PrepareDataForTestFailures(self, analysis, build_info, data,
399 show_debug_info=False):
355 400
356 def _PrepareDataForTestFailures(self, analysis, build_info,
357 show_debug_info=False):
358 data = self._PrepareCommonDataForFailure(analysis)
359 data['status_message_map'] = result_status.STATUS_MESSAGE_MAP 401 data['status_message_map'] = result_status.STATUS_MESSAGE_MAP
360 402
361 organized_results = _GetOrganizedAnalysisResultBySuspectedCL( 403 organized_results = _GetOrganizedAnalysisResultBySuspectedCL(
362 analysis.result) 404 analysis.result)
363 analysis_result = _GetAnalysisResultWithTryJobInfo( 405 analysis_result = _GetAnalysisResultWithTryJobInfo(
364 show_debug_info, organized_results, *build_info) 406 show_debug_info, organized_results, *build_info)
365 407
366 data['analysis_result'] = analysis_result 408 data['analysis_result'] = analysis_result
367 return data 409 return data
368 410
(...skipping 29 matching lines...) Expand all
398 build_completed = (users.is_current_user_admin() and 440 build_completed = (users.is_current_user_admin() and
399 self.request.get('build_completed') == '1') 441 self.request.get('build_completed') == '1')
400 force_try_job = (users.is_current_user_admin() and 442 force_try_job = (users.is_current_user_admin() and
401 self.request.get('force_try_job') == '1') 443 self.request.get('force_try_job') == '1')
402 analysis = build_failure_analysis_pipelines.ScheduleAnalysisIfNeeded( 444 analysis = build_failure_analysis_pipelines.ScheduleAnalysisIfNeeded(
403 master_name, builder_name, build_number, 445 master_name, builder_name, build_number,
404 build_completed=build_completed, force=force, 446 build_completed=build_completed, force=force,
405 force_try_job=force_try_job, 447 force_try_job=force_try_job,
406 queue_name=constants.WATERFALL_ANALYSIS_QUEUE) 448 queue_name=constants.WATERFALL_ANALYSIS_QUEUE)
407 449
450 data = self._PrepareCommonDataForFailure(analysis)
451 data['suspected_cls'] = _GetAllSuspectedCLsAndCheckStatus(
452 master_name, builder_name, build_number, analysis)
453
408 if analysis.failure_type == failure_type.COMPILE: 454 if analysis.failure_type == failure_type.COMPILE:
455 self._PrepareDataForCompileFailure(analysis, data)
409 return { 456 return {
410 'template': 'waterfall/compile_failure.html', 457 'template': 'waterfall/compile_failure.html',
411 'data': self._PrepareDataForCompileFailure(analysis), 458 'data': data
412 } 459 }
413 else: 460 else:
461 self._PrepareDataForTestFailures(
462 analysis, build_info, data, self._ShowDebugInfo())
414 return { 463 return {
415 'template': 'waterfall/test_failure.html', 464 'template': 'waterfall/test_failure.html',
416 'data': self._PrepareDataForTestFailures(analysis, build_info, 465 'data': data
417 self._ShowDebugInfo()),
418 } 466 }
419 467
420 def HandlePost(self): # pragma: no cover 468 def HandlePost(self): # pragma: no cover
421 return self.HandleGet() 469 return self.HandleGet()
OLDNEW
« no previous file with comments | « no previous file | appengine/findit/handlers/test/build_failure_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698