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

Side by Side Diff: appengine/findit/waterfall/try_job_util.py

Issue 1591003002: [Findit] Modify tryjob pipelines to trigger try jobs for test failure. (Closed) Base URL: https://chromium.googlesource.com/infra/infra.git@master
Patch Set: . Created 4 years, 10 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 2015 The Chromium Authors. All rights reserved. 1 # Copyright 2015 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 import logging 5 import logging
6 6
7 from google.appengine.api import modules 7 from google.appengine.api import modules
8 from google.appengine.ext import ndb 8 from google.appengine.ext import ndb
9 9
10 from model import wf_analysis_status 10 from model import wf_analysis_status
11 from model.wf_try_job import WfTryJob 11 from model.wf_try_job import WfTryJob
12 from waterfall import try_job_pipeline 12 from waterfall import try_job_pipeline
13 from waterfall import waterfall_config 13 from waterfall import waterfall_config
14 from waterfall.try_job_type import TryJobType
15
14 16
15 # TODO(chanli): Need to figure out why try-job-queue doesn't work. 17 # TODO(chanli): Need to figure out why try-job-queue doesn't work.
16 TRY_JOB_PIPELINE_QUEUE_NAME = 'build-failure-analysis-queue' 18 TRY_JOB_PIPELINE_QUEUE_NAME = 'build-failure-analysis-queue'
17 19
18 20
19 def _CheckFailureForTryJobKey(master_name, builder_name, build_number, 21 def _CheckFailureForTryJobKey(
20 failure_result_map, step_name, failure): 22 master_name, builder_name, build_number,
23 failure_result_map, failed_step_or_test, failure):
21 """Compares the current_failure and first_failure for each failed_step/test. 24 """Compares the current_failure and first_failure for each failed_step/test.
22 25
23 If equal, a new try_job needs to start; 26 If equal, a new try_job needs to start;
24 If not, apply the key of the first_failure's try_job to this failure. 27 If not, apply the key of the first_failure's try_job to this failure.
25 """ 28 """
26 # TODO(chanli): Need to compare failures across builders 29 # TODO(chanli): Need to compare failures across builders
27 # after the grouping of failures is implemented. 30 # after the grouping of failures is implemented.
28 new_try_job_key = '%s/%s/%s' % (master_name, builder_name, build_number) 31 # TODO(chanli): Need to handle cases where first failure is actually
32 # more than 20 builds back. The implementation should not be here,
33 # but need to be taken care of.
29 if not failure.get('last_pass'): 34 if not failure.get('last_pass'):
30 # Bail out since cannot figure out the good_revision. 35 # Bail out since cannot figure out the good_revision.
31 return False, None 36 return False, None
32 37
33 if failure['current_failure'] == failure['first_failure']: 38 if failure['current_failure'] == failure['first_failure']:
34 failure_result_map[step_name] = new_try_job_key 39 failure_result_map[failed_step_or_test] = '%s/%s/%s' % (
35 logging.info('First-time failure') 40 master_name, builder_name, build_number)
36 return True, failure['last_pass'] # A new try_job is needed. 41 return True, failure['last_pass'] # A new try_job is needed.
37 else: 42 else:
38 # TODO(chanli): Need to handle cases where first failure is actually 43 failure_result_map[failed_step_or_test] = '%s/%s/%s' % (
39 # more than 20 builds back. The implementation should not be here,
40 # but need to be taken care of.
41 try_job_key = '%s/%s/%s' % (
42 master_name, builder_name, failure['first_failure']) 44 master_name, builder_name, failure['first_failure'])
43 failure_result_map[step_name] = try_job_key 45 return False, None
44 logging.info('Not first-time failure') 46
45 return False, failure['last_pass'] 47
48 def _CheckIfNeedNewTryJobForTestFailure(
49 failure_level, master_name, builder_name, build_number,
50 failure_result_map, failures):
51 """Traverses failed steps or tests to check if a new try job is needed."""
52 need_new_try_job = False
53 last_pass = build_number
54 targeted_tests = {} if failure_level == 'step' else []
55
56 for failure_name, failure in failures.iteritems():
57 if 'tests' in failure:
58 failure_result_map[failure_name] = {}
59 failure_targeted_tests, failure_need_try_job, failure_last_pass = (
60 _CheckIfNeedNewTryJobForTestFailure(
61 'test', master_name, builder_name, build_number,
62 failure_result_map[failure_name], failure['tests']))
63 if failure_need_try_job:
64 targeted_tests[failure_name] = failure_targeted_tests
65 else:
66 failure_need_try_job, failure_last_pass = _CheckFailureForTryJobKey(
67 master_name, builder_name, build_number,
68 failure_result_map, failure_name, failure)
69 if failure_need_try_job:
70 if failure_level == 'step':
71 targeted_tests[failure_name] = []
72 else:
73 targeted_tests.append(failure_name)
74
75 need_new_try_job = need_new_try_job or failure_need_try_job
76 last_pass = (failure_last_pass if failure_last_pass and
77 failure_last_pass < last_pass else last_pass)
78
79 return targeted_tests, need_new_try_job, last_pass
46 80
47 81
48 @ndb.transactional 82 @ndb.transactional
49 def _NeedANewTryJob( 83 def _NeedANewTryJob(
50 master_name, builder_name, build_number, failed_steps): 84 master_name, builder_name, build_number, failed_steps, failure_result_map):
51 """Checks if a new try_job is needed.""" 85 """Checks if a new try_job is needed."""
52 need_new_try_job = False 86 need_new_try_job = False
53 failure_result_map = {} 87 last_pass = build_number
54 last_pass = None
55 88
56 for step_name, step in failed_steps.iteritems(): 89 if 'compile' in failed_steps:
57 # TODO(chanli): support test failures when the recipe is ready. 90 try_job_type = TryJobType.COMPILE
58 if step_name == 'compile': 91 targeted_tests = None
59 need_new_try_job, last_pass = _CheckFailureForTryJobKey( 92 need_new_try_job, last_pass = _CheckFailureForTryJobKey(
60 master_name, builder_name, build_number, 93 master_name, builder_name, build_number,
61 failure_result_map, step_name, step) 94 failure_result_map, TryJobType.COMPILE, failed_steps['compile'])
95 else:
96 try_job_type = TryJobType.TEST
97 targeted_tests, need_new_try_job, last_pass = (
98 _CheckIfNeedNewTryJobForTestFailure(
99 'step', master_name, builder_name, build_number, failure_result_map,
100 failed_steps))
62 101
63 if need_new_try_job: 102 if need_new_try_job:
64 try_job = WfTryJob.Get( 103 try_job = WfTryJob.Get(
65 master_name, builder_name, build_number) 104 master_name, builder_name, build_number)
66 105
67 if try_job: 106 if try_job:
68 if try_job.failed: 107 if try_job.failed:
69 try_job.status = wf_analysis_status.PENDING 108 try_job.status = wf_analysis_status.PENDING
70 try_job.put() 109 try_job.put()
71 else: 110 else:
72 need_new_try_job = False 111 need_new_try_job = False
73 break 112 else:
74 else: 113 try_job = WfTryJob.Create(
75 try_job = WfTryJob.Create( 114 master_name, builder_name, build_number)
76 master_name, builder_name, build_number) 115 try_job.put()
77 try_job.put()
78 break
79 116
80 return need_new_try_job, failure_result_map, last_pass 117 return need_new_try_job, last_pass, try_job_type, targeted_tests
81 118
82 119
83 def _GetFailedTargetsFromSignals(signals): 120 def _GetFailedTargetsFromSignals(signals):
84 compile_targets = [] 121 compile_targets = []
85 122
86 if not signals or 'compile' not in signals: 123 if not signals or 'compile' not in signals:
87 return compile_targets 124 return compile_targets
88 125
89 for source_target in signals['compile']['failed_targets']: 126 for source_target in signals['compile']['failed_targets']:
90 # Link failures have only targets but no source. TODO(lijeffrey): 127 # Link failures have only targets but no source. TODO(lijeffrey):
(...skipping 11 matching lines...) Expand all
102 build_number = failure_info['build_number'] 139 build_number = failure_info['build_number']
103 failed_steps = failure_info.get('failed_steps', []) 140 failed_steps = failure_info.get('failed_steps', [])
104 builds = failure_info.get('builds', {}) 141 builds = failure_info.get('builds', {})
105 142
106 tryserver_mastername, tryserver_buildername = ( 143 tryserver_mastername, tryserver_buildername = (
107 waterfall_config.GetTrybotForWaterfallBuilder(master_name, builder_name)) 144 waterfall_config.GetTrybotForWaterfallBuilder(master_name, builder_name))
108 if not tryserver_mastername or not tryserver_buildername: 145 if not tryserver_mastername or not tryserver_buildername:
109 logging.info('%s, %s is not supported yet.', master_name, builder_name) 146 logging.info('%s, %s is not supported yet.', master_name, builder_name)
110 return {} 147 return {}
111 148
112 need_new_try_job, failure_result_map, last_pass = _NeedANewTryJob( 149 failure_result_map = {}
113 master_name, builder_name, build_number, failed_steps) 150 need_new_try_job, last_pass, try_job_type, targeted_tests = (
151 _NeedANewTryJob(master_name, builder_name, build_number,
152 failed_steps, failure_result_map))
114 153
115 if need_new_try_job: 154 if need_new_try_job:
116 compile_targets = _GetFailedTargetsFromSignals(signals) 155 compile_targets = (_GetFailedTargetsFromSignals(signals)
156 if try_job_type == TryJobType.COMPILE else None)
117 157
118 new_try_job_pipeline = try_job_pipeline.TryJobPipeline( 158 new_try_job_pipeline = try_job_pipeline.TryJobPipeline(
119 master_name, builder_name, build_number, 159 master_name, builder_name, build_number,
120 builds[str(last_pass)]['chromium_revision'], 160 builds[str(last_pass)]['chromium_revision'],
121 builds[str(build_number)]['chromium_revision'], 161 builds[str(build_number)]['chromium_revision'],
122 compile_targets) 162 builds[str(build_number)]['blame_list'],
163 try_job_type, compile_targets, targeted_tests)
123 164
124 new_try_job_pipeline.target = ( 165 new_try_job_pipeline.target = (
125 '%s.build-failure-analysis' % modules.get_current_version_name()) 166 '%s.build-failure-analysis' % modules.get_current_version_name())
126 new_try_job_pipeline.start(queue_name=TRY_JOB_PIPELINE_QUEUE_NAME) 167 new_try_job_pipeline.start(queue_name=TRY_JOB_PIPELINE_QUEUE_NAME)
127 logging.info('Try-job was scheduled for build %s, %s, %s: %s', 168 logging.info('Try-job was scheduled for build %s, %s, %s: %s',
128 master_name, builder_name, build_number, 169 master_name, builder_name, build_number,
129 new_try_job_pipeline.pipeline_status_path) 170 new_try_job_pipeline.pipeline_status_path)
130 171
131 return failure_result_map 172 return failure_result_map
OLDNEW
« appengine/findit/waterfall/try_job_type.py ('K') | « appengine/findit/waterfall/try_job_type.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698