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

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: rebase 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
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 cl_confidence
20 from model import result_status as analysis_result_status
21 from model import suspected_cl_status
22 from model.base_build_model import BaseBuildModel
23 from model.result_status import RESULT_STATUS_TO_DESCRIPTION
24 from model.suspected_cl_status import CL_STATUS_TO_DESCRIPTION
18 from model.wf_analysis import WfAnalysis 25 from model.wf_analysis import WfAnalysis
26 from model.wf_suspected_cl import WfSuspectedCL
19 from model.wf_try_job import WfTryJob 27 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 28 from waterfall import build_failure_analysis_pipelines
23 from waterfall import buildbot 29 from waterfall import buildbot
24 from waterfall import waterfall_config 30 from waterfall import waterfall_config
25 31
26 32
27 NON_SWARMING = object() 33 NON_SWARMING = object()
28 34
29 35
36 _ANALYSIS_CL_STATUS_MAP = {
37 analysis_result_status.FOUND_CORRECT: suspected_cl_status.CORRECT,
38 analysis_result_status.FOUND_INCORRECT: suspected_cl_status.INCORRECT
39 }
40
41
30 def _FormatDatetime(dt): 42 def _FormatDatetime(dt):
31 if not dt: 43 if not dt:
32 return None 44 return None
33 else: 45 else:
34 return dt.strftime('%Y-%m-%d %H:%M:%S UTC') 46 return dt.strftime('%Y-%m-%d %H:%M:%S UTC')
35 47
36 48
49 def _GetCLDict(analysis, cl_info):
50 if not cl_info:
51 return {}
52
53 cl_keys = cl_info.split('/')
54 repo_name = cl_keys[0]
55 revision = cl_keys[1]
56 for cl in analysis.suspected_cls:
57 if cl['repo_name'] == repo_name and cl['revision'] == revision:
58 return cl
59 return {}
60
61
37 def _GetTriageHistory(analysis): 62 def _GetTriageHistory(analysis):
38 if (not users.is_current_user_admin() or 63 if (not users.is_current_user_admin() or
39 not analysis.completed or 64 not analysis.completed or
40 not analysis.triage_history): 65 not analysis.triage_history):
41 return None 66 return None
42 67
43 triage_history = [] 68 triage_history = []
44 for triage_record in analysis.triage_history: 69 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({ 70 triage_history.append({
49 'triage_time': _FormatDatetime( 71 'triage_time': _FormatDatetime(
50 datetime.utcfromtimestamp(triage_record['triage_timestamp'])), 72 datetime.utcfromtimestamp(triage_record['triage_timestamp'])),
51 'user_name': triage_record['user_name'], 73 'user_name': triage_record['user_name'],
52 'result_status': RESULT_STATUS_TO_DESCRIPTION.get(status), 74 'triaged_cl': _GetCLDict(analysis, triage_record.get('triaged_cl')),
75 'result_status': (
76 RESULT_STATUS_TO_DESCRIPTION.get(triage_record.get('result_status'))
77 or CL_STATUS_TO_DESCRIPTION.get(triage_record.get('cl_status'))),
53 'version': triage_record.get('version'), 78 'version': triage_record.get('version'),
54 }) 79 })
55 80
56 return triage_history 81 return triage_history
57 82
58 83
59 def _GetOrganizedAnalysisResultBySuspectedCL(analysis_result): 84 def _GetOrganizedAnalysisResultBySuspectedCL(analysis_result):
60 """Group tests it they have the same suspected CLs.""" 85 """Group tests it they have the same suspected CLs."""
61 organized_results = defaultdict(list) 86 organized_results = defaultdict(list)
62 87
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after
298 compile_failure = None 323 compile_failure = None
299 for failure in analysis.result.get('failures', []): 324 for failure in analysis.result.get('failures', []):
300 if failure['step_name'] == constants.COMPILE_STEP_NAME: 325 if failure['step_name'] == constants.COMPILE_STEP_NAME:
301 compile_failure = failure 326 compile_failure = failure
302 if compile_failure: # pragma: no branch. 327 if compile_failure: # pragma: no branch.
303 data['first_failure'] = compile_failure['first_failure'] 328 data['first_failure'] = compile_failure['first_failure']
304 data['last_pass'] = compile_failure['last_pass'] 329 data['last_pass'] = compile_failure['last_pass']
305 data['suspected_cls_by_heuristic'] = compile_failure['suspected_cls'] 330 data['suspected_cls_by_heuristic'] = compile_failure['suspected_cls']
306 331
307 332
333 def _GetAllSuspectedCLsAndCheckStatus(
334 master_name, builder_name, build_number, analysis):
335 build_key = BaseBuildModel.CreateBuildId(
336 master_name, builder_name, build_number)
337 suspected_cls = copy.deepcopy(analysis.suspected_cls)
338 if not suspected_cls:
339 return []
340
341 for cl in suspected_cls:
342 cl['status'] = _ANALYSIS_CL_STATUS_MAP.get(analysis.result_status, None)
343 suspected_cl = WfSuspectedCL.Get(cl['repo_name'], cl['revision'])
344 if not suspected_cl:
345 continue
346
347 build = suspected_cl.builds.get(build_key)
348 if build:
349 cl['status'] = build['status']
350
351 return suspected_cls
352
353
308 class BuildFailure(BaseHandler): 354 class BuildFailure(BaseHandler):
309 PERMISSION_LEVEL = Permission.ANYONE 355 PERMISSION_LEVEL = Permission.ANYONE
310 356
311 def _ShowDebugInfo(self): 357 def _ShowDebugInfo(self):
312 # Show debug info only if the app is run locally during development, if the 358 # 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 359 # currently logged-in user is an admin, or if it is explicitly requested
314 # with parameter 'debug=1'. 360 # with parameter 'debug=1'.
315 return users.is_current_user_admin() or self.request.get('debug') == '1' 361 return users.is_current_user_admin() or self.request.get('debug') == '1'
316 362
317 def _ShowTriageHelpButton(self): 363 def _ShowTriageHelpButton(self):
(...skipping 18 matching lines...) Expand all
336 'triage_history': _GetTriageHistory(analysis), 382 'triage_history': _GetTriageHistory(analysis),
337 'show_triage_help_button': self._ShowTriageHelpButton(), 383 'show_triage_help_button': self._ShowTriageHelpButton(),
338 'triage_reference_analysis_master_name': 384 'triage_reference_analysis_master_name':
339 analysis.triage_reference_analysis_master_name, 385 analysis.triage_reference_analysis_master_name,
340 'triage_reference_analysis_builder_name': 386 'triage_reference_analysis_builder_name':
341 analysis.triage_reference_analysis_builder_name, 387 analysis.triage_reference_analysis_builder_name,
342 'triage_reference_analysis_build_number': 388 'triage_reference_analysis_build_number':
343 analysis.triage_reference_analysis_build_number 389 analysis.triage_reference_analysis_build_number
344 } 390 }
345 391
346 def _PrepareDataForCompileFailure(self, analysis): 392 def _PrepareDataForCompileFailure(self, analysis, data):
347 data = self._PrepareCommonDataForFailure(analysis)
348 393
349 # Check result from heuristic analysis. 394 # Check result from heuristic analysis.
350 _PopulateHeuristicDataForCompileFailure(analysis, data) 395 _PopulateHeuristicDataForCompileFailure(analysis, data)
351 # Check result from try job. 396 # Check result from try job.
352 data['try_job'] = _PrepareTryJobDataForCompileFailure(analysis) 397 data['try_job'] = _PrepareTryJobDataForCompileFailure(analysis)
353 398
354 return data 399 def _PrepareDataForTestFailures(self, analysis, build_info, data,
400 show_debug_info=False):
355 401
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 402 data['status_message_map'] = result_status.STATUS_MESSAGE_MAP
360 403
361 organized_results = _GetOrganizedAnalysisResultBySuspectedCL( 404 organized_results = _GetOrganizedAnalysisResultBySuspectedCL(
362 analysis.result) 405 analysis.result)
363 analysis_result = _GetAnalysisResultWithTryJobInfo( 406 analysis_result = _GetAnalysisResultWithTryJobInfo(
364 show_debug_info, organized_results, *build_info) 407 show_debug_info, organized_results, *build_info)
365 408
366 data['analysis_result'] = analysis_result 409 data['analysis_result'] = analysis_result
367 return data 410 return data
368 411
(...skipping 29 matching lines...) Expand all
398 build_completed = (users.is_current_user_admin() and 441 build_completed = (users.is_current_user_admin() and
399 self.request.get('build_completed') == '1') 442 self.request.get('build_completed') == '1')
400 force_try_job = (users.is_current_user_admin() and 443 force_try_job = (users.is_current_user_admin() and
401 self.request.get('force_try_job') == '1') 444 self.request.get('force_try_job') == '1')
402 analysis = build_failure_analysis_pipelines.ScheduleAnalysisIfNeeded( 445 analysis = build_failure_analysis_pipelines.ScheduleAnalysisIfNeeded(
403 master_name, builder_name, build_number, 446 master_name, builder_name, build_number,
404 build_completed=build_completed, force=force, 447 build_completed=build_completed, force=force,
405 force_try_job=force_try_job, 448 force_try_job=force_try_job,
406 queue_name=constants.WATERFALL_ANALYSIS_QUEUE) 449 queue_name=constants.WATERFALL_ANALYSIS_QUEUE)
407 450
451 data = self._PrepareCommonDataForFailure(analysis)
452 data['suspected_cls'] = _GetAllSuspectedCLsAndCheckStatus(
453 master_name, builder_name, build_number, analysis)
454
408 if analysis.failure_type == failure_type.COMPILE: 455 if analysis.failure_type == failure_type.COMPILE:
456 self._PrepareDataForCompileFailure(analysis, data)
409 return { 457 return {
410 'template': 'waterfall/compile_failure.html', 458 'template': 'waterfall/compile_failure.html',
411 'data': self._PrepareDataForCompileFailure(analysis), 459 'data': data
412 } 460 }
413 else: 461 else:
462 self._PrepareDataForTestFailures(
463 analysis, build_info, data, self._ShowDebugInfo())
414 return { 464 return {
415 'template': 'waterfall/test_failure.html', 465 'template': 'waterfall/test_failure.html',
416 'data': self._PrepareDataForTestFailures(analysis, build_info, 466 'data': data
417 self._ShowDebugInfo()),
418 } 467 }
419 468
420 def HandlePost(self): # pragma: no cover 469 def HandlePost(self): # pragma: no cover
421 return self.HandleGet() 470 return self.HandleGet()
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698