Esempio n. 1
0
 def test_badly_formed(self):
     "resolve_task_references ignores badly-formatted artifact references"
     for inv in ["<edge1>", "edge1/foo>", "<edge1>/foo", "<edge1>foo"]:
         resolved = resolve_task_references("subject",
                                            {"artifact-reference": inv},
                                            "tid-self", "tid-decision", {})
         self.assertEqual(resolved, inv)
Esempio n. 2
0
 def do(self, input, output):
     taskid_for_edge_name = {"edge%d" % n: "tid%d" % n for n in range(1, 4)}
     with mock.patch.dict(
             os.environ,
         {"TASKCLUSTER_ROOT_URL": "https://tc-tests.localhost"}):
         self.assertEqual(
             resolve_task_references("subject", input, "tid-self",
                                     "tid-decision", taskid_for_edge_name),
             output,
         )
Esempio n. 3
0
 def do(self, input, output):
     taskid_for_edge_name = {"edge%d" % n: "tid%d" % n for n in range(1, 4)}
     self.assertEqual(
         resolve_task_references(
             "subject",
             input,
             "tid-self",
             "tid-decision",
             taskid_for_edge_name,
         ),
         output,
     )
Esempio n. 4
0
 def test_invalid(self):
     "resolve_task_references raises a KeyError on reference to an invalid task"
     self.assertRaisesRegexp(
         KeyError,
         "task 'subject' has no dependency named 'no-such'",
         lambda: resolve_task_references(
             "subject",
             {"artifact-reference": "<no-such/public/artifact>"},
             "tid-self",
             "tid-decision",
             {},
         ),
     )
Esempio n. 5
0
 def test_self(self):
     "resolve_task_references raises KeyError on artifact references to `self`"
     self.assertRaisesRegexp(
         KeyError,
         "task 'subject' can't reference artifacts of self",
         lambda: resolve_task_references(
             "subject",
             {"artifact-reference": "<self/public/artifact>"},
             "tid-self",
             "tid-decision",
             {},
         ),
     )
Esempio n. 6
0
def get_subgraph(
    target_task_graph,
    removed_tasks,
    replaced_tasks,
    label_to_taskid,
    decision_task_id,
):
    """
    Return the subgraph of target_task_graph consisting only of
    non-optimized tasks and edges between them.

    To avoid losing track of taskIds for tasks optimized away, this method
    simultaneously substitutes real taskIds for task labels in the graph, and
    populates each task definition's `dependencies` key with the appropriate
    taskIds.  Task references are resolved in the process.
    """

    # check for any dependency edges from included to removed tasks
    bad_edges = [(l, r, n) for l, r, n in target_task_graph.graph.edges
                 if l not in removed_tasks and r in removed_tasks]
    if bad_edges:
        probs = ", ".join(f"{l} depends on {r} as {n} but it has been removed"
                          for l, r, n in bad_edges)
        raise Exception("Optimization error: " + probs)

    # fill in label_to_taskid for anything not removed or replaced
    assert replaced_tasks <= set(label_to_taskid)
    for label in sorted(target_task_graph.graph.nodes - removed_tasks -
                        set(label_to_taskid)):
        label_to_taskid[label] = slugid()

    # resolve labels to taskIds and populate task['dependencies']
    tasks_by_taskid = {}
    named_links_dict = target_task_graph.graph.named_links_dict()
    omit = removed_tasks | replaced_tasks
    for label, task in target_task_graph.tasks.items():
        if label in omit:
            continue
        task.task_id = label_to_taskid[label]
        named_task_dependencies = {
            name: label_to_taskid[label]
            for name, label in named_links_dict.get(label, {}).items()
        }

        # Add remaining soft dependencies
        if task.soft_dependencies:
            named_task_dependencies.update({
                label: label_to_taskid[label]
                for label in task.soft_dependencies
                if label in label_to_taskid and label not in omit
            })

        task.task = resolve_task_references(
            task.label,
            task.task,
            task_id=task.task_id,
            decision_task_id=decision_task_id,
            dependencies=named_task_dependencies,
        )
        deps = task.task.setdefault("dependencies", [])
        deps.extend(sorted(named_task_dependencies.values()))
        tasks_by_taskid[task.task_id] = task

    # resolve edges to taskIds
    edges_by_taskid = ((label_to_taskid.get(left), label_to_taskid.get(right),
                        name) for (left, right,
                                   name) in target_task_graph.graph.edges)
    # ..and drop edges that are no longer entirely in the task graph
    #   (note that this omits edges to replaced tasks, but they are still in task.dependnecies)
    edges_by_taskid = {(left, right, name)
                       for (left, right, name) in edges_by_taskid
                       if left in tasks_by_taskid and right in tasks_by_taskid}

    return TaskGraph(tasks_by_taskid,
                     Graph(set(tasks_by_taskid), edges_by_taskid))