Bug 1427312 - Add mechanism to create tasks to compare Firefox builds. r=dustin

There are e.g. some build infrastructure changes that we want to have a
controlled impact on the Firefox builds we produce. We have, in multiple
occasions, gone through manual work to compare Firefox builds, most of
the time using the diffoscope tool (https://diffoscope.org/).

This change introduces a new task kind that takes two Firefox builds as
input, either by name (reference to a build from the current task graph)
or by index (reference to a build from a previous push), and compares
them.

In order to get a Firefox build by index, we rely on dummy tasks with
an optimization we expect to always hit, so we add the necessary bits
to ensure those dummy tasks can go through up to the optimization phase
and be optimized out there.
This commit is contained in:
Mike Hommey
2017-12-28 12:14:34 +09:00
parent fd9a1bdc44
commit ae3d424d62
11 changed files with 350 additions and 1 deletions

View File

@@ -0,0 +1,158 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
"""
This transform construct tasks to perform diffs between builds, as
defined in kind.yml
"""
from __future__ import absolute_import, print_function, unicode_literals
from taskgraph.transforms.base import TransformSequence
from taskgraph.util.schema import (
Schema,
validate_schema,
)
from taskgraph.util.taskcluster import get_artifact_url
from voluptuous import (
Any,
Optional,
Required,
)
transforms = TransformSequence()
index_or_string = Any(
basestring,
{Required('index-search'): basestring},
)
diff_description_schema = Schema({
# Name of the diff task.
Required('name'): basestring,
# Treeherder symbol.
Required('symbol'): basestring,
# relative path (from config.path) to the file the task was defined in.
Optional('job-from'): basestring,
# Original and new builds to compare.
Required('original'): index_or_string,
Required('new'): index_or_string,
# Arguments to pass to diffoscope, used for job-defaults in
# taskcluster/ci/diffoscope/kind.yml
Optional('args'): basestring,
# Extra arguments to pass to diffoscope, that can be set per job.
Optional('extra-args'): basestring,
})
@transforms.add
def validate(config, tasks):
for task in tasks:
yield validate_schema(
diff_description_schema, task,
"In diff task {!r}:".format(task.get('name', 'unknown')))
@transforms.add
def fill_template(config, tasks):
dummy_tasks = {}
for task in tasks:
name = task['name']
deps = {}
urls = {}
previous_artifact = None
for k in ('original', 'new'):
value = task[k]
if isinstance(value, basestring):
deps[k] = value
task_id = '<{}>'.format(k)
os_hint = value
else:
index = value['index-search']
if index not in dummy_tasks:
dummy_tasks[index] = {
'label': 'index-search-' + index,
'description': index,
'worker-type': 'invalid/always-optimized',
'run': {
'using': 'always-optimized',
},
'optimization': {
'index-search': [index],
}
}
yield dummy_tasks[index]
deps[index] = 'index-search-' + index
task_id = '<{}>'.format(index)
os_hint = index.split('.')[-1]
if 'linux' in os_hint:
artifact = 'target.tar.bz2'
elif 'macosx' in os_hint:
artifact = 'target.dmg'
elif 'android' in os_hint:
artifact = 'target.apk'
elif 'win' in os_hint:
artifact = 'target.zip'
else:
raise Exception(
'Cannot figure out the OS for {!r}'.format(value))
if previous_artifact is not None and previous_artifact != artifact:
raise Exception(
'Cannot compare builds from different OSes')
url = get_artifact_url(task_id, 'public/build/{}'.format(artifact))
urls[k] = {'task-reference': url}
previous_artifact = artifact
taskdesc = {
'label': 'diff-' + name,
'description': name,
'treeherder': {
'symbol': task['symbol'],
'platform': 'diff/opt',
'kind': 'other',
'tier': 2,
},
'worker-type': 'aws-provisioner-v1/gecko-{}-b-linux'.format(
config.params['level']),
'worker': {
'docker-image': {'in-tree': 'diffoscope'},
'artifacts': [{
'type': 'file',
'path': '/builds/worker/diff.html',
'name': 'public/diff.html',
}, {
'type': 'file',
'path': '/builds/worker/diff.txt',
'name': 'public/diff.txt',
}],
'env': {
'ORIG_URL': urls['original'],
'NEW_URL': urls['new'],
'DIFFOSCOPE_ARGS': ' '.join(
task[k] for k in ('args', 'extra-args') if k in task)
},
'max-run-time': 1800,
},
'run': {
'using': 'run-task',
'checkout': False,
'command': '/builds/worker/bin/get_and_diffoscope '
'"$ORIG_URL" "$NEW_URL"',
},
'dependencies': deps,
}
if artifact.endswith('.dmg'):
taskdesc['toolchains'] = [
'linux64-cctools-port',
'linux64-libdmg',
]
yield taskdesc