| Index: infra/bots/gen_buildbot_specs.py
|
| diff --git a/infra/bots/gen_buildbot_specs.py b/infra/bots/gen_buildbot_specs.py
|
| new file mode 100755
|
| index 0000000000000000000000000000000000000000..d960ab217b712e7635e7db1b4af0688380a2f3b1
|
| --- /dev/null
|
| +++ b/infra/bots/gen_buildbot_specs.py
|
| @@ -0,0 +1,172 @@
|
| +#!/usr/bin/env python
|
| +#
|
| +# Copyright 2015 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.
|
| +
|
| +
|
| +'''Generate buildbot specs for all buildbots.'''
|
| +
|
| +
|
| +import datetime
|
| +import imp
|
| +import json
|
| +import os
|
| +import re
|
| +import subprocess
|
| +import sys
|
| +import tempfile
|
| +
|
| +
|
| +SKIA_DIR = os.path.abspath(os.path.join(
|
| + os.path.dirname(os.path.realpath(__file__)),
|
| + os.pardir, os.pardir))
|
| +
|
| +BUILDBOT_SPEC_FILE = os.path.join(SKIA_DIR, 'tools', 'buildbot_spec.py')
|
| +
|
| +SKIA_RECIPES = [
|
| + 'swarm_compile.py',
|
| + 'swarm_housekeeper.py',
|
| + 'swarm_perf.py',
|
| + 'swarm_RecreateSKPs.py',
|
| + 'swarm_test.py',
|
| + 'swarm_trigger.py'
|
| +]
|
| +
|
| +
|
| +def prettier_print(obj, indent, stream=sys.stdout, max_line_length=80):
|
| + """Pretty-print the object, in a nicer format than pprint."""
|
| +
|
| + def _breakline(line):
|
| + """Break the line to fit under N characters."""
|
| + # If we're under the limit, just return.
|
| + if len(line) <= max_line_length:
|
| + return [line]
|
| +
|
| + # Dict entries.
|
| + m = re.match(r'^(\s+)(.+): (.+)$', line)
|
| + if m:
|
| + return (_breakline(m.groups()[0] + m.groups()[1] + ':') +
|
| + _breakline(m.groups()[0] + ' ' + m.groups()[2]))
|
| +
|
| + # List entries and dict keys.
|
| + m = re.match(r"^(\s+)'(.+)'([:,])$", line)
|
| + if m:
|
| + prefix = m.groups()[0]
|
| + content = m.groups()[1]
|
| + max_len = max_line_length - len(prefix) - len("(''):")
|
| + parts = []
|
| + while len(content) > max_len:
|
| + parts.append(content[:max_len])
|
| + content = content[max_len:]
|
| + parts.append(content)
|
| + lines = _breakline(prefix + "('" + parts[0] + "'")
|
| + for p in parts[1:-1]:
|
| + lines.extend(_breakline(prefix + " '" + p + "'"))
|
| + lines.extend(_breakline(prefix + " '" + parts[-1] + "')" + m.groups()[2]))
|
| + return lines
|
| +
|
| + class LineBreakingStream(object):
|
| + """Stream wrapper which writes line-by-line, breaking them as needed."""
|
| + def __init__(self, backing_stream):
|
| + self._backing_stream = backing_stream
|
| + self._current_line = ''
|
| +
|
| + def _writeline(self, line):
|
| + for l in _breakline(line):
|
| + self._backing_stream.write(l + '\n')
|
| +
|
| + def write(self, s):
|
| + self._current_line += s
|
| + split = self._current_line.split('\n')
|
| + for w in split[:-1]:
|
| + self._writeline(w)
|
| + self._current_line = split[len(split)-1]
|
| +
|
| + def flush(self):
|
| + self._writeline(self._current_line)
|
| +
|
| + def _pprint(obj, indent, stream):
|
| + indent_str = ' ' * indent
|
| + if isinstance(obj, dict):
|
| + stream.write('{\n')
|
| + for k in sorted(obj.iterkeys()):
|
| + stream.write(indent_str + '\'%s\': ' % k)
|
| + _pprint(obj[k], indent + 2, stream=stream)
|
| + stream.write(',\n')
|
| + stream.write(' ' * (indent-2) + '}')
|
| + elif isinstance(obj, list):
|
| + stream.write('[\n')
|
| + for v in obj:
|
| + stream.write(indent_str)
|
| + _pprint(v, indent + 2, stream=stream)
|
| + stream.write(',\n')
|
| + stream.write(' ' * (indent-2) + ']')
|
| + elif isinstance(obj, basestring):
|
| + stream.write('\'%s\'' % obj)
|
| + elif isinstance(obj, bool):
|
| + if obj:
|
| + stream.write('True')
|
| + else:
|
| + stream.write('False')
|
| + else:
|
| + stream.write(obj)
|
| +
|
| + s = LineBreakingStream(stream)
|
| + _pprint(obj, indent, stream=s)
|
| + s.flush()
|
| +
|
| +
|
| +def get_bots():
|
| + """Find all of the bots referenced in Skia recipes."""
|
| + recipes = os.path.join(SKIA_DIR, 'infra', 'bots', 'recipes')
|
| + bots = []
|
| + for skia_recipe in SKIA_RECIPES:
|
| + skia_recipe = os.path.join(recipes, skia_recipe)
|
| + skia = imp.load_source('skia', skia_recipe)
|
| + for _, slaves in skia.TEST_BUILDERS.iteritems():
|
| + for _, builders in slaves.iteritems():
|
| + bots.extend(builders)
|
| + bots.sort()
|
| + return bots
|
| +
|
| +
|
| +def main():
|
| + """Generate a spec for each of the above bots. Dump them all to a file."""
|
| + # Get the list of bots.
|
| + bots = get_bots()
|
| +
|
| + # Create the fake specs.
|
| + specs = {}
|
| + tmp_spec_file = tempfile.NamedTemporaryFile(delete=False)
|
| + tmp_spec_file.close()
|
| + try:
|
| + for bot in bots:
|
| + subprocess.check_call(['python', BUILDBOT_SPEC_FILE,
|
| + tmp_spec_file.name, bot])
|
| + with open(tmp_spec_file.name) as f:
|
| + spec = json.load(f)
|
| + spec['dm_flags'] = ['--dummy-flags']
|
| + spec['nanobench_flags'] = ['--dummy-flags']
|
| + specs[bot] = spec
|
| + finally:
|
| + os.remove(tmp_spec_file.name)
|
| +
|
| + out = os.path.join(
|
| + SKIA_DIR, 'infra', 'bots', 'recipe_modules', 'skia', 'fake_specs.py')
|
| +
|
| + with open(out, 'w') as f:
|
| + f.write('''# 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.
|
| +
|
| +# This file is generated by the %s script.
|
| +
|
| +FAKE_SPECS = ''' % sys.argv[0])
|
| + prettier_print(specs, indent=2, stream=f)
|
| +
|
| + print 'Wrote output to %s' % out
|
| +
|
| +
|
| +if __name__ == '__main__':
|
| + main()
|
|
|