OLD | NEW |
1 # Copyright 2016 The Chromium Authors. All rights reserved. | 1 # Copyright 2016 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 | 5 |
6 # Recipe module for Skia Swarming trigger. | 6 # Recipe module for Skia Swarming trigger. |
7 | 7 |
8 | 8 |
9 import json | 9 import json |
10 | 10 |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
70 dimensions['gpu'] = 'none' | 70 dimensions['gpu'] = 'none' |
71 # TODO(borenet): Add appropriate CPU dimension(s). | 71 # TODO(borenet): Add appropriate CPU dimension(s). |
72 #dimensions['cpu'] = builder_cfg['cpu_or_gpu_value'] | 72 #dimensions['cpu'] = builder_cfg['cpu_or_gpu_value'] |
73 else: # pragma: no cover | 73 else: # pragma: no cover |
74 dimensions['gpu'] = builder_cfg['cpu_or_gpu_value'] | 74 dimensions['gpu'] = builder_cfg['cpu_or_gpu_value'] |
75 else: | 75 else: |
76 dimensions['gpu'] = 'none' | 76 dimensions['gpu'] = 'none' |
77 return dimensions | 77 return dimensions |
78 | 78 |
79 | 79 |
| 80 def isolate_recipes(api): |
| 81 """Isolate the recipes.""" |
| 82 skia_recipes_dir = api.path['build'].join( |
| 83 'scripts', 'slave', 'recipes', 'skia') |
| 84 api.skia_swarming.create_isolated_gen_json( |
| 85 skia_recipes_dir.join('recipes.isolate'), |
| 86 skia_recipes_dir, |
| 87 'linux', |
| 88 'isolate_recipes', |
| 89 {}) |
| 90 return api.skia_swarming.batcharchive(['isolate_recipes'])[0][1] |
| 91 |
| 92 |
| 93 def trigger_task(api, task_name, builder, builder_cfg, got_revision, |
| 94 infrabots_dir, idempotent=False, store_output=True, |
| 95 extra_isolate_hashes=None): |
| 96 """Trigger the given bot to run as a Swarming task.""" |
| 97 # TODO(borenet): We're using Swarming directly to run the recipe through |
| 98 # recipes.py. Once it's possible to track the state of a Buildbucket build, |
| 99 # we should switch to use the trigger recipe module instead. |
| 100 |
| 101 properties = { |
| 102 'buildername': builder, |
| 103 'mastername': api.properties['mastername'], |
| 104 'buildnumber': api.properties['buildnumber'], |
| 105 'reason': 'Triggered by Skia swarm_trigger Recipe', |
| 106 'revision': got_revision, |
| 107 'slavename': api.properties['slavename'], |
| 108 'swarm_out_dir': '${ISOLATED_OUTDIR}', |
| 109 } |
| 110 if builder_cfg['is_trybot']: |
| 111 properties['issue'] = str(api.properties['issue']) |
| 112 properties['patchset'] = str(api.properties['patchset']) |
| 113 properties['rietveld'] = api.properties['rietveld'] |
| 114 |
| 115 extra_args = [ |
| 116 '--properties', json.dumps(properties), |
| 117 '--workdir', '../../..', |
| 118 'skia/swarm_%s' % task_name, |
| 119 ] |
| 120 |
| 121 isolate_base_dir = api.path['slave_build'] |
| 122 dimensions = swarm_dimensions(builder_cfg) |
| 123 isolate_blacklist = ['.git', 'out', '*.pyc'] |
| 124 isolate_vars = { |
| 125 'BUILD': api.path['build'], |
| 126 'WORKDIR': api.path['slave_build'], |
| 127 } |
| 128 |
| 129 return api.skia_swarming.isolate_and_trigger_task( |
| 130 infrabots_dir.join('%s_skia.isolate' % task_name), |
| 131 isolate_base_dir, |
| 132 '%s_skia' % task_name, |
| 133 isolate_vars, |
| 134 dimensions, |
| 135 isolate_blacklist=isolate_blacklist, |
| 136 extra_isolate_hashes=extra_isolate_hashes, |
| 137 idempotent=idempotent, |
| 138 store_output=store_output, |
| 139 extra_args=extra_args) |
| 140 |
| 141 |
80 def checkout_steps(api): | 142 def checkout_steps(api): |
81 """Run the steps to obtain a checkout of Skia.""" | 143 """Run the steps to obtain a checkout of Skia.""" |
82 gclient_cfg = api.gclient.make_config(CACHE_DIR=None) | 144 gclient_cfg = api.gclient.make_config(CACHE_DIR=None) |
83 skia = gclient_cfg.solutions.add() | 145 skia = gclient_cfg.solutions.add() |
84 skia.name = 'skia' | 146 skia.name = 'skia' |
85 skia.managed = False | 147 skia.managed = False |
86 skia.url = 'https://skia.googlesource.com/skia.git' | 148 skia.url = 'https://skia.googlesource.com/skia.git' |
87 skia.revision = api.properties.get('revision') or 'origin/master' | 149 skia.revision = api.properties.get('revision') or 'origin/master' |
88 api.skia.update_repo(skia) | 150 api.skia.update_repo(skia) |
89 | 151 |
90 # Run 'gclient sync'. | 152 # Run 'gclient sync'. |
91 gclient_cfg.got_revision_mapping['skia'] = 'got_revision' | 153 gclient_cfg.got_revision_mapping['skia'] = 'got_revision' |
92 gclient_cfg.target_os.add('llvm') | 154 gclient_cfg.target_os.add('llvm') |
93 update_step = api.gclient.checkout(gclient_config=gclient_cfg) | 155 update_step = api.gclient.checkout(gclient_config=gclient_cfg) |
94 | 156 |
95 got_revision = update_step.presentation.properties['got_revision'] | 157 got_revision = update_step.presentation.properties['got_revision'] |
96 api.tryserver.maybe_apply_issue() | 158 api.tryserver.maybe_apply_issue() |
97 return got_revision | 159 return got_revision |
98 | 160 |
99 | 161 |
100 def compile_steps_swarm(api, infrabots_dir, builder_cfg): | 162 def compile_steps_swarm(api, builder_cfg, got_revision, infrabots_dir, |
| 163 extra_isolate_hashes): |
101 builder_name = derive_compile_bot_name(api.properties['buildername'], | 164 builder_name = derive_compile_bot_name(api.properties['buildername'], |
102 builder_cfg) | 165 builder_cfg) |
103 # Windows bots require a toolchain. | 166 # Windows bots require a toolchain. |
104 extra_hashes = None | 167 extra_hashes = extra_isolate_hashes[:] |
105 if 'Win' in builder_name: | 168 if 'Win' in builder_name: |
106 test_data = '''{ | 169 test_data = '''{ |
107 "2013": "705384d88f80da637eb367e5acc6f315c0e1db2f", | 170 "2013": "705384d88f80da637eb367e5acc6f315c0e1db2f", |
108 "2015": "38380d77eec9164e5818ae45e2915a6f22d60e85" | 171 "2015": "38380d77eec9164e5818ae45e2915a6f22d60e85" |
109 }''' | 172 }''' |
110 hash_file = infrabots_dir.join('win_toolchain_hash.json') | 173 hash_file = infrabots_dir.join('win_toolchain_hash.json') |
111 j = api.skia._readfile(hash_file, | 174 j = api.skia._readfile(hash_file, |
112 name='Read win_toolchain_hash.json', | 175 name='Read win_toolchain_hash.json', |
113 test_data=test_data).rstrip() | 176 test_data=test_data).rstrip() |
114 hashes = json.loads(j) | 177 hashes = json.loads(j) |
115 extra_hashes = [hashes['2013']] | 178 extra_hashes.append(hashes['2013']) |
116 | 179 |
117 # Isolate the inputs and trigger the task. | 180 task = trigger_task( |
118 isolate_path = infrabots_dir.join('compile_skia.isolate') | 181 api, |
119 isolate_vars = {'BUILDER_NAME': builder_name} | 182 'compile', |
120 dimensions = swarm_dimensions(builder_cfg) | 183 builder_name, |
121 task = api.skia_swarming.isolate_and_trigger_task( | 184 builder_cfg, |
122 isolate_path, infrabots_dir, 'compile_skia', isolate_vars, | 185 got_revision, |
123 dimensions, idempotent=True, store_output=False, | 186 infrabots_dir, |
124 isolate_blacklist=['.git', 'out', '*.pyc'], | 187 idempotent=True, |
| 188 store_output=False, |
125 extra_isolate_hashes=extra_hashes) | 189 extra_isolate_hashes=extra_hashes) |
126 | 190 |
127 # Wait for compile to finish, record the results hash. | 191 # Wait for compile to finish, record the results hash. |
128 return api.skia_swarming.collect_swarming_task_isolate_hash(task) | 192 return api.skia_swarming.collect_swarming_task_isolate_hash(task) |
129 | 193 |
130 | 194 |
131 def download_images(api, infrabots_dir): | 195 def download_images(api, infrabots_dir): |
132 api.python('Download images', | 196 api.python('Download images', |
133 script=infrabots_dir.join('download_images.py'), | 197 script=infrabots_dir.join('download_images.py'), |
134 env=api.skia.gsutil_env('chromium-skia-gm.boto')) | 198 env=api.skia.gsutil_env('chromium-skia-gm.boto')) |
135 | 199 |
136 | 200 |
137 def download_skps(api, infrabots_dir): | 201 def download_skps(api, infrabots_dir): |
138 api.python('Download SKPs', | 202 api.python('Download SKPs', |
139 script=infrabots_dir.join('download_skps.py'), | 203 script=infrabots_dir.join('download_skps.py'), |
140 env=api.skia.gsutil_env('chromium-skia-gm.boto')) | 204 env=api.skia.gsutil_env('chromium-skia-gm.boto')) |
141 | 205 |
142 | 206 |
143 def perf_steps_trigger(api, infrabots_dir, compile_hash, dimensions, | 207 def perf_steps_trigger(api, builder_cfg, got_revision, infrabots_dir, |
144 got_revision, is_trybot): | 208 extra_hashes): |
145 """Trigger perf tests via Swarming.""" | 209 """Trigger perf tests via Swarming.""" |
146 # Swarm the tests. | 210 return trigger_task( |
147 task_name = 'perf_skia' | 211 api, |
148 isolate_path = infrabots_dir.join('%s.isolate' % task_name) | 212 'perf', |
149 issue = str(api.properties['issue']) if is_trybot else '' | 213 api.properties['buildername'], |
150 patchset = str(api.properties['patchset']) if is_trybot else '' | 214 builder_cfg, |
151 isolate_vars = { | 215 got_revision, |
152 'MASTER_NAME': api.properties['mastername'], | 216 infrabots_dir, |
153 'BUILDER_NAME': api.properties['buildername'], | 217 extra_isolate_hashes=extra_hashes) |
154 'BUILD_NUMBER': str(api.properties['buildnumber']), | |
155 'SLAVE_NAME': api.properties['slavename'], | |
156 'REVISION': got_revision, | |
157 'ISSUE': issue, | |
158 'PATCHSET': patchset, | |
159 } | |
160 return api.skia_swarming.isolate_and_trigger_task( | |
161 isolate_path, infrabots_dir, task_name, isolate_vars, dimensions, | |
162 isolate_blacklist=['.git'], extra_isolate_hashes=[compile_hash]) | |
163 | 218 |
164 | 219 |
165 def perf_steps_collect(api, task, upload_perf_results, got_revision, | 220 def perf_steps_collect(api, task, upload_perf_results, got_revision, |
166 is_trybot): | 221 is_trybot): |
167 """Wait for perf steps to finish and upload results.""" | 222 """Wait for perf steps to finish and upload results.""" |
168 # Wait for nanobench to finish, download the results. | 223 # Wait for nanobench to finish, download the results. |
169 api.file.rmtree('results_dir', task.task_output_dir, infra_step=True) | 224 api.file.rmtree('results_dir', task.task_output_dir, infra_step=True) |
170 api.skia_swarming.collect_swarming_task(task) | 225 api.skia_swarming.collect_swarming_task(task) |
171 | 226 |
172 # Upload the results. | 227 # Upload the results. |
(...skipping 20 matching lines...) Expand all Loading... |
193 upload_args.append(api.properties['issue']) | 248 upload_args.append(api.properties['issue']) |
194 api.python( | 249 api.python( |
195 'Upload perf results', | 250 'Upload perf results', |
196 script=api.skia.resource('upload_bench_results.py'), | 251 script=api.skia.resource('upload_bench_results.py'), |
197 args=upload_args, | 252 args=upload_args, |
198 cwd=api.path['checkout'], | 253 cwd=api.path['checkout'], |
199 env=api.skia.gsutil_env('chromium-skia-gm.boto'), | 254 env=api.skia.gsutil_env('chromium-skia-gm.boto'), |
200 infra_step=True) | 255 infra_step=True) |
201 | 256 |
202 | 257 |
203 def test_steps_trigger(api, infrabots_dir, compile_hash, dimensions, | 258 def test_steps_trigger(api, builder_cfg, got_revision, infrabots_dir, |
204 got_revision, is_trybot): | 259 extra_hashes): |
205 """Trigger DM via Swarming.""" | 260 """Trigger DM via Swarming.""" |
206 # Swarm the tests. | 261 return trigger_task( |
207 task_name = 'test_skia' | 262 api, |
208 isolate_path = infrabots_dir.join('%s.isolate' % task_name) | 263 'test', |
209 issue = str(api.properties['issue']) if is_trybot else '' | 264 api.properties['buildername'], |
210 patchset = str(api.properties['patchset']) if is_trybot else '' | 265 builder_cfg, |
211 isolate_vars = { | 266 got_revision, |
212 'MASTER_NAME': api.properties['mastername'], | 267 infrabots_dir, |
213 'BUILDER_NAME': api.properties['buildername'], | 268 extra_isolate_hashes=extra_hashes) |
214 'BUILD_NUMBER': str(api.properties['buildnumber']), | |
215 'SLAVE_NAME': api.properties['slavename'], | |
216 'REVISION': got_revision, | |
217 'ISSUE': issue, | |
218 'PATCHSET': patchset, | |
219 } | |
220 | |
221 return api.skia_swarming.isolate_and_trigger_task( | |
222 isolate_path, infrabots_dir, task_name, isolate_vars, dimensions, | |
223 isolate_blacklist=['.git'], extra_isolate_hashes=[compile_hash]) | |
224 | 269 |
225 | 270 |
226 def test_steps_collect(api, task, upload_dm_results, got_revision, is_trybot): | 271 def test_steps_collect(api, task, upload_dm_results, got_revision, is_trybot): |
227 """Collect the DM results from Swarming.""" | 272 """Collect the DM results from Swarming.""" |
228 # Wait for tests to finish, download the results. | 273 # Wait for tests to finish, download the results. |
229 api.file.rmtree('results_dir', task.task_output_dir, infra_step=True) | 274 api.file.rmtree('results_dir', task.task_output_dir, infra_step=True) |
230 api.skia_swarming.collect_swarming_task(task) | 275 api.skia_swarming.collect_swarming_task(task) |
231 | 276 |
232 # Upload the results. | 277 # Upload the results. |
233 if upload_dm_results: | 278 if upload_dm_results: |
(...skipping 23 matching lines...) Expand all Loading... |
257 got_revision = checkout_steps(api) | 302 got_revision = checkout_steps(api) |
258 builder_spec = api.skia.get_builder_spec(api.path['checkout'], | 303 builder_spec = api.skia.get_builder_spec(api.path['checkout'], |
259 api.properties['buildername']) | 304 api.properties['buildername']) |
260 builder_cfg = builder_spec['builder_cfg'] | 305 builder_cfg = builder_spec['builder_cfg'] |
261 infrabots_dir = api.path['checkout'].join('infra', 'bots') | 306 infrabots_dir = api.path['checkout'].join('infra', 'bots') |
262 | 307 |
263 api.skia_swarming.setup( | 308 api.skia_swarming.setup( |
264 api.path['checkout'].join('infra', 'bots', 'tools', 'luci-go'), | 309 api.path['checkout'].join('infra', 'bots', 'tools', 'luci-go'), |
265 swarming_rev='') | 310 swarming_rev='') |
266 | 311 |
267 compile_hash = compile_steps_swarm(api, infrabots_dir, builder_cfg) | 312 recipes_hash = isolate_recipes(api) |
| 313 |
| 314 compile_hash = compile_steps_swarm(api, builder_cfg, got_revision, |
| 315 infrabots_dir, [recipes_hash]) |
| 316 extra_hashes = [recipes_hash, compile_hash] |
268 | 317 |
269 do_test_steps = builder_spec['do_test_steps'] | 318 do_test_steps = builder_spec['do_test_steps'] |
270 do_perf_steps = builder_spec['do_perf_steps'] | 319 do_perf_steps = builder_spec['do_perf_steps'] |
271 is_trybot = builder_cfg['is_trybot'] | |
272 | 320 |
273 if not (do_test_steps or do_perf_steps): | 321 if not (do_test_steps or do_perf_steps): |
274 return | 322 return |
275 | 323 |
276 download_skps(api, infrabots_dir) | 324 download_skps(api, infrabots_dir) |
277 download_images(api, infrabots_dir) | 325 download_images(api, infrabots_dir) |
278 | 326 |
279 dimensions = swarm_dimensions(builder_cfg) | |
280 | |
281 test_task = None | 327 test_task = None |
282 perf_task = None | 328 perf_task = None |
283 if do_test_steps: | 329 if do_test_steps: |
284 test_task = test_steps_trigger(api, infrabots_dir, compile_hash, dimensions, | 330 test_task = test_steps_trigger(api, builder_cfg, got_revision, |
285 got_revision, is_trybot) | 331 infrabots_dir, extra_hashes) |
286 if do_perf_steps: | 332 if do_perf_steps: |
287 perf_task = perf_steps_trigger(api, infrabots_dir, compile_hash, dimensions, | 333 perf_task = perf_steps_trigger(api, builder_cfg, got_revision, |
288 got_revision, is_trybot) | 334 infrabots_dir, extra_hashes) |
| 335 is_trybot = builder_cfg['is_trybot'] |
289 if test_task: | 336 if test_task: |
290 test_steps_collect(api, test_task, builder_spec['upload_dm_results'], | 337 test_steps_collect(api, test_task, builder_spec['upload_dm_results'], |
291 got_revision, is_trybot) | 338 got_revision, is_trybot) |
292 if perf_task: | 339 if perf_task: |
293 perf_steps_collect(api, perf_task, builder_spec['upload_perf_results'], | 340 perf_steps_collect(api, perf_task, builder_spec['upload_perf_results'], |
294 got_revision, is_trybot) | 341 got_revision, is_trybot) |
295 | 342 |
296 | 343 |
297 def GenTests(api): | 344 def GenTests(api): |
298 for mastername, slaves in TEST_BUILDERS.iteritems(): | 345 for mastername, slaves in TEST_BUILDERS.iteritems(): |
299 for slavename, builders_by_slave in slaves.iteritems(): | 346 for slavename, builders_by_slave in slaves.iteritems(): |
300 for builder in builders_by_slave: | 347 for builder in builders_by_slave: |
301 test = ( | 348 test = ( |
302 api.test(builder) + | 349 api.test(builder) + |
303 api.properties(buildername=builder, | 350 api.properties(buildername=builder, |
304 mastername=mastername, | 351 mastername=mastername, |
305 slavename=slavename, | 352 slavename=slavename, |
306 buildnumber=5, | 353 buildnumber=5, |
307 revision='abc123') + | 354 revision='abc123') + |
308 api.path.exists( | 355 api.path.exists( |
309 api.path['slave_build'].join('skia'), | 356 api.path['slave_build'].join('skia'), |
310 api.path['slave_build'].join('tmp', 'uninteresting_hashes.txt') | 357 api.path['slave_build'].join('tmp', 'uninteresting_hashes.txt') |
311 ) | 358 ) |
312 ) | 359 ) |
313 if 'Trybot' in builder: | 360 if 'Trybot' in builder: |
314 test += api.properties(issue=500, | 361 test += api.properties(issue=500, |
315 patchset=1, | 362 patchset=1, |
316 rietveld='https://codereview.chromium.org') | 363 rietveld='https://codereview.chromium.org') |
317 if 'Win' in builder: | 364 test += api.step_data( |
318 test += api.step_data( | 365 'upload new .isolated file for compile_skia', |
319 'upload new .isolated file for compile_skia', | 366 stdout=api.raw_io.output('def456 XYZ.isolated')) |
320 stdout=api.raw_io.output('def456 XYZ.isolated')) | |
321 if 'Test' in builder: | 367 if 'Test' in builder: |
322 test += api.step_data( | 368 test += api.step_data( |
323 'upload new .isolated file for test_skia', | 369 'upload new .isolated file for test_skia', |
324 stdout=api.raw_io.output('def456 XYZ.isolated')) | 370 stdout=api.raw_io.output('def456 XYZ.isolated')) |
325 if ('Test' in builder and 'Debug' in builder) or 'Perf' in builder: | 371 if ('Test' in builder and 'Debug' in builder) or 'Perf' in builder: |
326 test += api.step_data( | 372 test += api.step_data( |
327 'upload new .isolated file for perf_skia', | 373 'upload new .isolated file for perf_skia', |
328 stdout=api.raw_io.output('def456 XYZ.isolated')) | 374 stdout=api.raw_io.output('def456 XYZ.isolated')) |
329 | 375 |
330 yield test | 376 yield test |
OLD | NEW |