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

Unified Diff: infra/bots/common.py

Issue 1827413002: Fixes for Swarming recipes (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Reinstate tmp_dir Created 4 years, 9 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « infra/bots/add_isolated_input.py ('k') | infra/bots/compile_skia.isolate » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: infra/bots/common.py
diff --git a/infra/bots/common.py b/infra/bots/common.py
index 8d91f743bd949fa5ec93d7236e3c51681edee4a9..e4314dd78fa100ff2e606b890a41f27f8d32f16b 100644
--- a/infra/bots/common.py
+++ b/infra/bots/common.py
@@ -6,91 +6,20 @@
# found in the LICENSE file.
-import contextlib
-import glob
-import math
import os
-import psutil
import shutil
-import socket
import subprocess
-import sys
-import time
-import urllib2
-from flavor import android_flavor
-from flavor import chromeos_flavor
-from flavor import cmake_flavor
-from flavor import coverage_flavor
-from flavor import default_flavor
-from flavor import ios_flavor
-from flavor import valgrind_flavor
-from flavor import xsan_flavor
-
-
-CONFIG_COVERAGE = 'Coverage'
-CONFIG_DEBUG = 'Debug'
-CONFIG_RELEASE = 'Release'
-VALID_CONFIGS = (CONFIG_COVERAGE, CONFIG_DEBUG, CONFIG_RELEASE)
-
-BUILD_PRODUCTS_WHITELIST = [
- 'dm',
- 'dm.exe',
- 'nanobench',
- 'nanobench.exe',
- '*.so',
- '*.dll',
-]
-
-GM_ACTUAL_FILENAME = 'actual-results.json'
-GM_EXPECTATIONS_FILENAME = 'expected-results.json'
-GM_IGNORE_TESTS_FILENAME = 'ignored-tests.txt'
-
-GOLD_UNINTERESTING_HASHES_URL = 'https://gold.skia.org/_/hashes'
GS_GM_BUCKET = 'chromium-skia-gm'
-GS_SUMMARIES_BUCKET = 'chromium-skia-gm-summaries'
GS_SUBDIR_TMPL_SK_IMAGE = 'skimage/v%s'
GS_SUBDIR_TMPL_SKP = 'playback_%s/skps'
-SKIA_REPO = 'https://skia.googlesource.com/skia.git'
-INFRA_REPO = 'https://skia.googlesource.com/buildbot.git'
-
-SERVICE_ACCOUNT_FILE = 'service-account-skia.json'
-SERVICE_ACCOUNT_INTERNAL_FILE = 'service-account-skia-internal.json'
-
VERSION_FILE_SK_IMAGE = 'SK_IMAGE_VERSION'
VERSION_FILE_SKP = 'SKP_VERSION'
-def is_android(bot_cfg):
- """Determine whether the given bot is an Android bot."""
- return ('Android' in bot_cfg.get('extra_config', '') or
- bot_cfg.get('os') == 'Android')
-
-def is_chromeos(bot_cfg):
- return ('CrOS' in bot_cfg.get('extra_config', '') or
- bot_cfg.get('os') == 'ChromeOS')
-
-def is_cmake(bot_cfg):
- return 'CMake' in bot_cfg.get('extra_config', '')
-
-def is_ios(bot_cfg):
- return ('iOS' in bot_cfg.get('extra_config', '') or
- bot_cfg.get('os') == 'iOS')
-
-
-def is_valgrind(bot_cfg):
- return 'Valgrind' in bot_cfg.get('extra_config', '')
-
-
-def is_xsan(bot_cfg):
- return (bot_cfg.get('extra_config') == 'ASAN' or
- bot_cfg.get('extra_config') == 'MSAN' or
- bot_cfg.get('extra_config') == 'TSAN')
-
-
def download_dir(skia_dir, tmp_dir, version_file, gs_path_tmpl, dst_dir):
# Ensure that the tmp_dir exists.
if not os.path.isdir(tmp_dir):
@@ -124,368 +53,3 @@ def download_dir(skia_dir, tmp_dir, version_file, gs_path_tmpl, dst_dir):
subprocess.check_call(['gsutil', 'cp', '-R', gs_path, dst_dir])
with open(actual_version_file, 'w') as f:
f.write(expected_version)
-
-
-def get_uninteresting_hashes(hashes_file):
- retries = 5
- timeout = 60
- wait_base = 15
-
- socket.setdefaulttimeout(timeout)
- for retry in range(retries):
- try:
- with contextlib.closing(
- urllib2.urlopen(GOLD_UNINTERESTING_HASHES_URL, timeout=timeout)) as w:
- hashes = w.read()
- with open(hashes_file, 'w') as f:
- f.write(hashes)
- break
- except Exception as e:
- print >> sys.stderr, 'Failed to get uninteresting hashes from %s:\n%s' % (
- GOLD_UNINTERESTING_HASHES_URL, e)
- if retry == retries:
- raise
- waittime = wait_base * math.pow(2, retry)
- print 'Retry in %d seconds.' % waittime
- time.sleep(waittime)
-
-
-class BotInfo(object):
- def __init__(self, bot_name, swarm_out_dir):
- """Initialize the bot, given its name.
-
- Assumes that CWD is the directory containing this file.
- """
- self.name = bot_name
- self.skia_dir = os.path.abspath(os.path.join(
- os.path.dirname(os.path.realpath(__file__)),
- os.pardir, os.pardir))
- self.swarm_out_dir = swarm_out_dir
- os.chdir(self.skia_dir)
- self.build_dir = os.path.abspath(os.path.join(self.skia_dir, os.pardir))
- self.infrabots_dir = os.path.join(self.skia_dir, 'infra', 'bots')
- self.home_dir = os.path.expanduser('~')
-
- self.spec = self.get_bot_spec(bot_name)
- self.bot_cfg = self.spec['builder_cfg']
- self.out_dir = os.path.join(os.pardir, 'out')
- self.configuration = self.spec['configuration']
- self.default_env = {
- 'CHROME_HEADLESS': '1',
- 'SKIA_OUT': self.out_dir,
- 'BUILDTYPE': self.configuration,
- 'PATH': os.environ['PATH'],
- }
- if 'Win' in self.bot_cfg['os']:
- self.default_env['SystemRoot'] = 'C:\\Windows'
- self.default_env['TEMP'] = os.path.join(
- self.home_dir, 'AppData', 'Local', 'Temp')
- self.default_env['TMP'] = self.default_env['TEMP']
- self.default_env.update(self.spec['env'])
- self.build_targets = [str(t) for t in self.spec['build_targets']]
- self.is_trybot = self.bot_cfg['is_trybot']
- self.upload_dm_results = self.spec['upload_dm_results']
- self.upload_perf_results = self.spec['upload_perf_results']
- self.perf_data_dir = os.path.join(self.swarm_out_dir, 'perfdata',
- self.name, 'data')
- self.resource_dir = os.path.join(self.skia_dir, 'resources')
- self.images_dir = os.path.join(self.build_dir, 'images')
- self.local_skp_dir = os.path.join(self.build_dir, 'playback', 'skps')
- self.dm_flags = self.spec['dm_flags']
- self.nanobench_flags = self.spec['nanobench_flags']
- self._ccache = None
- self._checked_for_ccache = False
- self._already_ran = {}
- self.tmp_dir = os.path.join(self.build_dir, 'tmp')
- self.flavor = self.get_flavor(self.bot_cfg)
-
- # These get filled in during subsequent steps.
- self.device_dirs = None
- self.build_number = None
- self.got_revision = None
- self.master_name = None
- self.slave_name = None
-
- @property
- def ccache(self):
- if not self._checked_for_ccache:
- self._checked_for_ccache = True
- if sys.platform != 'win32':
- try:
- result = subprocess.check_output(['which', 'ccache'])
- self._ccache = result.rstrip()
- except subprocess.CalledProcessError:
- pass
-
- return self._ccache
-
- def get_bot_spec(self, bot_name):
- """Retrieve the bot spec for this bot."""
- sys.path.append(self.skia_dir)
- from tools import buildbot_spec
- return buildbot_spec.get_builder_spec(bot_name)
-
- def get_flavor(self, bot_cfg):
- """Return a flavor utils object specific to the given bot."""
- if is_android(bot_cfg):
- return android_flavor.AndroidFlavorUtils(self)
- elif is_chromeos(bot_cfg):
- return chromeos_flavor.ChromeOSFlavorUtils(self)
- elif is_cmake(bot_cfg):
- return cmake_flavor.CMakeFlavorUtils(self)
- elif is_ios(bot_cfg):
- return ios_flavor.iOSFlavorUtils(self)
- elif is_valgrind(bot_cfg):
- return valgrind_flavor.ValgrindFlavorUtils(self)
- elif is_xsan(bot_cfg):
- return xsan_flavor.XSanFlavorUtils(self)
- elif bot_cfg.get('configuration') == CONFIG_COVERAGE:
- return coverage_flavor.CoverageFlavorUtils(self)
- else:
- return default_flavor.DefaultFlavorUtils(self)
-
- def run(self, cmd, env=None, cwd=None):
- _env = {}
- _env.update(self.default_env)
- _env.update(env or {})
- cwd = cwd or self.skia_dir
- print '============'
- print 'CMD: %s' % cmd
- print 'CWD: %s' % cwd
- print 'ENV: %s' % _env
- print '============'
- subprocess.check_call(cmd, env=_env, cwd=cwd)
-
- def compile_steps(self):
- for t in self.build_targets:
- self.flavor.compile(t)
- dst = os.path.join(self.swarm_out_dir, 'out', self.configuration)
- os.makedirs(dst)
- for pattern in BUILD_PRODUCTS_WHITELIST:
- path = os.path.join(self.out_dir, self.configuration, pattern)
- for f in glob.glob(path):
- print 'Copying build product %s' % f
- shutil.copy(f, dst)
- self.cleanup()
-
- def _run_once(self, fn, *args, **kwargs):
- if not fn.__name__ in self._already_ran:
- self._already_ran[fn.__name__] = True
- fn(*args, **kwargs)
-
- def install(self):
- """Copy the required executables and files to the device."""
- self.device_dirs = self.flavor.get_device_dirs()
-
- # Run any device-specific installation.
- self.flavor.install()
-
- # TODO(borenet): Only copy files which have changed.
- # Resources
- self.flavor.copy_directory_contents_to_device(self.resource_dir,
- self.device_dirs.resource_dir)
-
- def _key_params(self):
- """Build a unique key from the builder name (as a list).
-
- E.g. arch x86 gpu GeForce320M mode MacMini4.1 os Mac10.6
- """
- # Don't bother to include role, which is always Test.
- # TryBots are uploaded elsewhere so they can use the same key.
- blacklist = ['role', 'is_trybot']
-
- flat = []
- for k in sorted(self.bot_cfg.keys()):
- if k not in blacklist:
- flat.append(k)
- flat.append(self.bot_cfg[k])
- return flat
-
- def test_steps(self, got_revision, master_name, slave_name, build_number,
- issue=None, patchset=None):
- """Run the DM test."""
- self.build_number = build_number
- self.got_revision = got_revision
- self.master_name = master_name
- self.slave_name = slave_name
- self._run_once(self.install)
-
- use_hash_file = False
- if self.upload_dm_results:
- # This must run before we write anything into self.device_dirs.dm_dir
- # or we may end up deleting our output on machines where they're the same.
- host_dm_dir = os.path.join(self.swarm_out_dir, 'dm')
- print 'host dm dir: %s' % host_dm_dir
- self.flavor.create_clean_host_dir(host_dm_dir)
- if str(host_dm_dir) != str(self.device_dirs.dm_dir):
- self.flavor.create_clean_device_dir(self.device_dirs.dm_dir)
-
- # Obtain the list of already-generated hashes.
- if not os.path.isdir(self.tmp_dir):
- os.makedirs(self.tmp_dir)
- hash_filename = 'uninteresting_hashes.txt'
- host_hashes_file = os.path.join(self.tmp_dir, hash_filename)
- hashes_file = self.flavor.device_path_join(
- self.device_dirs.tmp_dir, hash_filename)
-
- try:
- get_uninteresting_hashes(host_hashes_file)
- except Exception:
- pass
-
- if os.path.exists(host_hashes_file):
- self.flavor.copy_file_to_device(host_hashes_file, hashes_file)
- use_hash_file = True
-
- # Run DM.
- properties = [
- 'gitHash', self.got_revision,
- 'master', self.master_name,
- 'builder', self.name,
- 'build_number', self.build_number,
- ]
- if self.is_trybot:
- if not issue:
- raise Exception('issue is required for trybots.')
- if not patchset:
- raise Exception('patchset is required for trybots.')
- properties.extend([
- 'issue', issue,
- 'patchset', patchset,
- ])
-
- args = [
- 'dm',
- '--undefok', # This helps branches that may not know new flags.
- '--resourcePath', self.device_dirs.resource_dir,
- '--skps', self.device_dirs.skp_dir,
- '--images', self.flavor.device_path_join(
- self.device_dirs.images_dir, 'dm'),
- '--nameByHash',
- '--properties'
- ] + properties
-
- args.append('--key')
- args.extend(self._key_params())
- if use_hash_file:
- args.extend(['--uninterestingHashesFile', hashes_file])
- if self.upload_dm_results:
- args.extend(['--writePath', self.device_dirs.dm_dir])
-
- skip_flag = None
- if self.bot_cfg.get('cpu_or_gpu') == 'CPU':
- skip_flag = '--nogpu'
- elif self.bot_cfg.get('cpu_or_gpu') == 'GPU':
- skip_flag = '--nocpu'
- if skip_flag:
- args.append(skip_flag)
- args.extend(self.dm_flags)
-
- self.flavor.run(args, env=self.default_env)
-
- if self.upload_dm_results:
- # Copy images and JSON to host machine if needed.
- self.flavor.copy_directory_contents_to_host(self.device_dirs.dm_dir,
- host_dm_dir)
-
- # See skia:2789.
- if ('Valgrind' in self.name and
- self.bot_cfg.get('cpu_or_gpu') == 'GPU'):
- abandonGpuContext = list(args)
- abandonGpuContext.append('--abandonGpuContext')
- self.flavor.run(abandonGpuContext)
- preAbandonGpuContext = list(args)
- preAbandonGpuContext.append('--preAbandonGpuContext')
- self.flavor.run(preAbandonGpuContext)
-
- self.cleanup()
-
- def perf_steps(self, got_revision, master_name, slave_name, build_number,
- issue=None, patchset=None):
- """Run Skia benchmarks."""
- self.build_number = build_number
- self.got_revision = got_revision
- self.master_name = master_name
- self.slave_name = slave_name
- self._run_once(self.install)
- if self.upload_perf_results:
- self.flavor.create_clean_device_dir(self.device_dirs.perf_data_dir)
-
- # Run nanobench.
- properties = [
- '--properties',
- 'gitHash', self.got_revision,
- 'build_number', self.build_number,
- ]
- if self.is_trybot:
- if not issue:
- raise Exception('issue is required for trybots.')
- if not patchset:
- raise Exception('patchset is required for trybots.')
- properties.extend([
- 'issue', issue,
- 'patchset', patchset,
- ])
-
- target = 'nanobench'
- if 'VisualBench' in self.name:
- target = 'visualbench'
- args = [
- target,
- '--undefok', # This helps branches that may not know new flags.
- '-i', self.device_dirs.resource_dir,
- '--skps', self.device_dirs.skp_dir,
- '--images', self.flavor.device_path_join(
- self.device_dirs.images_dir, 'dm'), # Using DM images for now.
- ]
-
- skip_flag = None
- if self.bot_cfg.get('cpu_or_gpu') == 'CPU':
- skip_flag = '--nogpu'
- elif self.bot_cfg.get('cpu_or_gpu') == 'GPU':
- skip_flag = '--nocpu'
- if skip_flag:
- args.append(skip_flag)
- args.extend(self.nanobench_flags)
-
- if self.upload_perf_results:
- json_path = self.flavor.device_path_join(
- self.device_dirs.perf_data_dir,
- 'nanobench_%s.json' % self.got_revision)
- args.extend(['--outResultsFile', json_path])
- args.extend(properties)
-
- keys_blacklist = ['configuration', 'role', 'is_trybot']
- args.append('--key')
- for k in sorted(self.bot_cfg.keys()):
- if not k in keys_blacklist:
- args.extend([k, self.bot_cfg[k]])
-
- self.flavor.run(args, env=self.default_env)
-
- # See skia:2789.
- if ('Valgrind' in self.name and
- self.bot_cfg.get('cpu_or_gpu') == 'GPU'):
- abandonGpuContext = list(args)
- abandonGpuContext.extend(['--abandonGpuContext', '--nocpu'])
- self.flavor.run(abandonGpuContext, env=self.default_env)
-
- # Copy results to host.
- if self.upload_perf_results:
- if not os.path.exists(self.perf_data_dir):
- os.makedirs(self.perf_data_dir)
- self.flavor.copy_directory_contents_to_host(
- self.device_dirs.perf_data_dir, self.perf_data_dir)
-
- self.cleanup()
-
- def cleanup(self):
- if sys.platform == 'win32':
- # Kill mspdbsrv.exe, which tends to hang around after the build finishes.
- for p in psutil.process_iter():
- try:
- if p.name == 'mspdbsrv.exe':
- p.kill()
- except psutil._error.AccessDenied:
- pass
- self.flavor.cleanup_steps()
« no previous file with comments | « infra/bots/add_isolated_input.py ('k') | infra/bots/compile_skia.isolate » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698