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

Side by Side Diff: scripts/slave/recipes/findit/chromium/compile.py

Issue 1416763007: Add a recipe to identify culprits for chromium compile failures. (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/build.git@master
Patch Set: Rebase and Address comments. Created 5 years, 1 month 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
(Empty)
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
3 # found in the LICENSE file.
4
5 import json
6
7 from recipe_engine.config import List
8 from recipe_engine.recipe_api import Property
9
10
11 DEPS = [
12 'chromium',
13 'chromium_tests',
14 'findit',
15 'gclient',
16 'json',
17 'path',
18 'properties',
19 'python',
20 'step',
21 ]
22
23
24 PROPERTIES = {
25 'target_mastername': Property(
26 kind=str, help='The target master to match compile config to.'),
27 'target_buildername': Property(
28 kind=str, help='The target builder to match compile config to.'),
29 'target_solution': Property(
Paweł Hajdan Jr. 2015/11/24 13:20:41 Why is this needed? The mastername and buildernam
stgao 2015/11/24 23:19:20 This is very helpful, and it could save me one par
30 kind=str, help='The gclient solution, eg: src for chromium.'),
31 'target_solution_revisions': Property(
32 kind=List(basestring),
33 help='The revisions to be tested for compile failure, '
34 'ordered from older revisions to newer revisions.'),
35 'requested_compile_targets': Property(
36 kind=List(basestring), default=None, param_name='compile_targets',
37 help='The failed compile targets, eg: browser_tests'),
38 }
39
40
41 class CompileResult(object):
42 SKIPPED = 'skipped' # No compile is needed.
43 PASSED = 'passed' # Compile passed.
44 FAILED = 'failed' # Compile failed.
45
46
47 def _run_compile_at_revision(api, target_mastername, target_buildername,
48 target_solution, revision,
49 compile_targets):
50 with api.step.nest('test %s' % str(revision)):
51 # Configure the revision to recompile.
52 api.gclient.c.revisions[target_solution] = revision
53
54 bot_update_step, master_dict, test_spec = \
55 api.chromium_tests.prepare_checkout(
56 target_mastername,
57 target_buildername)
58
59 # If no compile targets are provided, use analyze to filter out the
Paweł Hajdan Jr. 2015/11/24 13:20:41 Why do you want to support the case where no compi
stgao 2015/11/24 23:19:20 For compile failures on the waterfall, now there i
60 # impacted compile targets by the given revision.
61 # TODO: if compile targets are provided, check if they exist and use analyze
62 # to filter out the impacted ones by the given revision.
63 compile_targets = sorted(set(compile_targets or []))
64 if not compile_targets:
65 affected_files = api.findit.get_files_affected_by_revision(
66 revision, target_solution)
67
68 test_targets, compile_targets, _ = \
69 api.chromium_tests.get_test_targets_compile_targets_and_tests(
Dirk Pranke 2015/11/24 00:17:41 why are you splitting test_targets and compile_tar
stgao 2015/11/24 06:15:29 Yes, to match the changed API in chromium_tests.an
stgao 2015/11/24 23:19:19 Done.
70 target_mastername,
71 target_buildername,
72 master_dict,
73 test_spec,
74 override_bot_type='builder_tester',
75 override_tests=[])
76 additional_compile_targets = sorted(
77 set(compile_targets) - set(test_targets))
78
79 _, compile_targets = api.chromium_tests.analyze(
Paweł Hajdan Jr. 2015/11/24 13:20:41 Is analyze _really_ needed here? Why can't we rely
stgao 2015/11/24 23:19:20 We could do that, but it will be slow, because mor
Paweł Hajdan Jr. 2015/11/30 16:19:05 What's the reasoning behind this? I'm not convince
stgao 2015/12/01 16:30:00 In this smoke test, build in http://shortn/_d3dv1O
80 affected_files,
81 test_targets,
82 additional_compile_targets,
83 'trybot_analyze_config.json')
84
85 if not compile_targets:
86 # No compile target is impacted by the given revision.
87 return CompileResult.SKIPPED
88
89 assert compile_targets, 'compile targets should not be empty!'
Dirk Pranke 2015/11/24 00:17:41 nit: I'm not convinced this assert is really usefu
stgao 2015/11/24 23:19:20 Done.
90
91 try:
92 api.chromium_tests.compile_specific_targets(
93 target_mastername,
94 target_buildername,
95 bot_update_step,
96 master_dict,
97 compile_targets,
98 [], # Not run any test.
Dirk Pranke 2015/11/24 00:17:41 nit: I'd just say tests_including_triggered=[] ins
stgao 2015/11/24 23:19:20 Done.
99 override_bot_type='builder_tester')
Paweł Hajdan Jr. 2015/11/24 13:20:41 Why is this needed?
stgao 2015/11/24 23:19:20 Just want to make it explicit. I could remove it i
Paweł Hajdan Jr. 2015/11/30 16:19:05 That's actually a behavior change. chromium_trybot
stgao 2015/12/01 16:30:00 Oh, I see. I thought it was the same as a "builder
stgao 2015/12/01 17:15:02 As discussion in the meeting, I will add this bot-
100 return CompileResult.PASSED
101 except api.step.InfraFailure:
102 raise
103 except api.step.StepFailure:
104 return CompileResult.FAILED
105
106
107 def RunSteps(api, target_mastername, target_buildername,
108 target_solution, target_solution_revisions,
109 requested_compile_targets):
110 api.chromium_tests.configure_build(
111 target_mastername, target_buildername, override_bot_type='builder_tester')
Paweł Hajdan Jr. 2015/11/24 13:20:41 Why is override_bot_type needed here?
stgao 2015/11/24 23:19:20 Just want to make it explicit. I could remove it i
112
113 results = []
114 try:
115 for current_revision in target_solution_revisions:
116 try:
117 compile_result = _run_compile_at_revision(
118 api, target_mastername, target_buildername, target_solution,
119 current_revision, requested_compile_targets)
120 except api.step.InfraFailure:
121 # Retry once only on infra failure.
Paweł Hajdan Jr. 2015/11/24 13:20:41 Is this retry really needed/useful here?
stgao 2015/11/24 23:19:19 For compile failures on the waterfall, I saw a lot
Paweł Hajdan Jr. 2015/11/30 16:19:05 Can we start with a version of this recipe which d
stgao 2015/12/01 16:30:00 OK. Removed.
122 compile_result = _run_compile_at_revision(
123 api, target_mastername, target_buildername, target_solution,
124 current_revision, requested_compile_targets)
125
126 results.append([current_revision, compile_result])
127 if compile_result == CompileResult.FAILED:
128 # TODO: if compile targets are specified, compile may fail because those
Paweł Hajdan Jr. 2015/11/24 13:20:41 Please follow the style guide's TODO(...) format.
stgao 2015/11/24 23:19:20 Done.
129 # targets are added in a later revision.
130 break # Found the culprit, no need to check later revisions.
131 finally:
132 # Report the result.
133 step_result = api.python.inline(
Paweł Hajdan Jr. 2015/11/24 13:20:41 Why not use api.python.result_step (or succeeding/
stgao 2015/11/24 23:19:20 I'm afraid I can't do that. Because they don't su
Paweł Hajdan Jr. 2015/11/30 16:19:05 Could you at the very least add a TODO, and eventu
stgao 2015/12/01 16:30:00 Done.
134 'report', 'import sys; sys.exit(0)', add_python_log=False)
135 if (not requested_compile_targets and
136 results and results[-1][1] == CompileResult.FAILED):
137 step_result.presentation.step_text = '<br/>Culprit: %s' % results[-1][0]
138 step_result.presentation.logs.setdefault('result', []).append(
139 json.dumps(results, indent=2))
140
141 return results
142
143
144 def GenTests(api):
145 def props(compile_targets=None):
146 properties = {
147 'mastername': 'tryserver.chromium.linux',
148 'buildername': 'linux_variable',
149 'slavename': 'build1-a1',
150 'buildnumber': '1',
151 'target_mastername': 'chromium.linux',
152 'target_buildername': 'Linux Builder',
153 'target_solution': 'src',
154 'target_solution_revisions': ['r1'],
155 }
156 if compile_targets:
157 properties['compile_targets'] = compile_targets
158 return api.properties(**properties)
159
160 yield (
161 api.test('compile_skipped') +
162 props() +
163 api.override_step_data(
164 'test r1.analyze',
165 api.json.output({
166 'status': 'No dependencies',
167 'compile_targets': [],
168 'test_targets': [],
169 })
170 )
171 )
172
173 yield (
174 api.test('successful_compile_targets_returned_by_analyze') +
175 props() +
176 api.override_step_data(
177 'test r1.analyze',
178 api.json.output({
179 'status': 'Found dependency',
180 'compile_targets': ['test_target', 'test_target_run'],
181 'test_targets': ['test_target', 'test_target_run'],
182 })
183 )
184 )
185
186 yield (
187 api.test('failed_compile_targets_returned_by_analyze') +
188 props() +
189 api.override_step_data(
190 'test r1.analyze',
191 api.json.output({
192 'status': 'Found dependency',
193 'compile_targets': ['test_target', 'test_target_run'],
194 'test_targets': ['test_target', 'test_target_run'],
195 })
196 ) +
197 api.override_step_data('test r1.compile', retcode=1)
198 )
199
200 yield (
201 api.test('compile_specified_targets') +
202 props(compile_targets=['target_name'])
203 )
204
205 yield (
206 api.test('compile_failed') +
207 props(compile_targets=['target_name']) +
208 api.override_step_data('test r1.compile', retcode=1)
209 )
210
211 yield (
212 api.test('successful_retry_compile_upon_infra_failure') +
213 props(compile_targets=['target_name']) +
214 api.override_step_data(
215 'test r1.compile',
216 api.json.output({
217 'notice': [
218 {
219 'infra_status': {
220 'ping_status_code': 408,
221 },
222 },
223 ],
224 }),
225 retcode=1) +
226 api.override_step_data(
227 'test r1.compile (2)',
228 api.json.output({
229 'notice': [
230 {
231 'infra_status': {
232 'ping_status_code': 200,
233 },
234 },
235 ],
236 }),
237 retcode=1)
238 )
239
240 yield (
241 api.test('failed_retry_compile_upon_infra_failure') +
242 props(compile_targets=['target_name']) +
243 api.override_step_data(
244 'test r1.compile',
245 api.json.output({
246 'notice': [
247 {
248 'infra_status': {
249 'ping_status_code': 408,
250 },
251 },
252 ],
253 }),
254 retcode=1) +
255 api.override_step_data(
256 'test r1.compile (2)',
257 api.json.output({
258 'notice': [
259 {
260 'infra_status': {
261 'ping_status_code': 408,
262 },
263 },
264 ],
265 }),
266 retcode=1)
267 )
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698