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

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

Powered by Google App Engine
This is Rietveld 408576698