Bug 1316077 part 1: Support buildbot-bridge for talos tests. r=dustin
While we don't have physical machines running taskcluster-worker, we
want to schedule talos tests on Taskcluster and run them on buildbot.
buildbot-bridge acts as a worker that runs its tasks in buildbot
machines. Any talos task is redirected to buildbot-bridge.
MozReview-Commit-ID: Im9IhhT0Mr1
--- a/taskcluster/taskgraph/transforms/task.py
+++ b/taskcluster/taskgraph/transforms/task.py
@@ -466,16 +466,27 @@ def build_macosx_engine_payload(config,
task_def['payload'] = {
'link': worker['link'],
'command': worker['command'],
'env': worker['env'],
'artifacts': artifacts,
}
+
+@payload_builder('buildbot-bridge')
+def build_buildbot_bridge_payload(config, task, task_def):
+ worker = task['worker']
+ task_def['payload'] = {
+ 'buildername': worker['buildername'],
+ 'sourcestamp': worker['sourcestamp'],
+ 'properties': worker['properties'],
+ }
+
+
transforms = TransformSequence()
@transforms.add
def validate(config, tasks):
for task in tasks:
yield validate_schema(
task_description_schema, task,
--- a/taskcluster/taskgraph/transforms/tests/all_kinds.py
+++ b/taskcluster/taskgraph/transforms/tests/all_kinds.py
@@ -19,17 +19,19 @@ import copy
transforms = TransformSequence()
@transforms.add
def set_worker_implementation(config, tests):
"""Set the worker implementation based on the test platform."""
for test in tests:
- if test['test-platform'].startswith('win'):
+ if test.get('suite', '') == 'talos':
+ test['worker-implementation'] = 'buildbot-bridge'
+ elif test['test-platform'].startswith('win'):
test['worker-implementation'] = 'generic-worker'
elif test['test-platform'].startswith('macosx'):
test['worker-implementation'] = 'macosx-engine'
else:
test['worker-implementation'] = 'docker-worker'
yield test
--- a/taskcluster/taskgraph/transforms/tests/make_task_description.py
+++ b/taskcluster/taskgraph/transforms/tests/make_task_description.py
@@ -43,16 +43,28 @@ WORKER_TYPE = {
ARTIFACTS = [
# (artifact name prefix, in-image path)
("public/logs/", "build/upload/logs/"),
("public/test", "artifacts/"),
("public/test_info/", "build/blobber_upload_dir/"),
]
+BUILDER_NAME_PREFIX = {
+ 'linux64-pgo': 'Ubuntu VM 12.04 x64',
+ 'linux64': 'Ubuntu VM 12.04 x64',
+ 'linux64-asan': 'Ubuntu ASAN VM 12.04 x64',
+ 'linux64-ccov': 'Ubuntu Code Coverage VM 12.04 x64',
+ 'linux64-jsdcov': 'Ubuntu Code Coverage VM 12.04 x64',
+ 'macosx64': 'Rev7 MacOSX Yosemite 10.10.5',
+ 'android-4.3-arm7-api-15': 'Android 4.3 armv7 API 15+',
+ 'android-4.2-x86': 'Android 4.2 x86 Emulator',
+ 'android-4.3-arm7-api-15-gradle': 'Android 4.3 armv7 API 15+',
+}
+
logger = logging.getLogger(__name__)
transforms = TransformSequence()
@transforms.add
def make_task_description(config, tests):
"""Convert *test* descriptions to *task* descriptions (input to
@@ -60,17 +72,22 @@ def make_task_description(config, tests)
for test in tests:
label = '{}-{}-{}'.format(config.kind, test['test-platform'], test['test-name'])
if test['chunks'] > 1:
label += '-{}'.format(test['this-chunk'])
build_label = test['build-label']
- unittest_try_name = test.get('unittest-try-name', test['test-name'])
+ if 'talos-try-name' in test:
+ try_name = test['talos-try-name']
+ attr_try_name = 'talos_try_name'
+ else:
+ try_name = test.get('unittest-try-name', test['test-name'])
+ attr_try_name = 'unittest_try_name'
attr_build_platform, attr_build_type = test['build-platform'].split('/', 1)
suite = test['suite']
if '/' in suite:
suite, flavor = suite.split('/', 1)
else:
flavor = suite
@@ -79,17 +96,17 @@ def make_task_description(config, tests)
attributes.update({
'build_platform': attr_build_platform,
'build_type': attr_build_type,
# only keep the first portion of the test platform
'test_platform': test['test-platform'].split('/')[0],
'test_chunk': str(test['this-chunk']),
'unittest_suite': suite,
'unittest_flavor': flavor,
- 'unittest_try_name': unittest_try_name,
+ attr_try_name: try_name,
})
taskdesc = {}
taskdesc['label'] = label
taskdesc['description'] = test['description']
taskdesc['attributes'] = attributes
taskdesc['dependencies'] = {'build': build_label}
taskdesc['deadline-after'] = '1 day'
@@ -438,8 +455,58 @@ def macosx_engine_setup(config, test, ta
for i, c in enumerate(command):
if isinstance(c, basestring) and c.startswith('--test-suite'):
command[i] += suffix
if 'download-symbols' in mozharness:
download_symbols = mozharness['download-symbols']
download_symbols = {True: 'true', False: 'false'}.get(download_symbols, download_symbols)
command.append('--download-symbols=' + download_symbols)
+
+
+@worker_setup_function("buildbot-bridge")
+def buildbot_bridge_setup(config, test, taskdesc):
+ branch = config.params['project']
+ platform, build_type = test['build-platform'].split('/')
+ test_name = test.get('talos-try-name', test['test-name'])
+ mozharness = test['mozharness']
+
+ if test['e10s'] and not test_name.endswith('-e10s'):
+ test_name += '-e10s'
+
+ if mozharness.get('chunked', False):
+ this_chunk = test.get('this-chunk')
+ test_name = '{}-{}'.format(test_name, this_chunk)
+
+ worker = taskdesc['worker'] = {}
+ worker['implementation'] = test['worker-implementation']
+
+ taskdesc['worker-type'] = 'buildbot-bridge/buildbot-bridge'
+
+ if test.get('suite', '') == 'talos':
+ buildername = '{} {} talos {}'.format(
+ BUILDER_NAME_PREFIX[platform],
+ branch,
+ test_name
+ )
+ if buildername.startswith('Ubuntu'):
+ buildername = buildername.replace('VM', 'HW')
+ else:
+ buildername = '{} {} {} test {}'.format(
+ BUILDER_NAME_PREFIX[platform],
+ branch,
+ build_type,
+ test_name
+ )
+
+ worker.update({
+ 'buildername': buildername,
+ 'sourcestamp': {
+ 'branch': branch,
+ 'repository': config.params['head_repository'],
+ 'revision': config.params['head_rev'],
+ },
+ 'properties': {
+ 'product': test.get('product', 'firefox'),
+ 'who': config.params['owner'],
+ 'installer_path': mozharness['build-artifact-name'],
+ }
+ })
--- a/taskcluster/taskgraph/transforms/tests/test_description.py
+++ b/taskcluster/taskgraph/transforms/tests/test_description.py
@@ -36,16 +36,19 @@ test_description_schema = Schema({
basestring,
{'by-test-platform': {basestring: basestring}},
),
# the name by which this test suite is addressed in try syntax; defaults to
# the test-name
Optional('unittest-try-name'): basestring,
+ # the name by which this talos test is addressed in try syntax
+ Optional('talos-try-name'): basestring,
+
# the symbol, or group(symbol), under which this task should appear in
# treeherder.
'treeherder-symbol': basestring,
# the value to place in task.extra.treeherder.machine.platform; ideally
# this is the same as build-platform, and that is the default, but in
# practice it's not always a match.
Optional('treeherder-machine-platform'): basestring,
@@ -220,16 +223,19 @@ test_description_schema = Schema({
'build-label': basestring,
# the platform on which the tests will run
'test-platform': basestring,
# the name of the test (the key in tests.yml)
'test-name': basestring,
+ # the product name, defaults to firefox
+ Optional('product'): basestring,
+
}, required=True)
# TODO: can we have validate and validate_full for before and after?
def validate(config, tests):
for test in tests:
yield validate_schema(test_description_schema, test,
"In test {!r}:".format(test['test-name']))
--- a/taskcluster/taskgraph/try_option_syntax.py
+++ b/taskcluster/taskgraph/try_option_syntax.py
@@ -518,17 +518,18 @@ class TryOptionSyntax(object):
return False
if 'platforms' in test and attr('test_platform') not in test['platforms']:
return False
if 'only_chunks' in test and attr('test_chunk') not in test['only_chunks']:
return False
return True
if attr('kind') in ('desktop-test', 'android-test'):
- return match_test(self.unittests, 'unittest_try_name')
+ return match_test(self.unittests, 'unittest_try_name') \
+ or match_test(self.talos, 'talos_try_name')
elif attr('kind') in JOB_KINDS:
# This will add 'job' tasks to the target set even if no try syntax was specified.
if not self.jobs:
return True
if attr('build_platform') in self.jobs:
return True
elif attr('kind') in BUILD_KINDS:
if attr('build_type') not in self.build_types:
@@ -548,13 +549,14 @@ class TryOptionSyntax(object):
if list is None:
return '<all>'
return ', '.join(str(e) for e in list)
return "\n".join([
"build_types: " + ", ".join(self.build_types),
"platforms: " + none_for_all(self.platforms),
"unittests: " + none_for_all(self.unittests),
+ "talos: " + none_for_all(self.talos),
"jobs: " + none_for_all(self.jobs),
"trigger_tests: " + str(self.trigger_tests),
"interactive: " + str(self.interactive),
"notifications: " + self.notifications,
])