fune/taskcluster/gecko_taskgraph/task.py
Andrew Halberstadt 95449daa6d Bug 1732723 - Rename "taskgraph" Python module to "gecko_taskgraph". r=jmaher
For a long time two copies of the 'taskgraph' module have existed in parallel.
We've attempted to keep them in sync, but over time they have diverged and the
maintenance burden has increased.

In order to reduce this burden, we'd like to re-join the two code bases. The
canonical repo will be the one that lives outside of mozilla-central, and this
module will depend on it. Since they both have the same module name (taskgraph)
we need to rename the version in mozilla-central to avoid collisions.

Other consumers of 'taskgraph' (like mobile repos) have standardized on
'<project>_taskgraph' as their module names. So replicating that here as well.

Differential Revision: https://phabricator.services.mozilla.com/D127118
2021-09-30 09:50:08 -04:00

98 lines
3.6 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/.
import attr
@attr.s
class Task:
"""
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 gecko_taskgraph.optimize)
- dependencies: tasks this one depends on, in the form {name: label}, for example
{'build': 'build-linux64/opt', 'docker-image': '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.
- if_dependencies: only run this task if at least one of these dependencies
are present.
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)
if_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 :]
else:
raise AttributeError(f"Task {self.label} does not have a name.")
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),
"if_dependencies": self.if_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"),
if_dependencies=task_dict.get("if_dependencies"),
release_artifacts=task_dict.get("release-artifacts"),
)
if "task_id" in task_dict:
rv.task_id = task_dict["task_id"]
return rv