fune/taskcluster/taskgraph/transforms/docker_image.py
Dustin J. Mitchell f8a58269bd Bug 1359976: base worker payload generation on worker-type; r=wcosta r=aki
To date we have variously specified both worker-type and worker-implementation,
often manually coordinated. We also embedded a few awkward assumptions such as
that the native engine only runs on OS X.

But a worker type has one and only one implementation, and that implementation
is stable over time (as changing it would require simultaneous landings on all
trees).

Instead, this change makes worker-type the primary configuration, and derives
both a worker implementation (defining the payload format) and worker OS
(determining what to include in the payload) from that value. The derivation
occurs when deciding how to implement a particular job, where the run_using
functions are distinguished by worker implementation.

The two-part logic to determine how and where to run a test task based on its
platform is combined into a single transform, `set_worker_type`.

This contains some other related changes:
 - MOZ_AUTOMATION is set in specific jobs, rather than everywhere docker-worker
   is used
 - the URL to test packages is factored out into a shared function
 - docker-worker test defaults are applied in `mozharness_test.py`
 - the WORKER_TYPE array in `task.py`, formerly mixing two types of keys, is
   split
 - the 'invalid' workerType is assigned an 'invalid' implementation
 - all tasks that do not use job descriptions but use docker-worker, etc. have
   `worker.os` added

Tested to not produce a substantially different taskgraph for a regular push, a
try push, or a nightly cron.

MozReview-Commit-ID: LDHrmrpBo7I

--HG--
extra : rebase_source : 4cdfe6b8d9874b0c156671515b213d820b48482f
2017-05-08 22:53:50 +00:00

126 lines
5.1 KiB
Python

# 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/.
"""
Transform the upload-symbols task description template,
taskcluster/ci/upload-symbols/job-template.yml
into an actual task description.
"""
from __future__ import absolute_import, print_function, unicode_literals
import os
from taskgraph.transforms.base import TransformSequence
from .. import GECKO
from taskgraph.util.docker import (
docker_image,
generate_context_hash,
INDEX_PREFIX,
)
transforms = TransformSequence()
ROUTE_TEMPLATES = [
'index.{index_prefix}.level-{level}.{image_name}.latest',
'index.{index_prefix}.level-{level}.{image_name}.pushdate.{year}.{month}-{day}-{pushtime}',
'index.{index_prefix}.level-{level}.{image_name}.hash.{context_hash}',
]
@transforms.add
def fill_template(config, tasks):
for task in tasks:
image_name = task.pop('name')
job_symbol = task.pop('symbol')
context_path = os.path.join('taskcluster', 'docker', image_name)
context_hash = generate_context_hash(GECKO, context_path, image_name)
description = 'Build the docker image {} for use by dependent tasks'.format(
image_name)
routes = []
for tpl in ROUTE_TEMPLATES:
routes.append(tpl.format(
index_prefix=INDEX_PREFIX,
level=config.params['level'],
image_name=image_name,
project=config.params['project'],
head_rev=config.params['head_rev'],
pushlog_id=config.params.get('pushlog_id', 0),
pushtime=config.params['moz_build_date'][8:],
year=config.params['moz_build_date'][0:4],
month=config.params['moz_build_date'][4:6],
day=config.params['moz_build_date'][6:8],
context_hash=context_hash,
))
# As an optimization, if the context hash exists for a high level, that image
# task ID will be used. The reasoning behind this is that eventually everything ends
# up on level 3 at some point if most tasks use this as a common image
# for a given context hash, a worker within Taskcluster does not need to contain
# the same image per branch.
optimizations = [['index-search', '{}.level-{}.{}.hash.{}'.format(
INDEX_PREFIX, level, image_name, context_hash)]
for level in reversed(range(int(config.params['level']), 4))]
# Adjust the zstandard compression level based on the execution level.
# We use faster compression for level 1 because we care more about
# end-to-end times. We use slower/better compression for other levels
# because images are read more often and it is worth the trade-off to
# burn more CPU once to reduce image size.
zstd_level = '3' if int(config.params['level']) == 1 else '10'
# include some information that is useful in reconstructing this task
# from JSON
taskdesc = {
'label': 'build-docker-image-' + image_name,
'description': description,
'attributes': {'image_name': image_name},
'expires-after': '1 year',
'routes': routes,
'optimizations': optimizations,
'scopes': ['secrets:get:project/taskcluster/gecko/hgfingerprint'],
'treeherder': {
'symbol': job_symbol,
'platform': 'taskcluster-images/opt',
'kind': 'other',
'tier': 1,
},
'run-on-projects': [],
'worker-type': 'aws-provisioner-v1/gecko-images',
# can't use {in-tree: ..} here, otherwise we might try to build
# this image..
'worker': {
'implementation': 'docker-worker',
'os': 'linux',
'docker-image': docker_image('image_builder'),
'caches': [{
'type': 'persistent',
'name': 'level-{}-imagebuilder-v1'.format(config.params['level']),
'mount-point': '/home/worker/checkouts',
}],
'artifacts': [{
'type': 'file',
'path': '/home/worker/workspace/artifacts/image.tar.zst',
'name': 'public/image.tar.zst',
}],
'env': {
'HG_STORE_PATH': '/home/worker/checkouts/hg-store',
'HASH': context_hash,
'PROJECT': config.params['project'],
'IMAGE_NAME': image_name,
'DOCKER_IMAGE_ZSTD_LEVEL': zstd_level,
'GECKO_BASE_REPOSITORY': config.params['base_repository'],
'GECKO_HEAD_REPOSITORY': config.params['head_repository'],
'GECKO_HEAD_REV': config.params['head_rev'],
},
'chain-of-trust': True,
'docker-in-docker': True,
'taskcluster-proxy': True,
'max-run-time': 3600,
},
}
yield taskdesc