Index: infra/bots/recipes/swarm_trigger.py |
diff --git a/infra/bots/recipes/swarm_trigger.py b/infra/bots/recipes/swarm_trigger.py |
new file mode 100644 |
index 0000000000000000000000000000000000000000..5bc7ca653c87fda5ccea82d76bba3a5dfb4dd917 |
--- /dev/null |
+++ b/infra/bots/recipes/swarm_trigger.py |
@@ -0,0 +1,687 @@ |
+# Copyright 2016 The Chromium Authors. All rights reserved. |
+# Use of this source code is governed by a BSD-style license that can be |
+# found in the LICENSE file. |
+ |
+ |
+# Recipe module for Skia Swarming trigger. |
+ |
+ |
+import json |
+ |
+ |
+DEPS = [ |
+ 'build/file', |
+ 'build/gsutil', |
+ 'depot_tools/depot_tools', |
+ 'depot_tools/git', |
+ 'depot_tools/tryserver', |
+ 'recipe_engine/path', |
+ 'recipe_engine/properties', |
+ 'recipe_engine/python', |
+ 'recipe_engine/raw_io', |
+ 'recipe_engine/step', |
+ 'recipe_engine/time', |
+ 'skia', |
+ 'skia_swarming', |
+] |
+ |
+ |
+TEST_BUILDERS = { |
+ 'client.skia': { |
+ 'skiabot-linux-swarm-000': [ |
+ 'Test-Ubuntu-GCC-ShuttleA-GPU-GTX550Ti-x86_64-Release-Valgrind', |
+ 'Test-Ubuntu-Clang-GCE-CPU-AVX2-x86_64-Coverage-Trybot', |
+ 'Build-Mac-Clang-x86_64-Release', |
+ 'Build-Ubuntu-GCC-Arm64-Debug-Android_Vulkan', |
+ 'Build-Ubuntu-GCC-x86_64-Debug', |
+ 'Build-Ubuntu-GCC-x86_64-Release-RemoteRun', |
+ 'Build-Ubuntu-GCC-x86_64-Release-Trybot', |
+ 'Build-Win-MSVC-x86_64-Release', |
+ 'Build-Win-MSVC-x86_64-Release-Vulkan', |
+ 'Housekeeper-PerCommit', |
+ 'Housekeeper-Nightly-RecreateSKPs_Canary', |
+ 'Infra-PerCommit', |
+ 'Perf-Ubuntu-GCC-GCE-CPU-AVX2-x86_64-Release-Trybot', |
+ 'Test-Android-GCC-Nexus7v2-GPU-Tegra3-Arm7-Release', |
+ 'Test-Android-GCC-NVIDIA_Shield-GPU-TegraX1-Arm64-Debug-Vulkan', |
+ 'Test-iOS-Clang-iPad4-GPU-SGX554-Arm7-Release', |
+ 'Test-Mac-Clang-MacMini6.2-CPU-AVX-x86_64-Release', |
+ 'Test-Ubuntu-GCC-GCE-CPU-AVX2-x86_64-Debug', |
+ 'Test-Ubuntu-GCC-GCE-CPU-AVX2-x86_64-Debug-MSAN', |
+ 'Test-Win8-MSVC-ShuttleA-GPU-HD7770-x86_64-Release', |
+ 'Test-Win8-MSVC-ShuttleB-CPU-AVX2-x86_64-Release', |
+ ], |
+ }, |
+} |
+ |
+ |
+def derive_compile_bot_name(builder_name, builder_spec): |
+ builder_cfg = builder_spec['builder_cfg'] |
+ if builder_cfg['role'] == 'Housekeeper': |
+ return 'Build-Ubuntu-GCC-x86_64-Release-Shared' |
+ if builder_cfg['role'] in ('Test', 'Perf'): |
+ os = builder_cfg['os'] |
+ extra_config = builder_cfg.get('extra_config') |
+ if os == 'Android': |
+ if extra_config == 'Vulkan': |
+ extra_config = '%s_%s' % (os, 'Vulkan') |
+ else: |
+ extra_config = os |
+ os = 'Ubuntu' |
+ elif os == 'iOS': |
+ extra_config = os |
+ os = 'Mac' |
+ elif 'Win' in os: |
+ os = 'Win' |
+ builder_name = 'Build-%s-%s-%s-%s' % ( |
+ os, |
+ builder_cfg['compiler'], |
+ builder_cfg['arch'], |
+ builder_cfg['configuration'] |
+ ) |
+ if extra_config: |
+ builder_name += '-%s' % extra_config |
+ if builder_cfg['is_trybot']: |
+ builder_name += '-Trybot' |
+ return builder_name |
+ |
+ |
+def swarm_dimensions(builder_spec): |
+ """Return a dict of keys and values to be used as Swarming bot dimensions.""" |
+ dimensions = { |
+ 'pool': 'Skia', |
+ } |
+ builder_cfg = builder_spec['builder_cfg'] |
+ dimensions['os'] = builder_cfg.get('os', 'Ubuntu') |
+ if 'Win' in builder_cfg.get('os', ''): |
+ dimensions['os'] = 'Windows' |
+ if builder_cfg['role'] in ('Test', 'Perf'): |
+ if 'Android' in builder_cfg['os']: |
+ # For Android, the device type is a better dimension than CPU or GPU. |
+ dimensions['device_type'] = builder_spec['product.board'] |
+ elif 'iOS' in builder_cfg['os']: |
+ # For iOS, the device type is a better dimension than CPU or GPU. |
+ dimensions['device'] = builder_spec['device_cfg'] |
+ # TODO(borenet): Replace this hack with something better. |
+ dimensions['os'] = 'iOS-9.2' |
+ elif builder_cfg['cpu_or_gpu'] == 'CPU': |
+ dimensions['gpu'] = 'none' |
+ dimensions['cpu'] = { |
+ 'AVX': 'x86-64', |
+ 'AVX2': 'x86-64-avx2', |
+ 'SSE4': 'x86-64', |
+ }[builder_cfg['cpu_or_gpu_value']] |
+ if ('Win' in builder_cfg['os'] and |
+ builder_cfg['cpu_or_gpu_value'] == 'AVX2'): |
+ # AVX2 is not correctly detected on Windows. Fall back on other |
+ # dimensions to ensure that we correctly target machines which we know |
+ # have AVX2 support. |
+ dimensions['cpu'] = 'x86-64' |
+ dimensions['os'] = 'Windows-2008ServerR2-SP1' |
+ else: |
+ dimensions['gpu'] = { |
+ 'GeForce320M': '10de:08a4', |
+ 'GT610': '10de:104a', |
+ 'GTX550Ti': '10de:1244', |
+ 'GTX660': '10de:11c0', |
+ 'GTX960': '10de:1401', |
+ 'HD4000': '8086:0a2e', |
+ 'HD4600': '8086:0412', |
+ 'HD7770': '1002:683d', |
+ }[builder_cfg['cpu_or_gpu_value']] |
+ else: |
+ dimensions['gpu'] = 'none' |
+ return dimensions |
+ |
+ |
+def fix_filemodes(api, path): |
+ """Set all filemodes to 644 or 755 in the given directory path.""" |
+ api.python.inline( |
+ name='fix filemodes', |
+ program='''import os |
+for r, _, files in os.walk(os.getcwd()): |
+ for fname in files: |
+ f = os.path.join(r, fname) |
+ if os.path.isfile(f): |
+ if os.access(f, os.X_OK): |
+ os.chmod(f, 0755) |
+ else: |
+ os.chmod(f, 0644) |
+''', |
+ cwd=path) |
+ |
+ |
+def trigger_task(api, task_name, builder, master, slave, buildnumber, |
+ builder_spec, got_revision, infrabots_dir, idempotent=False, |
+ store_output=True, extra_isolate_hashes=None, expiration=None, |
+ hard_timeout=None, io_timeout=None, cipd_packages=None): |
+ """Trigger the given bot to run as a Swarming task.""" |
+ # TODO(borenet): We're using Swarming directly to run the recipe through |
+ # recipes.py. Once it's possible to track the state of a Buildbucket build, |
+ # we should switch to use the trigger recipe module instead. |
+ |
+ properties = { |
+ 'buildername': builder, |
+ 'mastername': master, |
+ 'buildnumber': buildnumber, |
+ 'reason': 'Triggered by Skia swarm_trigger Recipe', |
+ 'revision': got_revision, |
+ 'slavename': slave, |
+ 'swarm_out_dir': '${ISOLATED_OUTDIR}', |
+ } |
+ builder_cfg = builder_spec['builder_cfg'] |
+ if builder_cfg['is_trybot']: |
+ properties['issue'] = str(api.properties['issue']) |
+ properties['patchset'] = str(api.properties['patchset']) |
+ properties['rietveld'] = api.properties['rietveld'] |
+ |
+ extra_args = [ |
+ '--workdir', '../../..', |
+ 'swarm_%s' % task_name, |
+ ] |
+ for k, v in properties.iteritems(): |
+ extra_args.append('%s=%s' % (k, v)) |
+ |
+ isolate_base_dir = api.path['slave_build'] |
+ dimensions = swarm_dimensions(builder_spec) |
+ isolate_blacklist = ['.git', 'out', '*.pyc', '.recipe_deps'] |
+ isolate_vars = { |
+ 'WORKDIR': api.path['slave_build'], |
+ } |
+ |
+ isolate_file = '%s_skia.isolate' % task_name |
+ if 'Coverage' == builder_cfg.get('configuration'): |
+ isolate_file = 'coverage_skia.isolate' |
+ if 'RecreateSKPs' in builder: |
+ isolate_file = 'compile_skia.isolate' |
+ return api.skia_swarming.isolate_and_trigger_task( |
+ infrabots_dir.join(isolate_file), |
+ isolate_base_dir, |
+ '%s_skia' % task_name, |
+ isolate_vars, |
+ dimensions, |
+ isolate_blacklist=isolate_blacklist, |
+ extra_isolate_hashes=extra_isolate_hashes, |
+ idempotent=idempotent, |
+ store_output=store_output, |
+ extra_args=extra_args, |
+ expiration=expiration, |
+ hard_timeout=hard_timeout, |
+ io_timeout=io_timeout, |
+ cipd_packages=cipd_packages) |
+ |
+ |
+def checkout_steps(api): |
+ """Run the steps to obtain a checkout of Skia.""" |
+ # In this case, we're already running inside a checkout of Skia, so just |
+ # report the currently-checked-out commit. |
+ checkout_path = api.path['root'].join('skia') |
+ got_revision = api.git( |
+ 'rev-parse', 'HEAD', cwd=checkout_path, |
+ stdout=api.raw_io.output(), |
+ step_test_data=lambda: api.raw_io.test_api.stream_output('abc123\n'), |
+ ).stdout.rstrip() |
+ cmd = ['python', '-c', '"print \'%s\'"' % got_revision] |
+ res = api.step('got_revision', cmd=cmd) |
+ res.presentation.properties['got_revision'] = got_revision |
+ api.path['checkout'] = checkout_path |
+ fix_filemodes(api, api.path['checkout']) |
+ return got_revision |
+ |
+ |
+def housekeeper_swarm(api, builder_spec, got_revision, infrabots_dir, |
+ extra_isolate_hashes): |
+ task = trigger_task( |
+ api, |
+ 'housekeeper', |
+ api.properties['buildername'], |
+ api.properties['mastername'], |
+ api.properties['slavename'], |
+ api.properties['buildnumber'], |
+ builder_spec, |
+ got_revision, |
+ infrabots_dir, |
+ idempotent=False, |
+ store_output=False, |
+ extra_isolate_hashes=extra_isolate_hashes) |
+ return api.skia_swarming.collect_swarming_task(task) |
+ |
+ |
+def recreate_skps_swarm(api, builder_spec, got_revision, infrabots_dir, |
+ extra_isolate_hashes): |
+ task = trigger_task( |
+ api, |
+ 'RecreateSKPs', |
+ api.properties['buildername'], |
+ api.properties['mastername'], |
+ api.properties['slavename'], |
+ api.properties['buildnumber'], |
+ builder_spec, |
+ got_revision, |
+ infrabots_dir, |
+ idempotent=False, |
+ store_output=False, |
+ extra_isolate_hashes=extra_isolate_hashes) |
+ return api.skia_swarming.collect_swarming_task(task) |
+ |
+ |
+def infra_swarm(api, got_revision, infrabots_dir, extra_isolate_hashes): |
+ # Fake the builder spec. |
+ builder_spec = { |
+ 'builder_cfg': { |
+ 'role': 'Infra', |
+ 'is_trybot': api.properties['buildername'].endswith('-Trybot'), |
+ } |
+ } |
+ task = trigger_task( |
+ api, |
+ 'infra', |
+ api.properties['buildername'], |
+ api.properties['mastername'], |
+ api.properties['slavename'], |
+ api.properties['buildnumber'], |
+ builder_spec, |
+ got_revision, |
+ infrabots_dir, |
+ idempotent=False, |
+ store_output=False, |
+ extra_isolate_hashes=extra_isolate_hashes) |
+ return api.skia_swarming.collect_swarming_task(task) |
+ |
+ |
+def compile_steps_swarm(api, builder_spec, got_revision, infrabots_dir, |
+ extra_isolate_hashes, cipd_packages): |
+ builder_name = derive_compile_bot_name(api.properties['buildername'], |
+ builder_spec) |
+ compile_builder_spec = builder_spec |
+ if builder_name != api.properties['buildername']: |
+ compile_builder_spec = api.skia.get_builder_spec( |
+ api.path['slave_build'].join('skia'), builder_name) |
+ |
+ extra_hashes = extra_isolate_hashes[:] |
+ |
+ # Windows bots require a toolchain. |
+ if 'Win' in builder_name: |
+ version_file = infrabots_dir.join('assets', 'win_toolchain', 'VERSION') |
+ version = api.skia._readfile(version_file, |
+ name='read win_toolchain VERSION', |
+ test_data='0').rstrip() |
+ version = 'version:%s' % version |
+ pkg = ('t', 'skia/bots/win_toolchain', version) |
+ cipd_packages.append(pkg) |
+ |
+ if 'Vulkan' in builder_name: |
+ version_file = infrabots_dir.join('assets', 'win_vulkan_sdk', 'VERSION') |
+ cipd_packages.append(cipd_pkg(api, infrabots_dir, 'win_vulkan_sdk')) |
+ |
+ # Fake these properties for compile tasks so that they can be de-duped. |
+ master = 'client.skia.compile' |
+ slave = 'skiabot-dummy-compile-slave' |
+ buildnumber = 1 |
+ |
+ task = trigger_task( |
+ api, |
+ 'compile', |
+ builder_name, |
+ master, |
+ slave, |
+ buildnumber, |
+ compile_builder_spec, |
+ got_revision, |
+ infrabots_dir, |
+ idempotent=True, |
+ store_output=False, |
+ extra_isolate_hashes=extra_hashes, |
+ cipd_packages=cipd_packages) |
+ |
+ # Wait for compile to finish, record the results hash. |
+ return api.skia_swarming.collect_swarming_task_isolate_hash(task) |
+ |
+ |
+def get_timeouts(builder_cfg): |
+ """Some builders require longer than the default timeouts. |
+ |
+ Returns tuple of (expiration, hard_timeout, io_timeout). If those values are |
+ none then default timeouts should be used. |
+ """ |
+ expiration = None |
+ hard_timeout = None |
+ io_timeout = None |
+ if 'Valgrind' in builder_cfg.get('extra_config', ''): |
+ expiration = 2*24*60*60 |
+ hard_timeout = 9*60*60 |
+ io_timeout = 60*60 |
+ return expiration, hard_timeout, io_timeout |
+ |
+ |
+def perf_steps_trigger(api, builder_spec, got_revision, infrabots_dir, |
+ extra_hashes, cipd_packages): |
+ """Trigger perf tests via Swarming.""" |
+ |
+ expiration, hard_timeout, io_timeout = get_timeouts( |
+ builder_spec['builder_cfg']) |
+ return trigger_task( |
+ api, |
+ 'perf', |
+ api.properties['buildername'], |
+ api.properties['mastername'], |
+ api.properties['slavename'], |
+ api.properties['buildnumber'], |
+ builder_spec, |
+ got_revision, |
+ infrabots_dir, |
+ extra_isolate_hashes=extra_hashes, |
+ expiration=expiration, |
+ hard_timeout=hard_timeout, |
+ io_timeout=io_timeout, |
+ cipd_packages=cipd_packages) |
+ |
+ |
+def perf_steps_collect(api, task, upload_perf_results, got_revision, |
+ is_trybot): |
+ """Wait for perf steps to finish and upload results.""" |
+ # Wait for nanobench to finish, download the results. |
+ api.skia.rmtree(task.task_output_dir) |
+ api.skia_swarming.collect_swarming_task(task) |
+ |
+ # Upload the results. |
+ if upload_perf_results: |
+ perf_data_dir = api.path['slave_build'].join( |
+ 'perfdata', api.properties['buildername'], 'data') |
+ git_timestamp = api.git.get_timestamp(test_data='1408633190', |
+ infra_step=True) |
+ api.skia.rmtree(perf_data_dir) |
+ api.file.makedirs('perf_dir', perf_data_dir, infra_step=True) |
+ src_results_file = task.task_output_dir.join( |
+ '0', 'perfdata', api.properties['buildername'], 'data', |
+ 'nanobench_%s.json' % got_revision) |
+ dst_results_file = perf_data_dir.join( |
+ 'nanobench_%s_%s.json' % (got_revision, git_timestamp)) |
+ api.file.copy('perf_results', src_results_file, dst_results_file, |
+ infra_step=True) |
+ |
+ gsutil_path = api.depot_tools.gsutil_py_path |
+ upload_args = [api.properties['buildername'], api.properties['buildnumber'], |
+ perf_data_dir, got_revision, gsutil_path] |
+ if is_trybot: |
+ upload_args.append(api.properties['issue']) |
+ api.python( |
+ 'Upload perf results', |
+ script=api.skia.resource('upload_bench_results.py'), |
+ args=upload_args, |
+ cwd=api.path['checkout'], |
+ env=api.skia.gsutil_env('chromium-skia-gm.boto'), |
+ infra_step=True) |
+ |
+ |
+def test_steps_trigger(api, builder_spec, got_revision, infrabots_dir, |
+ extra_hashes, cipd_packages): |
+ """Trigger DM via Swarming.""" |
+ expiration, hard_timeout, io_timeout = get_timeouts( |
+ builder_spec['builder_cfg']) |
+ return trigger_task( |
+ api, |
+ 'test', |
+ api.properties['buildername'], |
+ api.properties['mastername'], |
+ api.properties['slavename'], |
+ api.properties['buildnumber'], |
+ builder_spec, |
+ got_revision, |
+ infrabots_dir, |
+ extra_isolate_hashes=extra_hashes, |
+ expiration=expiration, |
+ hard_timeout=hard_timeout, |
+ io_timeout=io_timeout, |
+ cipd_packages=cipd_packages) |
+ |
+ |
+def test_steps_collect(api, task, upload_dm_results, got_revision, is_trybot, |
+ builder_cfg): |
+ """Collect the test results from Swarming.""" |
+ # Wait for tests to finish, download the results. |
+ api.skia.rmtree(task.task_output_dir) |
+ api.skia_swarming.collect_swarming_task(task) |
+ |
+ # Upload the results. |
+ if upload_dm_results: |
+ dm_dir = api.path['slave_build'].join('dm') |
+ dm_src = task.task_output_dir.join('0', 'dm') |
+ api.skia.rmtree(dm_dir) |
+ api.file.copytree('dm_dir', dm_src, dm_dir, infra_step=True) |
+ |
+ # Upload them to Google Storage. |
+ api.python( |
+ 'Upload DM Results', |
+ script=api.skia.resource('upload_dm_results.py'), |
+ args=[ |
+ dm_dir, |
+ got_revision, |
+ api.properties['buildername'], |
+ api.properties['buildnumber'], |
+ api.properties['issue'] if is_trybot else '', |
+ api.path['slave_build'].join('skia', 'common', 'py', 'utils'), |
+ ], |
+ cwd=api.path['checkout'], |
+ env=api.skia.gsutil_env('chromium-skia-gm.boto'), |
+ infra_step=True) |
+ |
+ if builder_cfg['configuration'] == 'Coverage': |
+ upload_coverage_results(api, task, got_revision, is_trybot) |
+ |
+ |
+def upload_coverage_results(api, task, got_revision, is_trybot): |
+ results_dir = task.task_output_dir.join('0') |
+ git_timestamp = api.git.get_timestamp(test_data='1408633190', |
+ infra_step=True) |
+ |
+ # Upload raw coverage data. |
+ cov_file_basename = '%s.cov' % got_revision |
+ cov_file = results_dir.join(cov_file_basename) |
+ now = api.time.utcnow() |
+ gs_json_path = '/'.join(( |
+ str(now.year).zfill(4), str(now.month).zfill(2), |
+ str(now.day).zfill(2), str(now.hour).zfill(2), |
+ api.properties['buildername'], |
+ str(api.properties['buildnumber']))) |
+ if is_trybot: |
+ gs_json_path = '/'.join(('trybot', gs_json_path, |
+ str(api.properties['issue']))) |
+ api.gsutil.upload( |
+ name='upload raw coverage data', |
+ source=cov_file, |
+ bucket='skia-infra', |
+ dest='/'.join(('coverage-raw-v1', gs_json_path, |
+ cov_file_basename)), |
+ env={'AWS_CREDENTIAL_FILE': None, 'BOTO_CONFIG': None}, |
+ ) |
+ |
+ # Transform the nanobench_${git_hash}.json file received from swarming bot |
+ # into the nanobench_${git_hash}_${timestamp}.json file |
+ # upload_bench_results.py expects. |
+ src_nano_file = results_dir.join('nanobench_%s.json' % got_revision) |
+ dst_nano_file = results_dir.join( |
+ 'nanobench_%s_%s.json' % (got_revision, git_timestamp)) |
+ api.file.copy('nanobench JSON', src_nano_file, dst_nano_file, |
+ infra_step=True) |
+ api.file.remove('old nanobench JSON', src_nano_file) |
+ |
+ # Upload nanobench JSON data. |
+ gsutil_path = api.depot_tools.gsutil_py_path |
+ upload_args = [api.properties['buildername'], api.properties['buildnumber'], |
+ results_dir, got_revision, gsutil_path] |
+ if is_trybot: |
+ upload_args.append(api.properties['issue']) |
+ api.python( |
+ 'upload nanobench coverage results', |
+ script=api.skia.resource('upload_bench_results.py'), |
+ args=upload_args, |
+ cwd=api.path['checkout'], |
+ env=api.skia.gsutil_env('chromium-skia-gm.boto'), |
+ infra_step=True) |
+ |
+ # Transform the coverage_by_line_${git_hash}.json file received from |
+ # swarming bot into a coverage_by_line_${git_hash}_${timestamp}.json file. |
+ src_lbl_file = results_dir.join('coverage_by_line_%s.json' % got_revision) |
+ dst_lbl_file_basename = 'coverage_by_line_%s_%s.json' % ( |
+ got_revision, git_timestamp) |
+ dst_lbl_file = results_dir.join(dst_lbl_file_basename) |
+ api.file.copy('Line-by-line coverage JSON', src_lbl_file, dst_lbl_file, |
+ infra_step=True) |
+ api.file.remove('old line-by-line coverage JSON', src_lbl_file) |
+ |
+ # Upload line-by-line coverage data. |
+ api.gsutil.upload( |
+ name='upload line-by-line coverage data', |
+ source=dst_lbl_file, |
+ bucket='skia-infra', |
+ dest='/'.join(('coverage-json-v1', gs_json_path, |
+ dst_lbl_file_basename)), |
+ env={'AWS_CREDENTIAL_FILE': None, 'BOTO_CONFIG': None}, |
+ ) |
+ |
+ |
+def cipd_pkg(api, infrabots_dir, asset_name): |
+ """Find and return the CIPD package info for the given asset.""" |
+ version_file = infrabots_dir.join('assets', asset_name, 'VERSION') |
+ version = api.skia._readfile(version_file, |
+ name='read %s VERSION' % asset_name, |
+ test_data='0').rstrip() |
+ version = 'version:%s' % version |
+ return (asset_name, 'skia/bots/%s' % asset_name, version) |
+ |
+ |
+def RunSteps(api): |
+ got_revision = checkout_steps(api) |
+ infrabots_dir = api.path['checkout'].join('infra', 'bots') |
+ api.skia_swarming.setup( |
+ infrabots_dir.join('tools', 'luci-go'), |
+ swarming_rev='') |
+ |
+ # Run gsutil.py to ensure that it's installed. |
+ api.gsutil(['help']) |
+ |
+ extra_hashes = [] |
+ |
+ # Get ready to compile. |
+ compile_cipd_deps = [] |
+ extra_compile_hashes = [] |
+ |
+ infrabots_dir = api.path['checkout'].join('infra', 'bots') |
+ if 'Infra' in api.properties['buildername']: |
+ return infra_swarm(api, got_revision, infrabots_dir, extra_hashes) |
+ |
+ builder_spec = api.skia.get_builder_spec(api.path['checkout'], |
+ api.properties['buildername']) |
+ builder_cfg = builder_spec['builder_cfg'] |
+ |
+ if 'RecreateSKPs' in api.properties['buildername']: |
+ recreate_skps_swarm(api, builder_spec, got_revision, infrabots_dir, |
+ extra_hashes) |
+ return |
+ |
+ # Android bots require an SDK. |
+ if 'Android' in api.properties['buildername']: |
+ compile_cipd_deps.append(cipd_pkg(api, infrabots_dir, 'android_sdk')) |
+ |
+ # Compile. |
+ do_compile_steps = builder_spec.get('do_compile_steps', True) |
+ if do_compile_steps: |
+ extra_hashes.append(compile_steps_swarm( |
+ api, builder_spec, got_revision, infrabots_dir, extra_compile_hashes, |
+ cipd_packages=compile_cipd_deps)) |
+ |
+ if builder_cfg['role'] == 'Housekeeper': |
+ housekeeper_swarm(api, builder_spec, got_revision, infrabots_dir, |
+ extra_hashes) |
+ return |
+ |
+ # Get ready to test/perf. |
+ |
+ # CIPD packages needed by test/perf. |
+ cipd_packages = [] |
+ |
+ do_test_steps = builder_spec['do_test_steps'] |
+ do_perf_steps = builder_spec['do_perf_steps'] |
+ |
+ if not (do_test_steps or do_perf_steps): |
+ return |
+ |
+ # SKPs, SkImages. |
+ cipd_packages.append(cipd_pkg(api, infrabots_dir, 'skp')) |
+ cipd_packages.append(cipd_pkg(api, infrabots_dir, 'skimage')) |
+ |
+ # Trigger test and perf tasks. |
+ test_task = None |
+ perf_task = None |
+ if do_test_steps: |
+ test_task = test_steps_trigger(api, builder_spec, got_revision, |
+ infrabots_dir, extra_hashes, cipd_packages) |
+ if do_perf_steps: |
+ perf_task = perf_steps_trigger(api, builder_spec, got_revision, |
+ infrabots_dir, extra_hashes, cipd_packages) |
+ is_trybot = builder_cfg['is_trybot'] |
+ if test_task: |
+ test_steps_collect(api, test_task, builder_spec['upload_dm_results'], |
+ got_revision, is_trybot, builder_cfg) |
+ if perf_task: |
+ perf_steps_collect(api, perf_task, builder_spec['upload_perf_results'], |
+ got_revision, is_trybot) |
+ |
+ |
+def test_for_bot(api, builder, mastername, slavename, testname=None): |
+ """Generate a test for the given bot.""" |
+ testname = testname or builder |
+ test = ( |
+ api.test(testname) + |
+ api.properties(buildername=builder, |
+ mastername=mastername, |
+ slavename=slavename, |
+ buildnumber=5, |
+ path_config='kitchen', |
+ revision='abc123') |
+ ) |
+ paths = [ |
+ api.path['slave_build'].join('skia'), |
+ api.path['slave_build'].join('tmp', 'uninteresting_hashes.txt'), |
+ ] |
+ if 'Trybot' in builder: |
+ test += api.properties(issue=500, |
+ patchset=1, |
+ rietveld='https://codereview.chromium.org') |
+ if 'Android' in builder: |
+ paths.append(api.path['slave_build'].join( |
+ 'skia', 'infra', 'bots', 'assets', 'android_sdk', 'VERSION')) |
+ if 'Test' in builder and 'Coverage' not in builder: |
+ test += api.step_data( |
+ 'upload new .isolated file for test_skia', |
+ stdout=api.raw_io.output('def456 XYZ.isolated')) |
+ if ('Test' in builder and 'Debug' in builder) or 'Perf' in builder or ( |
+ 'Valgrind' in builder and 'Test' in builder): |
+ test += api.step_data( |
+ 'upload new .isolated file for perf_skia', |
+ stdout=api.raw_io.output('def456 XYZ.isolated')) |
+ if 'Housekeeper' in builder and 'RecreateSKPs' not in builder: |
+ test += api.step_data( |
+ 'upload new .isolated file for housekeeper_skia', |
+ stdout=api.raw_io.output('def456 XYZ.isolated')) |
+ if 'Win' in builder: |
+ paths.append(api.path['slave_build'].join( |
+ 'skia', 'infra', 'bots', 'assets', 'win_toolchain', 'VERSION')) |
+ paths.append(api.path['slave_build'].join( |
+ 'skia', 'infra', 'bots', 'assets', 'win_vulkan_sdk', 'VERSION')) |
+ paths.append(api.path['slave_build'].join( |
+ 'skia', 'infra', 'bots', 'assets', 'skimage', 'VERSION')) |
+ paths.append(api.path['slave_build'].join( |
+ 'skia', 'infra', 'bots', 'assets', 'skp', 'VERSION')) |
+ |
+ test += api.path.exists(*paths) |
+ |
+ return test |
+ |
+ |
+def GenTests(api): |
+ for mastername, slaves in TEST_BUILDERS.iteritems(): |
+ for slavename, builders_by_slave in slaves.iteritems(): |
+ for builder in builders_by_slave: |
+ yield test_for_bot(api, builder, mastername, slavename) |