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

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, 11 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 14
15 # TODO(chanli): Need to figure out why try-job-queue doesn't work. 15 # TODO(chanli): Need to figure out why try-job-queue doesn't work.
16 TRY_JOB_PIPELINE_QUEUE_NAME = 'build-failure-analysis-queue' 16 TRY_JOB_PIPELINE_QUEUE_NAME = 'build-failure-analysis-queue'
17 17
18 18
19 def _CheckFailureForTryJobKey(master_name, builder_name, build_number, 19 def _CheckFailureForTryJobKey(
20 failure_result_map, step_name, failure): 20 master_name, builder_name, build_number,
21 failure_result_map, failed_step_or_test, failure):
21 """Compares the current_failure and first_failure for each failed_step/test. 22 """Compares the current_failure and first_failure for each failed_step/test.
22 23
23 If equal, a new try_job needs to start; 24 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. 25 If not, apply the key of the first_failure's try_job to this failure.
25 """ 26 """
26 # TODO(chanli): Need to compare failures across builders 27 # TODO(chanli): Need to compare failures across builders
27 # after the grouping of failures is implemented. 28 # after the grouping of failures is implemented.
28 new_try_job_key = '%s/%s/%s' % (master_name, builder_name, build_number) 29 # TODO(chanli): Need to handle cases where first failure is actually
30 # more than 20 builds back. The implementation should not be here,
31 # but need to be taken care of.
29 if not failure.get('last_pass'): 32 if not failure.get('last_pass'):
30 # Bail out since cannot figure out the good_revision. 33 # Bail out since cannot figure out the good_revision.
31 return False, None 34 return False, None
32 35
33 if failure['current_failure'] == failure['first_failure']: 36 if failure['current_failure'] == failure['first_failure']:
34 failure_result_map[step_name] = new_try_job_key 37 failure_result_map[failed_step_or_test] = '%s/%s/%s' % (
35 logging.info('First-time failure') 38 master_name, builder_name, build_number)
36 return True, failure['last_pass'] # A new try_job is needed. 39 return True, failure['last_pass'] # A new try_job is needed.
37 else: 40 else:
38 # TODO(chanli): Need to handle cases where first failure is actually 41 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']) 42 master_name, builder_name, failure['first_failure'])
43 failure_result_map[step_name] = try_job_key 43 return False, None
44 logging.info('Not first-time failure')
45 return False, failure['last_pass']
46 44
47 45
48 @ndb.transactional 46 @ndb.transactional
49 def _NeedANewTryJob( 47 def _NeedANewTryJob(
50 master_name, builder_name, build_number, failed_steps): 48 master_name, builder_name, build_number, failed_steps, failure_result_map):
51 """Checks if a new try_job is needed.""" 49 """Checks if a new try_job is needed."""
52 need_new_try_job = False 50 need_new_try_job = False
53 failure_result_map = {} 51 last_pass = build_number
54 last_pass = None
55 52
56 for step_name, step in failed_steps.iteritems(): 53 if 'compile' in failed_steps:
57 # TODO(chanli): support test failures when the recipe is ready. 54 try_job_type = 'compile'
58 if step_name == 'compile': 55 targeted_tests = None
59 need_new_try_job, last_pass = _CheckFailureForTryJobKey( 56 need_new_try_job, last_pass = _CheckFailureForTryJobKey(
60 master_name, builder_name, build_number, 57 master_name, builder_name, build_number,
61 failure_result_map, step_name, step) 58 failure_result_map, 'compile', failed_steps['compile'])
59 else:
60 try_job_type = 'test'
61 targeted_tests = {}
62 for step_name, step in failed_steps.iteritems():
63 targeted_tests[step_name] = []
64 if 'tests' in step:
65 failure_result_map[step_name] = {}
66 step_need_new_try_job = False
67 step_last_pass = build_number
68 for test_name, test in step['tests'].iteritems():
69 test_need_new_try_job, test_last_pass = _CheckFailureForTryJobKey(
70 master_name, builder_name, build_number,
71 failure_result_map[step_name], test_name, test)
72 step_need_new_try_job = step_need_new_try_job or test_need_new_try_job
73 step_last_pass = (test_last_pass if test_last_pass and
74 test_last_pass < step_last_pass else step_last_pass)
75 if test_need_new_try_job:
76 targeted_tests[step_name].append(test_name)
77 if not step_need_new_try_job:
78 targeted_tests.pop(step_name)
79 else:
80 step_need_new_try_job, step_last_pass = _CheckFailureForTryJobKey(
81 master_name, builder_name, build_number,
82 failure_result_map, step_name, step)
83 if not step_need_new_try_job:
84 targeted_tests.pop(step_name)
62 85
63 if need_new_try_job: 86 need_new_try_job = need_new_try_job or step_need_new_try_job
64 try_job = WfTryJob.Get( 87 last_pass = (step_last_pass if step_last_pass and
65 master_name, builder_name, build_number) 88 step_last_pass < last_pass else last_pass)
66 89
67 if try_job: 90 if need_new_try_job:
68 if try_job.failed: 91 try_job = WfTryJob.Get(
69 try_job.status = wf_analysis_status.PENDING 92 master_name, builder_name, build_number)
70 try_job.put()
71 else:
72 need_new_try_job = False
73 break
74 else:
75 try_job = WfTryJob.Create(
76 master_name, builder_name, build_number)
77 try_job.put()
78 break
79 93
80 return need_new_try_job, failure_result_map, last_pass 94 if try_job:
95 if try_job.failed:
96 try_job.status = wf_analysis_status.PENDING
97 try_job.put()
98 else:
99 need_new_try_job = False
100 else:
101 try_job = WfTryJob.Create(
102 master_name, builder_name, build_number)
103 try_job.put()
104
105 return need_new_try_job, last_pass, try_job_type, targeted_tests
81 106
82 107
83 def _GetFailedTargetsFromSignals(signals): 108 def _GetFailedTargetsFromSignals(signals):
84 compile_targets = [] 109 compile_targets = []
85 110
86 if not signals or 'compile' not in signals: 111 if not signals or 'compile' not in signals:
87 return compile_targets 112 return compile_targets
88 113
89 for source_target in signals['compile']['failed_targets']: 114 for source_target in signals['compile']['failed_targets']:
90 # Link failures have only targets but no source. TODO(lijeffrey): 115 # Link failures have only targets but no source. TODO(lijeffrey):
(...skipping 11 matching lines...) Expand all
102 build_number = failure_info['build_number'] 127 build_number = failure_info['build_number']
103 failed_steps = failure_info.get('failed_steps', []) 128 failed_steps = failure_info.get('failed_steps', [])
104 builds = failure_info.get('builds', {}) 129 builds = failure_info.get('builds', {})
105 130
106 tryserver_mastername, tryserver_buildername = ( 131 tryserver_mastername, tryserver_buildername = (
107 waterfall_config.GetTrybotForWaterfallBuilder(master_name, builder_name)) 132 waterfall_config.GetTrybotForWaterfallBuilder(master_name, builder_name))
108 if not tryserver_mastername or not tryserver_buildername: 133 if not tryserver_mastername or not tryserver_buildername:
109 logging.info('%s, %s is not supported yet.', master_name, builder_name) 134 logging.info('%s, %s is not supported yet.', master_name, builder_name)
110 return {} 135 return {}
111 136
112 need_new_try_job, failure_result_map, last_pass = _NeedANewTryJob( 137 failure_result_map = {}
113 master_name, builder_name, build_number, failed_steps) 138 need_new_try_job, last_pass, try_job_type, targeted_tests= (
qyearsley 2016/01/17 03:43:12 space before =
chanli 2016/01/20 18:07:09 Done.
139 _NeedANewTryJob(master_name, builder_name, build_number,
140 failed_steps, failure_result_map))
114 141
115 if need_new_try_job: 142 if need_new_try_job:
116 compile_targets = _GetFailedTargetsFromSignals(signals) 143 compile_targets = (_GetFailedTargetsFromSignals(signals)
144 if try_job_type == 'compile' else None)
117 145
118 new_try_job_pipeline = try_job_pipeline.TryJobPipeline( 146 new_try_job_pipeline = try_job_pipeline.TryJobPipeline(
119 master_name, builder_name, build_number, 147 master_name, builder_name, build_number,
120 builds[str(last_pass)]['chromium_revision'], 148 builds[str(last_pass)]['chromium_revision'],
121 builds[str(build_number)]['chromium_revision'], 149 builds[str(build_number)]['chromium_revision'],
122 compile_targets) 150 builds[str(build_number)]['blame_list'],
151 try_job_type, compile_targets, targeted_tests)
123 152
124 new_try_job_pipeline.target = ( 153 new_try_job_pipeline.target = (
125 '%s.build-failure-analysis' % modules.get_current_version_name()) 154 '%s.build-failure-analysis' % modules.get_current_version_name())
126 new_try_job_pipeline.start(queue_name=TRY_JOB_PIPELINE_QUEUE_NAME) 155 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', 156 logging.info('Try-job was scheduled for build %s, %s, %s: %s',
128 master_name, builder_name, build_number, 157 master_name, builder_name, build_number,
129 new_try_job_pipeline.pipeline_status_path) 158 new_try_job_pipeline.pipeline_status_path)
130 159
131 return failure_result_map 160 return failure_result_map
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698