Bug 1374589 - Port windows tests which require signed builds to in-tree tasks r=Callek

MozReview-Commit-ID: JI0T2qW6P00

--HG--
extra : rebase_source : a537a28f7571bbbe84baef3413f8882867ee15c9
This commit is contained in:
Johan Lorenzo 2017-06-29 13:50:13 -07:00
Родитель 2f3c835cd3
Коммит fb9bfb407e
22 изменённых файлов: 218 добавлений и 115 удалений

Просмотреть файл

@ -2,7 +2,7 @@
# 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/.
loader: taskgraph.loader.single_dep:loader
loader: taskgraph.loader.build_signing:loader
transforms:
- taskgraph.transforms.build_signing:transforms
@ -12,8 +12,5 @@ transforms:
kind-dependencies:
- build
only-for-attributes:
- nightly
not-for-build-platforms:
- win64-nightly/opt

Просмотреть файл

@ -2,6 +2,7 @@ loader: taskgraph.loader.test:loader
kind-dependencies:
- build
- build-signing
transforms:
- taskgraph.transforms.tests:transforms

Просмотреть файл

@ -123,7 +123,7 @@ windows-vm-tests:
- mochitest-media
- web-platform-tests
- web-platform-tests-reftests
#- xpcshell
- xpcshell
windows-gpu-tests:
- reftest

Просмотреть файл

@ -1570,22 +1570,27 @@ xpcshell:
treeherder-symbol: tc-X(X)
run-on-projects:
by-test-platform:
windows.*: []
linux64-qr/.*: ['mozilla-central', 'try']
# TODO Windows: Turn on on the other branches once Bug 1374787 is fixed
windows.*: ['mozilla-central', 'try']
default: built-projects
docker-image: {"in-tree": "desktop1604-test"}
chunks:
by-test-platform:
linux64/debug: 10
android-4.2-x86/opt: 6
# windows.*: 1
macosx.*: 1
windows.*: 1
default: 8
instance-size:
by-test-platform:
android.*: xlarge
default: legacy # Bug 1281241: migrating to m3.large instances
max-run-time: 5400
tier:
by-test-platform:
windows.*: 3
default: default
e10s: false
allow-software-gl-layers: false
mozharness:
@ -1619,3 +1624,8 @@ xpcshell:
- --xpcshell-suite=xpcshell-coverage
default:
- --xpcshell-suite=xpcshell
requires-signed-builds:
by-test-platform:
windows10-64-asan/opt: false # No XPCShell on ASAN yet
windows.*: true
default: false

Просмотреть файл

@ -15,10 +15,9 @@ build-signing
-------------
Many builds must be signed. The build-signing task takes the unsigned `build`
kind artifacts and passess them through signingscriptworker to a signing server
kind artifacts and passes them through signingscriptworker to a signing server
and returns signed results.
artifact-build
--------------

Просмотреть файл

@ -0,0 +1,24 @@
# 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/.
from __future__ import absolute_import, print_function, unicode_literals
from taskgraph.loader.single_dep import loader as base_loader
# XXX: This logic should rely in kind.yml. This hasn't been done in the original
# patch because it required some heavy changes in single_dep.
LABELS_WHICH_SHOULD_SIGN_CI_BUILDS = (
'build-win32/debug', 'build-win32/opt', 'build-win32-pgo/opt',
'build-win64/debug', 'build-win64/opt', 'build-win64-pgo/opt',
)
def loader(kind, path, config, params, loaded_tasks):
jobs = base_loader(kind, path, config, params, loaded_tasks)
for job in jobs:
dependent_task = job['dependent-task']
if dependent_task.attributes.get('nightly') or \
dependent_task.label in LABELS_WHICH_SHOULD_SIGN_CI_BUILDS:
yield job

Просмотреть файл

@ -14,7 +14,13 @@ def loader(kind, path, config, params, loaded_tasks):
jobs = base_loader(kind, path, config, params, loaded_tasks)
for job in jobs:
job['dependent-tasks'] = get_dependent_loaded_tasks(config, loaded_tasks)
dependent_tasks = get_dependent_loaded_tasks(config, loaded_tasks)
if not dependent_tasks:
# PushApk must depend on signed APK. If no dependent task was found,
# this means another plaform (like windows) is being processed
continue
job['dependent-tasks'] = dependent_tasks
yield job

Просмотреть файл

@ -18,17 +18,21 @@ def loader(kind, path, config, params, loaded_tasks):
"""
# the kind on which this one depends
if len(config.get('kind-dependencies', [])) != 1:
if len(config.get('kind-dependencies', [])) != 2:
raise Exception(
"Test kinds must have exactly one item in kind-dependencies")
dep_kind = config['kind-dependencies'][0]
'Test kinds must have exactly 2 items in kind-dependencies'
)
# get build tasks, keyed by build platform
builds_by_platform = get_builds_by_platform(dep_kind, loaded_tasks)
builds_by_platform = get_builds_by_platform(dep_kind='build', loaded_tasks=loaded_tasks)
signed_builds_by_platform = get_builds_by_platform(
dep_kind='build-signing', loaded_tasks=loaded_tasks
)
# get the test platforms for those build tasks
test_platforms_cfg = load_yaml(path, 'test-platforms.yml')
test_platforms = get_test_platforms(test_platforms_cfg, builds_by_platform)
test_platforms = get_test_platforms(
test_platforms_cfg, builds_by_platform, signed_builds_by_platform
)
# expand the test sets for each of those platforms
test_sets_cfg = load_yaml(path, 'test-sets.yml')
@ -44,9 +48,12 @@ def loader(kind, path, config, params, loaded_tasks):
test['build-platform'] = test_platform['build-platform']
test['test-platform'] = test_platform_name
test['build-label'] = test_platform['build-label']
if test_platform.get('build-signing-label', None):
test['build-signing-label'] = test_platform['build-signing-label']
test['build-attributes'] = test_platform['build-attributes']
test['test-name'] = test_name
if test_platform['nightly']:
if test_platform.get('nightly'):
test.setdefault('attributes', {})['nightly'] = True
logger.debug("Generating tasks for test {} on platform {}".format(
@ -73,7 +80,7 @@ def get_builds_by_platform(dep_kind, loaded_tasks):
return builds_by_platform
def get_test_platforms(test_platforms_cfg, builds_by_platform):
def get_test_platforms(test_platforms_cfg, builds_by_platform, signed_builds_by_platform={}):
"""Get the test platforms for which test tasks should be generated,
based on the available build platforms. Returns a dictionary mapping
test platform to {test-set, build-platform, build-label}."""
@ -86,12 +93,22 @@ def get_test_platforms(test_platforms_cfg, builds_by_platform):
build_platform, test_platform))
continue
test_platforms[test_platform] = {
'nightly': builds_by_platform[build_platform].attributes.get('nightly', False),
'build-platform': build_platform,
'build-label': builds_by_platform[build_platform].label,
'build-attributes': builds_by_platform[build_platform].attributes,
}
if builds_by_platform[build_platform].attributes.get('nightly'):
test_platforms[test_platform]['nightly'] = \
builds_by_platform[build_platform].attributes['nightly']
test_platforms[test_platform].update(cfg)
if build_platform in signed_builds_by_platform:
# Context: Signed builds are only used by Windows
test_platforms[test_platform]['build-signing-label'] = \
signed_builds_by_platform[build_platform].label
return test_platforms

Просмотреть файл

@ -8,6 +8,7 @@ Transform the beetmover task into an actual task description.
from __future__ import absolute_import, print_function, unicode_literals
from taskgraph.transforms.base import TransformSequence
from taskgraph.util.attributes import copy_attributes_from_dependent_job
from taskgraph.util.schema import validate_schema, Schema
from taskgraph.util.scriptworker import (get_balrog_server_scope,
get_balrog_channel_scopes)
@ -63,11 +64,7 @@ def make_task_description(config, jobs):
treeherder.setdefault('tier', 1)
treeherder.setdefault('kind', 'build')
attributes = {
'nightly': dep_job.attributes.get('nightly', False),
'build_platform': dep_job.attributes.get('build_platform'),
'build_type': dep_job.attributes.get('build_type'),
}
attributes = copy_attributes_from_dependent_job(dep_job)
if dep_job.attributes.get('locale'):
treeherder['symbol'] = 'tc-Up({})'.format(dep_job.attributes.get('locale'))

Просмотреть файл

@ -8,6 +8,7 @@ Transform the beetmover task into an actual task description.
from __future__ import absolute_import, print_function, unicode_literals
from taskgraph.transforms.base import TransformSequence
from taskgraph.util.attributes import copy_attributes_from_dependent_job
from taskgraph.util.schema import validate_schema, Schema
from taskgraph.util.scriptworker import (get_beetmover_bucket_scope,
get_beetmover_action_scope)
@ -268,12 +269,8 @@ def make_task_description(config, jobs):
signing_dependencies = dep_job.dependencies
dependencies.update(signing_dependencies)
attributes = {
'nightly': dep_job.attributes.get('nightly', False),
'signed': dep_job.attributes.get('signed', False),
'build_platform': dep_job.attributes.get('build_platform'),
'build_type': dep_job.attributes.get('build_type'),
}
attributes = copy_attributes_from_dependent_job(dep_job)
if job.get('locale'):
attributes['locale'] = job['locale']

Просмотреть файл

@ -8,6 +8,7 @@ Transform the checksums signing task into an actual task description.
from __future__ import absolute_import, print_function, unicode_literals
from taskgraph.transforms.base import TransformSequence
from taskgraph.util.attributes import copy_attributes_from_dependent_job
from taskgraph.util.schema import validate_schema, Schema
from taskgraph.util.scriptworker import (get_beetmover_bucket_scope,
get_beetmover_action_scope)
@ -63,12 +64,8 @@ def make_beetmover_checksums_description(config, jobs):
if k.startswith('beetmover'):
dependencies[k] = v
attributes = {
'nightly': dep_job.attributes.get('nightly', False),
'signed': dep_job.attributes.get('signed', False),
'build_platform': dep_job.attributes.get('build_platform'),
'build_type': dep_job.attributes.get('build_type'),
}
attributes = copy_attributes_from_dependent_job(dep_job)
if dep_job.attributes.get('locale'):
treeherder['symbol'] = 'tc-BMcs({})'.format(dep_job.attributes.get('locale'))
attributes['locale'] = dep_job.attributes.get('locale')

Просмотреть файл

@ -8,6 +8,7 @@ Transform the beetmover task into an actual task description.
from __future__ import absolute_import, print_function, unicode_literals
from taskgraph.transforms.base import TransformSequence
from taskgraph.util.attributes import copy_attributes_from_dependent_job
from taskgraph.util.schema import validate_schema, Schema
from taskgraph.util.scriptworker import (get_beetmover_bucket_scope,
get_beetmover_action_scope)
@ -166,12 +167,7 @@ def make_task_description(config, jobs):
}
dependencies.update(repackage_dependencies)
attributes = {
'nightly': dep_job.attributes.get('nightly', False),
'signed': dep_job.attributes.get('signed', False),
'build_platform': dep_job.attributes.get('build_platform'),
'build_type': dep_job.attributes.get('build_type'),
}
attributes = copy_attributes_from_dependent_job(dep_job)
if job.get('locale'):
attributes['locale'] = job['locale']

Просмотреть файл

@ -22,8 +22,8 @@ def set_defaults(config, jobs):
job['treeherder'].setdefault('tier', 1)
job.setdefault('needs-sccache', True)
_, worker_os = worker_type_implementation(job['worker-type'])
worker = job.setdefault('worker', {})
if worker_os == "linux":
worker = job.setdefault('worker')
worker.setdefault('docker-image', {'in-tree': 'desktop-build'})
worker['chain-of-trust'] = True
extra = job.setdefault('extra', {})
@ -32,8 +32,12 @@ def set_defaults(config, jobs):
extra['chainOfTrust']['inputs']['docker-image'] = {
"task-reference": "<docker-image>"
}
elif worker_os in set(["macosx", "windows"]):
job['worker'].setdefault('env', {})
elif worker_os == "windows":
worker.setdefault('env', {})
worker['chain-of-trust'] = True
elif worker_os == "macosx":
worker.setdefault('env', {})
yield job

Просмотреть файл

@ -21,13 +21,15 @@ def add_signed_routes(config, jobs):
dep_job = job['dependent-task']
job['routes'] = []
for dep_route in dep_job.task.get('routes', []):
if not dep_route.startswith('index.gecko.v2'):
continue
branch = dep_route.split(".")[3]
rest = ".".join(dep_route.split(".")[4:])
job['routes'].append(
'index.gecko.v2.{}.signed-nightly.{}'.format(branch, rest))
if dep_job.attributes.get('nightly'):
for dep_route in dep_job.task.get('routes', []):
if not dep_route.startswith('index.gecko.v2'):
continue
branch = dep_route.split(".")[3]
rest = ".".join(dep_route.split(".")[4:])
job['routes'].append(
'index.gecko.v2.{}.signed-nightly.{}'.format(branch, rest))
yield job
@ -36,42 +38,10 @@ def make_signing_description(config, jobs):
for job in jobs:
dep_job = job['dependent-task']
if 'android' in dep_job.attributes.get('build_platform'):
job_specs = [
{
'artifacts': ['public/build/target.apk',
'public/build/en-US/target.apk'],
'format': 'jar',
},
]
elif 'macosx' in dep_job.attributes.get('build_platform'):
job_specs = [
{
'artifacts': ['public/build/target.dmg'],
'format': 'macapp',
},
]
else:
job_specs = [
{
'artifacts': ['public/build/target.tar.bz2'],
'format': 'gpg',
}, {
'artifacts': ['public/build/update/target.complete.mar'],
'format': 'mar',
}
]
upstream_artifacts = []
for spec in job_specs:
fmt = spec["format"]
upstream_artifacts.append({
"taskId": {"task-reference": "<build>"},
"taskType": "build",
"paths": spec["artifacts"],
"formats": [fmt]
})
job['upstream-artifacts'] = upstream_artifacts
job['upstream-artifacts'] = _generate_upstream_artifacts(
dep_job.attributes.get('build_platform'),
dep_job.attributes.get('nightly')
)
label = dep_job.label.replace("build-", "signing-")
job['label'] = label
@ -81,3 +51,41 @@ def make_signing_description(config, jobs):
job['use-funsize-route'] = True
yield job
def _generate_upstream_artifacts(build_platform, is_nightly=False):
if 'android' in build_platform:
artifacts_specificities = [{
'artifacts': [
'public/build/target.apk',
'public/build/en-US/target.apk'
],
'format': 'jar',
}]
# XXX: Mac and Windows don't sign mars because internal aren't signed at
# this stage of the release
elif 'macosx' in build_platform:
artifacts_specificities = [{
'artifacts': ['public/build/target.dmg'],
'format': 'macapp',
}]
elif 'win' in build_platform:
artifacts_specificities = [{
'artifacts': ['public/build/target.zip'],
'format': 'sha2signcode',
}]
else:
artifacts_specificities = [{
'artifacts': ['public/build/target.tar.bz2'],
'format': 'gpg',
}, {
'artifacts': ['public/build/update/target.complete.mar'],
'format': 'mar',
}]
return [{
'taskId': {'task-reference': '<build>'},
'taskType': 'build',
'paths': specificity['artifacts'],
'formats': [specificity['format']],
} for specificity in artifacts_specificities]

Просмотреть файл

@ -8,6 +8,7 @@ Transform the checksums signing task into an actual task description.
from __future__ import absolute_import, print_function, unicode_literals
from taskgraph.transforms.base import TransformSequence
from taskgraph.util.attributes import copy_attributes_from_dependent_job
from taskgraph.util.schema import validate_schema, Schema
from taskgraph.util.scriptworker import get_signing_cert_scope
from taskgraph.transforms.task import task_description_schema
@ -57,11 +58,8 @@ def make_checksums_signing_description(config, jobs):
label = job.get('label', "checksumssigning-{}".format(dep_job.label))
dependencies = {"beetmover": dep_job.label}
attributes = {
'nightly': dep_job.attributes.get('nightly', False),
'build_platform': dep_job.attributes.get('build_platform'),
'build_type': dep_job.attributes.get('build_type'),
}
attributes = copy_attributes_from_dependent_job(dep_job)
if dep_job.attributes.get('locale'):
treeherder['symbol'] = 'tc-cs({})'.format(dep_job.attributes.get('locale'))
attributes['locale'] = dep_job.attributes.get('locale')

Просмотреть файл

@ -81,6 +81,8 @@ mozharness_run_schema = Schema({
# If specified, use the in-tree job script specified.
Optional('job-script'): basestring,
Required('requires-signed-builds', default=False): bool,
})

Просмотреть файл

@ -203,7 +203,8 @@ def mozharness_test_on_generic_worker(config, job, taskdesc):
'type': 'directory'
})
installer_url = get_artifact_url('<build>', mozharness['build-artifact-name'])
upstream_task = '<build-signing>' if mozharness['requires-signed-builds'] else '<build>'
installer_url = get_artifact_url(upstream_task, mozharness['build-artifact-name'])
taskdesc['scopes'].extend(
['generic-worker:os-group:{}'.format(group) for group in test['os-groups']])

Просмотреть файл

@ -8,6 +8,7 @@ Transform the repackage task into an actual task description.
from __future__ import absolute_import, print_function, unicode_literals
from taskgraph.transforms.base import TransformSequence
from taskgraph.util.attributes import copy_attributes_from_dependent_job
from taskgraph.util.schema import validate_schema, Schema
from taskgraph.transforms.task import task_description_schema
from voluptuous import Any, Required, Optional
@ -109,11 +110,8 @@ def make_job_description(config, jobs):
signing_task_ref = "<{}>".format(signing_task)
build_task_ref = "<{}>".format(build_task)
attributes = {
'nightly': dep_job.attributes.get('nightly', False),
'build_platform': dep_job.attributes.get('build_platform'),
'build_type': dep_job.attributes.get('build_type'),
}
attributes = copy_attributes_from_dependent_job(dep_job)
if job.get('locale'):
attributes['locale'] = job['locale']

Просмотреть файл

@ -8,6 +8,7 @@ Transform the repackage signing task into an actual task description.
from __future__ import absolute_import, print_function, unicode_literals
from taskgraph.transforms.base import TransformSequence
from taskgraph.util.attributes import copy_attributes_from_dependent_job
from taskgraph.util.schema import validate_schema, Schema
from taskgraph.util.scriptworker import get_signing_cert_scope
from taskgraph.transforms.task import task_description_schema
@ -57,11 +58,8 @@ def make_repackage_signing_description(config, jobs):
# This is so we get the build task etc in our dependencies to
# have better beetmover support.
dependencies.update(signing_dependencies)
attributes = {
'nightly': dep_job.attributes.get('nightly', False),
'build_platform': dep_job.attributes.get('build_platform'),
'build_type': dep_job.attributes.get('build_type'),
}
attributes = copy_attributes_from_dependent_job(dep_job)
locale_str = ""
if dep_job.attributes.get('locale'):
treeherder['symbol'] = 'tc-rs({})'.format(dep_job.attributes.get('locale'))

Просмотреть файл

@ -8,6 +8,7 @@ Transform the signing task into an actual task description.
from __future__ import absolute_import, print_function, unicode_literals
from taskgraph.transforms.base import TransformSequence
from taskgraph.util.attributes import copy_attributes_from_dependent_job
from taskgraph.util.schema import validate_schema, Schema
from taskgraph.util.scriptworker import get_signing_cert_scope, get_devedition_signing_cert_scope
from taskgraph.transforms.task import task_description_schema
@ -88,21 +89,27 @@ def make_task_description(config, jobs):
signing_format_scopes.append("project:releng:signing:format:{}".format(format))
treeherder = job.get('treeherder', {})
treeherder.setdefault('symbol', 'tc(Ns)')
is_nightly = dep_job.attributes.get('nightly', False)
treeherder.setdefault('symbol', _generate_treeherder_symbol(is_nightly))
dep_th_platform = dep_job.task.get('extra', {}).get(
'treeherder', {}).get('machine', {}).get('platform', '')
treeherder.setdefault('platform', "{}/opt".format(dep_th_platform))
treeherder.setdefault('tier', 1)
build_type = dep_job.attributes.get('build_type')
build_platform = dep_job.attributes.get('build_platform')
treeherder.setdefault('platform', _generate_treeherder_platform(
dep_th_platform, build_platform, build_type
))
# TODO: Make non-nightly (i.e. windows CI builds) Tier 1 once green on
# central, inbound, autoland and try
treeherder.setdefault('tier', 1 if is_nightly else 3)
treeherder.setdefault('kind', 'build')
label = job.get('label', "{}-signing".format(dep_job.label))
attributes = {
'nightly': dep_job.attributes.get('nightly', False),
'build_platform': dep_job.attributes.get('build_platform'),
'build_type': dep_job.attributes.get('build_type'),
'signed': True,
}
attributes = copy_attributes_from_dependent_job(dep_job)
attributes['signed'] = True
if dep_job.attributes.get('chunk_locales'):
# Used for l10n attribute passthrough
attributes['chunk_locales'] = dep_job.attributes.get('chunk_locales')
@ -113,14 +120,16 @@ def make_task_description(config, jobs):
if dep_job.attributes.get('build_platform') in set(
['linux64-devedition-nightly', 'linux-devedition-nightly']):
signing_cert_scope = get_devedition_signing_cert_scope(config)
else:
elif is_nightly:
signing_cert_scope = get_signing_cert_scope(config)
else:
signing_cert_scope = 'project:releng:signing:cert:dep-signing'
task = {
'label': label,
'description': "{} Signing".format(
dep_job.task["metadata"]["description"]),
'worker-type': "scriptworker-prov-v1/signing-linux-v1",
'worker-type': _generate_worker_type(signing_cert_scope),
'worker': {'implementation': 'scriptworker-signing',
'upstream-artifacts': job['upstream-artifacts'],
'max-run-time': 3600},
@ -138,3 +147,17 @@ def make_task_description(config, jobs):
project=config.params['project'], level=config.params['level']))
yield task
def _generate_treeherder_platform(dep_th_platform, build_platform, build_type):
actual_build_type = 'pgo' if '-pgo' in build_platform else build_type
return '{}/{}'.format(dep_th_platform, actual_build_type)
def _generate_treeherder_symbol(is_nightly):
return 'tc(Ns)' if is_nightly else 'tc(Bs)'
def _generate_worker_type(signing_cert_scope):
worker_type = 'depsigning' if 'dep-signing' in signing_cert_scope else 'signing-linux-v1'
return 'scriptworker-prov-v1/{}'.format(worker_type)

Просмотреть файл

@ -249,6 +249,10 @@ test_description_schema = Schema({
# chunking-args = test-suite-suffix; "<CHUNK>" in this string will
# be replaced with the chunk number.
Optional('chunk-suffix'): basestring,
Required('requires-signed-builds', default=False): optionally_keyed_by(
'test-platform',
bool),
}
),
@ -269,6 +273,10 @@ test_description_schema = Schema({
# the label of the build task generating the materials to test
'build-label': basestring,
# the label of the signing task generating the materials to test.
# Signed builds are used in xpcshell tests on Windows, for instance.
Optional('build-signing-label'): basestring,
# the build's attributes
'build-attributes': {basestring: object},
@ -387,6 +395,7 @@ def set_target(config, tests):
else:
target = 'target.tar.bz2'
test['mozharness']['build-artifact-name'] = 'public/build/' + target
yield test
@ -492,6 +501,7 @@ def handle_keyed_by(config, tests):
'mozharness.chunked',
'mozharness.config',
'mozharness.extra-options',
'mozharness.requires-signed-builds',
]
for test in tests:
for field in fields:
@ -775,6 +785,10 @@ def make_job_description(config, tests):
jobdesc['when'] = test.get('when', {})
jobdesc['attributes'] = attributes
jobdesc['dependencies'] = {'build': build_label}
if test['mozharness']['requires-signed-builds'] is True:
jobdesc['dependencies']['build-signing'] = test['build-signing-label']
jobdesc['expires-after'] = test['expires-after']
jobdesc['routes'] = []
jobdesc['run-on-projects'] = test['run-on-projects']

Просмотреть файл

@ -19,6 +19,8 @@ RELEASE_PROJECTS = {
'mozilla-release',
}
_OPTIONAL_ATTRIBUTES = ('nightly', 'signed')
def attrmatch(attributes, **kwargs):
"""Determine whether the given set of task attributes matches. The
@ -81,3 +83,17 @@ def match_run_on_projects(project, run_on_projects):
return True
return project in run_on_projects
def copy_attributes_from_dependent_job(dep_job):
attributes = {
'build_platform': dep_job.attributes.get('build_platform'),
'build_type': dep_job.attributes.get('build_type'),
}
attributes.update({
attr: dep_job.attributes[attr]
for attr in _OPTIONAL_ATTRIBUTES if attr in dep_job.attributes
})
return attributes