| 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) | 327 dimensions = swarm_dimensions(builder_cfg) |
| 280 | 328 |
| 281 test_task = None | 329 test_task = None |
| 282 perf_task = None | 330 perf_task = None |
| 283 if do_test_steps: | 331 if do_test_steps: |
| 284 test_task = test_steps_trigger(api, infrabots_dir, compile_hash, dimensions, | 332 test_task = test_steps_trigger(api, builder_cfg, got_revision, |
| 285 got_revision, is_trybot) | 333 infrabots_dir, extra_hashes) |
| 286 if do_perf_steps: | 334 if do_perf_steps: |
| 287 perf_task = perf_steps_trigger(api, infrabots_dir, compile_hash, dimensions, | 335 perf_task = perf_steps_trigger(api, builder_cfg, got_revision, |
| 288 got_revision, is_trybot) | 336 infrabots_dir, extra_hashes) |
| 337 is_trybot = builder_cfg['is_trybot'] |
| 289 if test_task: | 338 if test_task: |
| 290 test_steps_collect(api, test_task, builder_spec['upload_dm_results'], | 339 test_steps_collect(api, test_task, builder_spec['upload_dm_results'], |
| 291 got_revision, is_trybot) | 340 got_revision, is_trybot) |
| 292 if perf_task: | 341 if perf_task: |
| 293 perf_steps_collect(api, perf_task, builder_spec['upload_perf_results'], | 342 perf_steps_collect(api, perf_task, builder_spec['upload_perf_results'], |
| 294 got_revision, is_trybot) | 343 got_revision, is_trybot) |
| 295 | 344 |
| 296 | 345 |
| 297 def GenTests(api): | 346 def GenTests(api): |
| 298 for mastername, slaves in TEST_BUILDERS.iteritems(): | 347 for mastername, slaves in TEST_BUILDERS.iteritems(): |
| 299 for slavename, builders_by_slave in slaves.iteritems(): | 348 for slavename, builders_by_slave in slaves.iteritems(): |
| 300 for builder in builders_by_slave: | 349 for builder in builders_by_slave: |
| 301 test = ( | 350 test = ( |
| 302 api.test(builder) + | 351 api.test(builder) + |
| 303 api.properties(buildername=builder, | 352 api.properties(buildername=builder, |
| 304 mastername=mastername, | 353 mastername=mastername, |
| 305 slavename=slavename, | 354 slavename=slavename, |
| 306 buildnumber=5, | 355 buildnumber=5, |
| 307 revision='abc123') + | 356 revision='abc123') + |
| 308 api.path.exists( | 357 api.path.exists( |
| 309 api.path['slave_build'].join('skia'), | 358 api.path['slave_build'].join('skia'), |
| 310 api.path['slave_build'].join('tmp', 'uninteresting_hashes.txt') | 359 api.path['slave_build'].join('tmp', 'uninteresting_hashes.txt') |
| 311 ) | 360 ) |
| 312 ) | 361 ) |
| 313 if 'Trybot' in builder: | 362 if 'Trybot' in builder: |
| 314 test += api.properties(issue=500, | 363 test += api.properties(issue=500, |
| 315 patchset=1, | 364 patchset=1, |
| 316 rietveld='https://codereview.chromium.org') | 365 rietveld='https://codereview.chromium.org') |
| 317 if 'Win' in builder: | 366 test += api.step_data( |
| 318 test += api.step_data( | 367 'upload new .isolated file for compile_skia', |
| 319 'upload new .isolated file for compile_skia', | 368 stdout=api.raw_io.output('def456 XYZ.isolated')) |
| 320 stdout=api.raw_io.output('def456 XYZ.isolated')) | |
| 321 if 'Test' in builder: | 369 if 'Test' in builder: |
| 322 test += api.step_data( | 370 test += api.step_data( |
| 323 'upload new .isolated file for test_skia', | 371 'upload new .isolated file for test_skia', |
| 324 stdout=api.raw_io.output('def456 XYZ.isolated')) | 372 stdout=api.raw_io.output('def456 XYZ.isolated')) |
| 325 if ('Test' in builder and 'Debug' in builder) or 'Perf' in builder: | 373 if ('Test' in builder and 'Debug' in builder) or 'Perf' in builder: |
| 326 test += api.step_data( | 374 test += api.step_data( |
| 327 'upload new .isolated file for perf_skia', | 375 'upload new .isolated file for perf_skia', |
| 328 stdout=api.raw_io.output('def456 XYZ.isolated')) | 376 stdout=api.raw_io.output('def456 XYZ.isolated')) |
| 329 | 377 |
| 330 yield test | 378 yield test |
| OLD | NEW |