Chromium Code Reviews| Index: infra/bots/recipe_modules/run/api.py |
| diff --git a/infra/bots/recipe_modules/run/api.py b/infra/bots/recipe_modules/run/api.py |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..752ee3858ac7ac4a99918e81d92cc1ceb4b3f67c |
| --- /dev/null |
| +++ b/infra/bots/recipe_modules/run/api.py |
| @@ -0,0 +1,150 @@ |
| +# 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. |
| + |
| + |
| +# pylint: disable=W0201 |
| + |
| + |
| +from recipe_engine import recipe_api |
| + |
| + |
| +BUILD_PRODUCTS_ISOLATE_WHITELIST = [ |
| + 'dm', |
| + 'dm.exe', |
| + 'nanobench', |
| + 'nanobench.exe', |
| + '*.so', |
| + '*.dll', |
| + '*.dylib', |
| + 'skia_launcher', |
| + 'lib/*.so', |
| + 'iOSShell.app', |
| + 'iOSShell.ipa', |
| + 'visualbench', |
| + 'visualbench.exe', |
| + 'vulkan-1.dll', |
| +] |
| + |
| + |
| +class SkiaStepApi(recipe_api.RecipeApi): |
| + |
| + def setup(self): |
|
rmistry
2016/08/03 14:15:16
Looks like a constructor should work here.
borenet
2016/08/03 14:30:00
Done.
|
| + """Initialize the recipe module.""" |
| + self._already_ran = {} |
| + self._ccache = None |
| + self._checked_for_ccache = False |
| + self._failed = [] |
| + |
| + def check_failure(self): |
| + """Raise an exception if any step failed.""" |
| + if self._failed: |
| + raise self.m.step.StepFailure('Failed build steps: %s' % |
| + ', '.join([f.name for f in self._failed])) |
| + |
| + def run_once(self, fn, *args, **kwargs): |
| + if not fn.__name__ in self._already_ran: |
| + self._already_ran[fn.__name__] = fn(*args, **kwargs) |
| + return self._already_ran[fn.__name__] |
| + |
| + def readfile(self, filename, *args, **kwargs): |
| + """Convenience function for reading files.""" |
| + name = kwargs.pop('name') or 'read %s' % self.m.path.basename(filename) |
| + return self.m.file.read(name, filename, infra_step=True, *args, **kwargs) |
| + |
| + def writefile(self, filename, contents): |
| + """Convenience function for writing files.""" |
| + return self.m.file.write('write %s' % self.m.path.basename(filename), |
| + filename, contents, infra_step=True) |
| + |
| + def rmtree(self, path): |
| + """Wrapper around api.file.rmtree with environment fix.""" |
| + env = {} |
| + env['PYTHONPATH'] = str(self.m.path['checkout'].join( |
| + 'infra', 'bots', '.recipe_deps', 'build', 'scripts')) |
| + self.m.file.rmtree(self.m.path.basename(path), |
| + path, |
| + env=env, |
| + infra_step=True) |
| + |
| + def __call__(self, steptype, name, abort_on_failure=True, |
| + fail_build_on_failure=True, env=None, **kwargs): |
| + """Run a step. If it fails, keep going but mark the build status failed.""" |
| + env = dict(env or {}) |
| + env.update(self.m.vars.default_env) |
| + try: |
| + return steptype(name=name, env=env, **kwargs) |
| + except self.m.step.StepFailure as e: |
| + if abort_on_failure: |
| + raise # pragma: no cover |
| + if fail_build_on_failure: |
| + self._failed.append(e) |
| + |
| + def json_from_file(self, filename, cwd, builder_name, test_data): |
| + """Execute the given script to obtain JSON data.""" |
| + return self.m.python( |
| + 'exec %s' % self.m.path.basename(filename), |
| + filename, |
| + args=[self.m.json.output(), builder_name], |
| + step_test_data=lambda: self.m.json.test_api.output(test_data), |
| + cwd=cwd, |
| + infra_step=True).json.output |
| + |
| + def copy_build_products(self, src, dst): |
| + """Copy whitelisted build products from src to dst.""" |
| + self.m.python.inline( |
| + name='copy build products', |
| + program='''import errno |
| +import glob |
| +import os |
| +import shutil |
| +import sys |
| + |
| +src = sys.argv[1] |
| +dst = sys.argv[2] |
| +build_products_whitelist = %s |
| + |
| +try: |
| + os.makedirs(dst) |
| +except OSError as e: |
| + if e.errno != errno.EEXIST: |
| + raise |
| + |
| +for pattern in build_products_whitelist: |
| + path = os.path.join(src, pattern) |
| + for f in glob.glob(path): |
| + dst_path = os.path.join(dst, os.path.relpath(f, src)) |
| + if not os.path.isdir(os.path.dirname(dst_path)): |
| + os.makedirs(os.path.dirname(dst_path)) |
| + print 'Copying build product %%s to %%s' %% (f, dst_path) |
| + shutil.move(f, dst_path) |
| +''' % str(BUILD_PRODUCTS_ISOLATE_WHITELIST), |
| + args=[src, dst], |
| + infra_step=True) |
| + |
| + def ccache(self): |
| + if not self._checked_for_ccache: |
| + self._checked_for_ccache = True |
| + if not self.m.platform.is_win: |
| + result = self( |
| + self.m.python.inline, |
| + name='has ccache?', |
| + program='''import json |
| +import subprocess |
| +import sys |
| + |
| +ccache = None |
| +try: |
| + ccache = subprocess.check_output(['which', 'ccache']).rstrip() |
| +except: |
| + pass |
| +print json.dumps({'ccache': ccache}) |
| +''', |
| + stdout=self.m.json.output(), |
| + infra_step=True, |
| + abort_on_failure=False, |
| + fail_build_on_failure=False) |
| + if result and result.stdout and result.stdout.get('ccache'): |
| + self._ccache = result.stdout['ccache'] |
| + |
| + return self._ccache |