fune/taskcluster/taskgraph/task.py
Tom Prince 7c05ff5c43 Bug 1653717: [taskgraph] Handle composite description nicely; r=Callek
When links to specific tasks in treeherder was added to the description in
Bug 1630710, This caused the descriptions for several derived tasks to include
the `{'task-reference': '...'}` wrapper in the derived description. This is
in addition to the already duplicate links to treeherder those tasks had.

To ameliorate this issue, keep track of the original description without the
treeherder link and use that in derived tasks.

Differential Revision: https://phabricator.services.mozilla.com/D84047
2020-07-18 15:59:27 +00:00

96 lines
3.5 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/.
from __future__ import absolute_import, print_function, unicode_literals
import attr
@attr.s
class Task(object):
"""
Representation of a task in a TaskGraph. Each Task has, at creation:
- kind: the name of the task kind
- label; the label for this task
- attributes: a dictionary of attributes for this task (used for filtering)
- task: the task definition (JSON-able dictionary)
- optimization: optimization to apply to the task (see taskgraph.optimize)
- dependencies: tasks this one depends on, in the form {name: label}, for example
{'build': 'build-linux64/opt', 'docker-image': 'build-docker-image-desktop-test'}
- soft_dependencies: tasks this one may depend on if they are available post
optimisation. They are set as a list of tasks label.
And later, as the task-graph processing proceeds:
- task_id -- TaskCluster taskId under which this task will be created
This class is just a convenience wrapper for the data type and managing
display, comparison, serialization, etc. It has no functionality of its own.
"""
kind = attr.ib()
label = attr.ib()
attributes = attr.ib()
task = attr.ib()
description = attr.ib(default="")
task_id = attr.ib(default=None, init=False)
optimization = attr.ib(default=None)
dependencies = attr.ib(factory=dict)
soft_dependencies = attr.ib(factory=list)
release_artifacts = attr.ib(
converter=attr.converters.optional(frozenset),
default=None,
)
def __attrs_post_init__(self):
self.attributes['kind'] = self.kind
@property
def name(self):
if self.label.startswith(self.kind + "-"):
return self.label[len(self.kind)+1:]
elif self.label.startswith("build-docker-image-"):
return self.label[len("build-docker-image-"):]
else:
raise AttributeError("Task {} does not have a name.".format(self.label))
def to_json(self):
rv = {
'kind': self.kind,
'label': self.label,
'description': self.description,
'attributes': self.attributes,
'dependencies': self.dependencies,
'soft_dependencies': sorted(self.soft_dependencies),
'optimization': self.optimization,
'task': self.task,
}
if self.task_id:
rv['task_id'] = self.task_id
if self.release_artifacts:
rv['release_artifacts'] = sorted(self.release_artifacts)
return rv
@classmethod
def from_json(cls, task_dict):
"""
Given a data structure as produced by taskgraph.to_json, re-construct
the original Task object. This is used to "resume" the task-graph
generation process, for example in Action tasks.
"""
rv = cls(
kind=task_dict['kind'],
label=task_dict['label'],
description=task_dict.get('description', ""),
attributes=task_dict['attributes'],
task=task_dict['task'],
optimization=task_dict['optimization'],
dependencies=task_dict.get('dependencies'),
soft_dependencies=task_dict.get('soft_dependencies'),
release_artifacts=task_dict.get('release-artifacts'),
)
if 'task_id' in task_dict:
rv.task_id = task_dict['task_id']
return rv