2017-07-20 22:24:50 +03:00
|
|
|
# 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
|
|
|
|
|
|
|
|
import re
|
|
|
|
|
|
|
|
from taskgraph.util.time import json_time_from_now
|
2018-12-18 18:35:18 +03:00
|
|
|
from taskgraph.util.taskcluster import get_artifact_url
|
2017-07-20 22:24:50 +03:00
|
|
|
|
|
|
|
TASK_REFERENCE_PATTERN = re.compile('<([^>]+)>')
|
2018-09-25 23:26:55 +03:00
|
|
|
ARTIFACT_REFERENCE_PATTERN = re.compile('<([^/]+)/([^>]+)>')
|
2017-07-20 22:24:50 +03:00
|
|
|
|
|
|
|
|
2018-09-25 23:26:55 +03:00
|
|
|
def _recurse(val, param_fns):
|
2017-07-20 22:24:50 +03:00
|
|
|
def recurse(val):
|
|
|
|
if isinstance(val, list):
|
|
|
|
return [recurse(v) for v in val]
|
|
|
|
elif isinstance(val, dict):
|
2018-09-25 23:26:55 +03:00
|
|
|
if len(val) == 1:
|
|
|
|
for param_key, param_fn in param_fns.items():
|
|
|
|
if val.keys() == [param_key]:
|
|
|
|
return param_fn(val[param_key])
|
|
|
|
return {k: recurse(v) for k, v in val.iteritems()}
|
2017-07-20 22:24:50 +03:00
|
|
|
else:
|
|
|
|
return val
|
|
|
|
return recurse(val)
|
|
|
|
|
|
|
|
|
|
|
|
def resolve_timestamps(now, task_def):
|
|
|
|
"""Resolve all instances of `{'relative-datestamp': '..'}` in the given task definition"""
|
2018-09-25 23:26:55 +03:00
|
|
|
return _recurse(task_def, {
|
|
|
|
'relative-datestamp': lambda v: json_time_from_now(v, now),
|
|
|
|
})
|
2017-07-20 22:24:50 +03:00
|
|
|
|
|
|
|
|
2020-06-03 05:35:14 +03:00
|
|
|
def resolve_task_references(label, task_def, task_id, dependencies):
|
2018-09-25 23:26:55 +03:00
|
|
|
"""Resolve all instances of
|
|
|
|
{'task-reference': '..<..>..'}
|
|
|
|
and
|
|
|
|
{'artifact-reference`: '..<dependency/artifact/path>..'}
|
2019-06-26 23:00:31 +03:00
|
|
|
in the given task definition, using the given dependencies
|
|
|
|
|
|
|
|
"""
|
2018-09-25 23:26:55 +03:00
|
|
|
|
|
|
|
def task_reference(val):
|
|
|
|
def repl(match):
|
|
|
|
key = match.group(1)
|
2020-06-03 05:35:14 +03:00
|
|
|
if key == 'self':
|
|
|
|
return task_id
|
2018-09-25 23:26:55 +03:00
|
|
|
try:
|
|
|
|
return dependencies[key]
|
|
|
|
except KeyError:
|
|
|
|
# handle escaping '<'
|
|
|
|
if key == '<':
|
|
|
|
return key
|
|
|
|
raise KeyError("task '{}' has no dependency named '{}'".format(label, key))
|
|
|
|
|
|
|
|
return TASK_REFERENCE_PATTERN.sub(repl, val)
|
|
|
|
|
|
|
|
def artifact_reference(val):
|
|
|
|
def repl(match):
|
|
|
|
dependency, artifact_name = match.group(1, 2)
|
|
|
|
|
2020-06-03 05:35:14 +03:00
|
|
|
if dependency == 'self':
|
|
|
|
raise KeyError(
|
|
|
|
"task '{}' can't reference artifacts of self".format(label)
|
|
|
|
)
|
|
|
|
|
2020-06-03 05:30:51 +03:00
|
|
|
try:
|
|
|
|
task_id = dependencies[dependency]
|
|
|
|
except KeyError:
|
|
|
|
raise KeyError("task '{}' has no dependency named '{}'".format(label, dependency))
|
2018-09-25 23:26:55 +03:00
|
|
|
|
2018-12-18 18:35:18 +03:00
|
|
|
assert artifact_name.startswith('public/'), \
|
|
|
|
"artifact-reference only supports public artifacts, not `{}`".format(artifact_name)
|
|
|
|
return get_artifact_url(task_id, artifact_name)
|
2018-09-25 23:26:55 +03:00
|
|
|
|
|
|
|
return ARTIFACT_REFERENCE_PATTERN.sub(repl, val)
|
|
|
|
|
|
|
|
return _recurse(task_def, {
|
|
|
|
'task-reference': task_reference,
|
|
|
|
'artifact-reference': artifact_reference,
|
|
|
|
})
|