deleted file mode 100644
--- a/taskcluster/docs/action-implementation.rst
+++ /dev/null
@@ -1,244 +0,0 @@
-Action Task Implementation
-==========================
-
-This document shows how to define an action in-tree such that it shows up in
-supported user interfaces like Treeherder. For details on interface between
-in-tree logic and external user interfaces, see
-:doc:`the specification for actions.json <action-spec>`.
-
-There are two options for defining actions: creating a callback action, or
-creating a custom action task. A callback action automatically defines an
-action task that will invoke a Python function of your devising.
-
-A custom action task is an arbitrary task definition that will be created
-directly. In cases where the callback would simply call ``queue.createTask``,
-a custom action task can be more efficient.
-
-Creating a Callback Action
---------------------------
-A *callback action* is an action that calls back into in-tree logic. That is,
-you register the action with name, title, description, context, input schema and a
-python callback. When the action is triggered in a user interface,
-input matching the schema is collected, passed to a new task which then calls
-your python callback, enabling it to do pretty much anything it wants to.
-
-To create a new action you must create a file
-``taskcluster/taskgraph/actions/my-action.py``, that at minimum contains::
-
- from registry import register_callback_action
-
- @register_callback_action(
- name='hello',
- title='Say Hello',
- symbol='hw', # Show the callback task in treeherder as 'hw'
- description="Simple **proof-of-concept** callback action",
- order=10000, # Order in which it should appear relative to other actions
- )
- def hello_world_action(parameters, input, task_group_id, task_id, task):
- # parameters is an instance of taskgraph.parameters.Parameters
- # it carries decision task parameters from the original decision task.
- # input, task_id, and task should all be None
- print "Hello was triggered from taskGroupId: " + taskGroupId
-
-The example above defines an action that is available in the context-menu for
-the entire task-group (result-set or push in Treeherder terminology). To create
-an action that shows up in the context menu for a task we would specify the
-``context`` parameter.
-
-
-Setting the Action Context
-..........................
-The context parameter should be a list of tag-sets, such as
-``context=[{"platform": "linux"}]``, which will make the task show up in the
-context-menu for any task with ``task.tags.platform = 'linux'``. Below is
-some examples of context parameters and the resulting conditions on
-``task.tags`` (tags used below are just illustrative).
-
-``context=[{"platform": "linux"}]``:
- Requires ``task.tags.platform = 'linux'``.
-``context=[{"kind": "test", "platform": "linux"}]``:
- Requires ``task.tags.platform = 'linux'`` **and** ``task.tags.kind = 'test'``.
-``context=[{"kind": "test"}, {"platform": "linux"}]``:
- Requires ``task.tags.platform = 'linux'`` **or** ``task.tags.kind = 'test'``.
-``context=[{}]``:
- Requires nothing and the action will show up in the context menu for all tasks.
-``context=[]``:
- Is the same as not setting the context parameter, which will make the action
- show up in the context menu for the task-group.
- (i.e., the action is not specific to some task)
-
-The example action below will be shown in the context-menu for tasks with
-``task.tags.platform = 'linux'``::
-
- from registry import register_callback_action
-
- @register_callback_action(
- name='retrigger',
- title='Retrigger',
- symbol='re-c', # Show the callback task in treeherder as 're-c'
- description="Create a clone of the task",
- order=1,
- context=[{'platform': 'linux'}]
- )
- def retrigger_action(parameters, input, task_group_id, task_id, task):
- # input will be None
- print "Retriggering: {}".format(task_id)
- print "task definition: {}".format(task)
-
-When the ``context`` parameter is set, the ``task_id`` and ``task`` parameters
-will provided to the callback. In this case the ``task_id`` and ``task``
-parameters will be the ``taskId`` and *task definition* of the task from whose
-context-menu the action was triggered.
-
-Typically, the ``context`` parameter is used for actions that operate on
-tasks, such as retriggering, running a specific test case, creating a loaner,
-bisection, etc. You can think of the context as a place the action should
-appear, but it's also very much a form of input the action can use.
-
-
-Specifying an Input Schema
-..........................
-In call examples so far the ``input`` parameter for the callbacks has been
-``None``. To make an action that takes input you must specify an input schema.
-This is done by passing a JSON schema as the ``schema`` parameter.
-
-When designing a schema for the input it is important to exploit as many of the
-JSON schema validation features as reasonably possible. Furthermore, it is
-*strongly* encouraged that the ``title`` and ``description`` properties in
-JSON schemas is used to provide a detailed explanation of what the input
-value will do. Authors can reasonably expect JSON schema ``description``
-properties to be rendered as markdown before being presented.
-
-The example below illustrates how to specify an input schema. Notice that while
-this example doesn't specify a ``context`` it is perfectly legal to specify
-both ``input`` and ``context``::
-
- from registry import register_callback_action
-
- @register_callback_action(
- name='run-all',
- title='Run All Tasks',
- symbol='ra-c', # Show the callback task in treeherder as 'ra-c'
- description="**Run all tasks** that have been _optimized_ away.",
- order=1,
- input={
- 'title': 'Action Options',
- 'description': 'Options for how you wish to run all tasks',
- 'properties': {
- 'priority': {
- 'title': 'priority'
- 'description': 'Priority that should be given to the tasks',
- 'type': 'string',
- 'enum': ['low', 'normal', 'high'],
- 'default': 'low',
- },
- 'runTalos': {
- 'title': 'Run Talos'
- 'description': 'Do you wish to also include talos tasks?',
- 'type': 'boolean',
- 'default': 'false',
- }
- },
- 'required': ['priority', 'runTalos'],
- 'additionalProperties': False,
- },
- )
- def retrigger_action(parameters, input, task_group_id, task_id, task):
- print "Create all pruned tasks with priority: {}".format(input['priority'])
- if input['runTalos']:
- print "Also running talos jobs..."
-
-When the ``schema`` parameter is given the callback will always be called with
-an ``input`` parameter that satisfies the previously given JSON schema.
-It is encouraged to set ``additionalProperties: false``, as well as specifying
-all properties as ``required`` in the JSON schema. Furthermore, it's good
-practice to provide ``default`` values for properties, as user interface generators
-will often take advantage of such properties.
-
-Once you have specified input and context as applicable for your action you can
-do pretty much anything you want from within your callback. Whether you want
-to create one or more tasks or run a specific piece of code like a test.
-
-Conditional Availability
-........................
-The decision parameters ``taskgraph.parameters.Parameters`` passed to
-the callback are also available when the decision task generates the list of
-actions to be displayed in the user interface. When registering an action
-callback the ``availability`` option can be used to specify a callable
-which, given the decision parameters, determines if the action should be available.
-The feature is illustrated below::
-
- from registry import register_callback_action
-
- @register_callback_action(
- name='hello',
- title='Say Hello',
- symbol='hw', # Show the callback task in treeherder as 'hw'
- description="Simple **proof-of-concept** callback action",
- order=2,
- # Define an action that is only included if this is a push to try
- available=lambda parameters: parameters.get('project', None) == 'try',
- )
- def try_only_action(parameters, input, task_group_id, task_id, task):
- print "My try-only action"
-
-Properties of ``parameters`` are documented in the
-:doc:`parameters section <parameters>`. You can also examine the
-``parameters.yml`` artifact created by decisions tasks.
-
-
-Creating a Custom Action Task
-------------------------------
-
-It is possible to define an action that doesn't take a callback. Instead, you'll
-then have to provide a task template. For details on how the task template
-language works refer to :doc:`the specification for actions.json <action-spec>`,
-the example below illustrates how to create such an action::
-
- from registry import register_task_action
-
- @register_task_action(
- name='retrigger',
- title='Retrigger',
- description="Create a clone of the task",
- order=1,
- context=[{'platform': 'linux'}],
- input={
- 'title': 'priority'
- 'description': 'Priority that should be given to the tasks',
- 'type': 'string',
- 'enum': ['low', 'normal', 'high'],
- 'default': 'low',
- },
- )
- def task_template_builder(parameters):
- # The task template builder may return None to signal that the action
- # isn't available.
- if parameters.get('project', None) != 'try':
- return None
- return {
- 'created': {'$fromNow': ''},
- 'deadline': {'$fromNow': '1 hour'},
- 'expires': {'$fromNow': '14 days'},
- 'provisionerId': '...',
- 'workerType': '...',
- 'priority': '${input}',
- 'payload': {
- 'command': '...',
- 'env': {
- 'TASK_DEFINITION': {'$json': {'eval': 'task'}}
- },
- ...
- },
- # It's now your responsibility to include treeherder routes, as well
- # additional metadata for treeherder in task.extra.treeherder.
- ...
- },
-
-This kind of action is useful for creating simple derivative tasks, but is
-limited by the expressiveness of the template language. On the other hand, it
-is more efficient than an action callback as it does not involve an
-intermediate action task before creating the task the user requested.
-
-For further details on the template language, see :doc:`the specification for
-actions.json <action-spec>`.
deleted file mode 100644
--- a/taskcluster/docs/action-spec.rst
+++ /dev/null
@@ -1,242 +0,0 @@
-Action Specification
-====================
-This document specifies how actions exposed by the *decision task* are to be
-presented and triggered from Treeherder, or similar user interfaces.
-
-The *decision task* creates an artifact ``public/actions.json`` to be consumed
-by a user interface such as Treeherder. The ``public/actions.json`` file
-specifies actions that can be triggered such as:
-
- * Retrigger a task,
- * Retry specific test cases many times,
- * Obtain a loaner machine,
- * Back-fill missing tasks,
- * ...
-
-Through the ``public/actions.json`` file it is possible expose actions defined
-in-tree such that the actions can be conveniently triggered in Treeherder.
-This has two purposes:
-
- 1. Facilitate development of utility actions/tools in-tree, and,
- 2. Strongly decouple build/test configuration from Treeherder.
-
-For details on how define custom actions in-tree, refer to
-:doc:`the in-tree actions section <action-details>`. This document merely
-specifies how ``actions.json`` shall be interpreted.
-
-Actions
--------
-
-The content of ``actions.json`` is a list of actions (and variables, to be
-described later). Each action has a ``kind`` describing how a user interface
-should trigger it. There is currently only one kind defined: ``task``.
-
-An action with ``kind: 'task'`` specifies a task that the user interface should
-create. That is, when the action is triggered, the user interface calls the
-Taskcluster API to create a new task, with the content of that task determined
-from ``actions.json``.
-
-The task created by the action may be useful in its own right (for example,
-running a test with additional debugging), or it may simplify trigger in-tree
-scripts that create new tasks. The latter form is called an *action task*, and
-is similar to a decision task. This allows in-tree scripts to execute
-complicated actions such as backfilling.
-
-Actions of the ``'task'`` *kind* **must** have a ``task`` property. This
-property specifies the task template to be parameterized and created in order
-to trigger the action.
-
-The template is parameterized using `JSON-e
-<https://github.com/taskcluster/json-e>`_, with the following context entries
-available:
-
-``taskGroupId``
- the ``taskGroupId`` of task-group this is triggerd from,
-``taskId``
- the ``taskId`` of the selected task, ``null`` if no task is
- selected (this is the case if the action has ``context: []``),
-``task``
- the task definition of the selected task, ``null`` if no task is
- selected (this is the case if the action has ``context: []``), and,
-``input``
- the input matching the ``schema`` property, ``null`` if the action
- doesn't have a ``schema`` property. See "Action Input" below.
-``<key>``
- Any ``<key>`` defined in the ``variables`` property may also be referenced.
- See "Variables" below.
-
-The following **example** demonstrates how a task template can specify
-timestamps and dump input JSON into environment variables::
-
- {
- "version": 1,
- "actions": [
- {
- "kind": "task",
- "name": "thing",
- "title: "Do A Thing",
- "description": "Do something",
- "task": {
- "workerType": "my-worker",
- "payload": {
- "created": {"$fromNow": ""},
- "deadline": {"$fromNow": "1 hour 15 minutes"},
- "expiration": {"$fromNow": "14 days"},
- "image": "my-docker-image",
- "env": {
- "TASKID_TRIGGERED_FOR": "${taskId}",
- "INPUT_JSON": {"$json": {"$eval": "input"}}
- },
- ...
- },
- ...
- }
- }
- ],
- "variables: {},
- }
-
-
-MetaData
-........
-
-Each action entry must define a ``name``, ``title`` and ``description``.
-furthermore, the list of actions should be sorted by the order in which actions
-should appear in a menu.
-
-The ``name`` is used by user interfaces to identify the action. For example, a
-retrigger button might look for an action with `name = "retrigger"`.
-
-Action names must be unique for a given task, or for a taskgroup, but the same
-name may be used for actions applying to disjoint sets of tasks. For example,
-it may be helpful to define different "retrigger" actions for build tasks
-`[{jobKind: 'build'}]` and test tasks `[{jobKind: 'test'}]`, and in this case
-only one such action would apply to any given task.
-
-The ``title`` is a human readable string intended to be used as label on the
-button, link or menu entry that triggers the action. This should be short and
-concise. Ideally, you'll want to avoid duplicates.
-
-The ``description`` property contains a human readable string describing the
-action, such as what it does, how it does it, what it is useful for. This string
-is to be render as **markdown**, allowing for bullet points, links and other
-simple formatting to explain what the action does.
-
-
-Action Context
-..............
-
-Few actions are relevant in all contexts. For this reason each action specifies
-a ``context`` property. This property specifies when an action is relevant.
-Actions *relevant* for a task should be displayed in a context menu for the
-given task. Similarly actions *not relevant* for a given task should not be
-displayed in the context menu for the given task.
-
-As a special case we say that actions for which *no relevant* contexts can
-exist, are *relevant* for the task-group. This could for example be an action
-to create tasks that was optimized away.
-
-The ``context`` property is specified as a list of *tag-sets*. A *tag-set* is a
-set of key-value pairs. A task is said to *match* a *tag-set* if ``task.tags``
-is a super-set of the *tag-set*. An action is said to be *relevant* for a given
-task, if ``task.tags`` *match* one of the *tag-sets* given in the ``context``
-property for the action.
-
-Naturally, it follows that an action with an empty list of *tag-sets* in its
-``context`` property cannot possibly be *relevant* for any task. Hence, by
-previously declared special case such an action is *relevant* for the
-task-group.
-
-**Examples**::
-
- // Example task definitions (everything but tags eclipsed)
- TaskA = {..., tags: {kind: 'test', platform: 'linux'}}
- TaskB = {..., tags: {kind: 'test', platform: 'windows'}}
- TaskC = {..., tags: {kind: 'build', platform: 'linux'}}
-
- Action1 = {..., context: [{kind: 'test'}]}
- // Action1 is relevant to: TaskA, TaskB
-
- Action2 = {..., context: [{kind: 'test', platform: 'linux'}]}
- // Action2 is relevant to: TaskA
-
- Action3 = {..., context: [{platform: 'linux'}]}
- // Action3 is relevant to: TaskA, TaskC
-
- Action4 = {..., context: [{kind: 'test'}, {kind: 'build'}]}
- // Action4 is relevant to: TaskA, TaskB, TaskC
-
- Action5 = {..., context: [{}]}
- // Action5 is relevant to: TaskA, TaskB, TaskC (all tasks in fact)
-
- Action6 = {..., context: []}
- // Action6 is relevant to the task-group
-
-
-Action Input
-............
-
-An action can take JSON input, the input format accepted by an action is
-specified using a `JSON schema <http://json-schema.org/>`_. This schema is
-specified with by the action's ``schema`` property. For example::
-
- {
- "version": 1,
- "actions": [
- {
- "kind": "task",
- "name": "thing",
- "title: "Do A Thing",
- "description": "Do something",
- "schema": {
- "description": "The thing to do",
- "title": "Thing",
- "default": "something",
- "type": "string"
- "maxLength": 255
- },
- "task": {
- "payload": {
- "env": {
- "INPUT_JSON": {"$json": {"$eval": "input"}}
- },
- ...
- },
- ...
- }
- }
- ],
- "variables: {},
- }
-
-User interfaces for triggering actions, like Treeherder, are expected to provide
-JSON input that satisfies this schema. These interfaces are also expected to
-validate the input against the schema before attempting to trigger the action.
-
-It is perfectly legal to reference external schemas using
-constructs like ``{"$ref": "https://example.com/my-schema.json"}``, in this case
-it however strongly recommended that the external resource is available over
-HTTPS and allows CORS requests from any source.
-
-When writing schemas it is strongly encouraged that the JSON schema
-``description`` properties are used to provide detailed descriptions. It is
-assumed that consumers will render these ``description`` properties as markdown.
-
-
-Variables
----------
-
-The ``public/actions.json`` artifact has a ``variables`` property that is a
-mapping from variable names to JSON values to be used as constants.
-These variables can be referenced from task templates, but beware that they
-may overshadow builtin variables. This is mainly useful to deduplicate commonly
-used values, in order to reduce template size. This feature does not
-introduce further expressiveness.
-
-Formal Specification
---------------------
-
-The following is the JSON schema for ``actions.json``.
-
-.. literalinclude:: actions-schema.yml
- :language: YAML
deleted file mode 100644
--- a/taskcluster/docs/action-uis.rst
+++ /dev/null
@@ -1,87 +0,0 @@
-User Interface Considerations
-=============================
-
-The actions system decouples in-tree changes from user interface changes by
-taking advantage of graceful degradation. User interfaces, when presented with
-an unfamiliar action, fall back to a usable default behavior, and can later be
-upgraded to handle that action with a more refined approach.
-
-Default Behavior
-----------------
-
-Every user interface should support the following:
-
- * Displaying a list of actions relevant to each task, and displaying
- task-group tasks for the associated task-group.
-
- * Providing an opportuntity for the user to enter input for an action. This
- might be in JSON or YAML, or using a form auto-generated from the action's
- JSON-schema. If the action has no schema, this step should be skipped.
- The user's input should be validated against the schema.
-
- * For ``action.kind = 'task'``, rendering the template using the JSON-e
- library, using the variables described in :doc:`action-spec`.
-
- * Calling ``Queue.createTask`` with the resulting task, using the user's
- Taskcluster credentials. See the next section for some important
- security-related concerns.
-
-Creating Tasks
---------------
-
-When executing an action, a UI must ensure that the user is authorized to
-perform the action, and that the user is not being "tricked" into executing
-an unexpected action.
-
-To accomplish the first, the UI should create tasks with the user's Taskcluster
-credentials. Do not use credentials configured as part of the service itself!
-
-To accomplish the second, use the decision tasks's ``scopes`` property as the
-`authorizedScopes
-<https://docs.taskcluster.net/manual/design/apis/hawk/authorized-scopes>`_ for
-the ``Queue.createTask`` call. This prevents action tasks from doing anything
-the original decision task couldn't do.
-
-Specialized Behavior
---------------------
-
-The default behavior is too clumsy for day-to-day use for common actions. User
-interfaces may want to provide a more natural interface that still takes advantage
-of the actions system.
-
-Specialized Input
-.................
-
-A user interface may provide specialized input forms for specific schemas. The
-input generated from the form must conform to the schema.
-
-To ensure that the schema has not changed, implementers should do a deep
-comparison between a schema for which a hand-written form exists, and the
-schema required by the action. If the two differ, the default behavior should
-be used instead.
-
-Specialized Triggering
-......................
-
-A user interface may want to trigger a specific action using a dedicated UI
-element. For example, an "start interactive session" button might be placed
-next to each failing test in a list of tests.
-
-User interfaces should look for the desired action by name. The UI should check
-that there is exactly one matching action available for the given task or
-task-graph. If multiple actions match, the UI should treat that as an error
-(helping to avoid actions being surreptitiously replaced by similarly-named,
-malicious actions).
-
-Having discovered the task, the user interface has a choice in how to provide
-its input. It can use the "specialized input" approach outlined above, providing
-a customized form if the action's schema is recognized and gracefully degrading
-if not.
-
-But if the user interface is generating the input internally, it may instead
-validate that generated input against the action's schema as given, proceeding
-if validation succeeds. In this alternative, there is no need to do a deep
-comparison of the schema. This approach allows in-tree changes that introduce
-backward-compatible changes to the schema, without breaking support in user
-interfaces. Of course, if the changes are not backward-compatibile, breakage
-will ensue.
deleted file mode 100644
--- a/taskcluster/docs/actions-schema.yml
+++ /dev/null
@@ -1,197 +0,0 @@
-$schema: http://json-schema.org/draft-04/schema#
-id: https://hg.mozilla.org/mozilla-central/raw-file/tip/taskcluster/docs/actions-schema.yml
-title: Schema for Exposing Actions
-description: |
- This document specifies the schema for the `public/actions.json` used by
- _decision tasks_ to expose actions that can be triggered by end-users.
-
- For the purpose of this document the _consumer_ is the user-interface that
- displays task results to the end-user and allows end-users to trigger actions
- defined by `public/actions.json`. A _consumer_ might be Treeherder.
- The _end-user_ is a developer who is inspecting the results, and wish to
- trigger actions.
-type: object
-properties:
- version:
- enum: [1]
- type: integer
- variables:
- type: object
- description: |
- Mapping from variable name to constants that can be referenced using
- `{$eval: '<variable>'}` within the task templates defined for each action.
-
- This is useful for commonly used constants that are used in many task
- templates. Whether it's to reduce the size of the `public/actions.json`
- artifact by reuseing large constants, or simply to make it easier to
- write task templates by exposing additional variables.
-
- These will overwrite any builtin variables, such as `taskGroupId`,
- `input`, `taskId`, `task`, and any further variables that future
- backwards compatible iterations of this specifcation adds. Hence, you
- should avoid declaring variables such as `input`, as it will shadow the
- builtin `input` variable.
- additionalProperties: true
- actions:
- type: array
- description: |
- List of actions that can be triggered.
- items:
- type: object
- properties:
- name:
- type: string
- maxLength: 255
- description: |
- The name of this action. This is used by user interfaces to
- identify the action. For example, a retrigger button might look for
- an action with `name = "retrigger"`.
-
- Action names must be unique for a given task, or for a taskgroup,
- but the same name may be used for actions applying to disjoint sets
- of tasks. For example, it may be helpful to define different
- "retrigger" actions for build tasks `[{jobKind: 'build'}]` and test
- tasks `[{jobKind: 'test'}]`, and in this case only one such action
- would apply to any given task.
- title:
- type: string
- maxLength: 255
- description: |
- Title text to be displayed on the button or link triggering the action.
- description:
- type: string
- maxLength: 4096
- description: |
- Human readable description of the action in markdown.
- Can be displayed in tooltip, popup and/or dialog when triggering
- the action.
- kind:
- enum:
- - task
- description: |
- Specifies the kind of action this is.
-
- The `task` _action kind_ is triggered by creating a task, following
- a task template.
-
- Other kinds might be added in the future. Consumers should ignore
- all entries featuring a `kind` property they don't recognize.
- context:
- type: array
- default: []
- items:
- type: object
- additionalProperties:
- type: string
- maxLength: 4096
- title: tag-set
- description: |
- A set of key-value pairs specifying a _tag-set_.
- description: |
- The `context` property determines in what context the action is
- relevant. Thus, what context the action should be presented to the
- end-user.
-
- The `context` property contains a set of tag-sets. A _tag-set_ is a
- set of key-value pairs. A task is said satisfy a tag-set if
- `task.tags` is a super-set of the given tag-set. An action is
- relevant for a task if the task satisfies at-least one of
- the tag-sets.
-
- Hence, an action with `context: [{a: '1'}, {b: '2'}]` is relevant
- for any task with `task.tags.a = '1'` or `task.tags.b = '2'`.
- An action with `context: [{a: '1', b: '2'}]` is only relevant for
- tasks with `task.tags.a = '1'` and `task.tags.b = '2'`.
-
- This allows restrictions of what tasks an action is relevant for.
- For example some tasks might not support running under a debugger.
-
- The keen reader observes that actions with `context: [{}]` are
- relevant for all tasks. Conversely, we have that tasks with
- `context: []` are irrelevant for all tasks. We abuse this property
- and define actions with `context: []` to be relevant for the
- _task-group_ only.
-
- That is an action with `context: []` should not be display in the
- context-sensitive menu for a task, rather it should be display when
- selecting the entire task-group. Presentation details are left for
- consumer to decide.
-
- Notice that the `context` property is optional, but defined to have
- a default value `context: []`. Hence, if the `context` is not
- specified consumer should take this to mean `context: []` implying
- that the action is relevant to the task-group, rather than any
- subset of tasks.
- schema:
- $ref: http://json-schema.org/schema
- description: |
- JSON schema for input parameters to the `task` template property.
- Consumers shall offer a user-interface where end-users can enter
- values that satisfy this schema. Furthermore, consumers **must**
- validate enter values against the given schema before parameterizing
- the `task` template property and triggering the action.
-
- In practice it's encourage that consumers employ a facility that
- can generate HTML forms from JSON schemas. However, if certain
- schemas are particularly complicated or common, consumers may also
- hand-write a user-interface for collecting the input. In this case
- the consumer **must** do a deep comparison between the schema given
- in the action, and the schema for which a custom user-interface have
- been written, and fall-back to an auto-generated form if the schema
- doesn't match.
-
- It is assumed that the JSON schema `description` property will be
- rendered as markdown when displayed as documentation for end-users.
- Producers of `public/actions.json` is encouraged to provide a
- detailed explanation of the input parameters using these
- `description` properties. And consumers are *strongly* encouraged
- to render `description` values as markdown.
-
- The `schema` property is optional, and if not given the input for
- `task` template parameterization shall be `null`.
- task:
- type: object
- title: task template
- description: |
- Task template for triggering the action.
-
- When an action have been selected in the appropriate context and
- input satisfying the `schema` (if any) has been collected. The
- action is triggered by parameterizing the task template given in
- this property, and creating the resulting task.
-
- The template is an object that is parameterized using
- [JSON-e](https://github.com/taskcluster/json-e), with the above
- variables supplied as context.
-
- This allows for dumping `input` and `taskId` into environment
- variables for the task to be created. The following task template
- injects `input` and `taskId` as environment variables:
- ```json
- {
- "workerType": "my-worker",
- "payload": {
- "created": {"$fromNow": ""},
- "deadline": {"$fromNow": "1 hour 15 minutes"},
- "expiration": {"$fromNow": "14 days"},
- "image": "my-docker-image",
- "env": {
- "TASKID_TRIGGERED_FOR": "${taskId}",
- "INPUT_JSON": {"$json": {"$eval": "input"}}
- },
- ...
- },
- ...
- }
- ```
- additionalProperties: false
- required:
- - title
- - description
- - kind
- - task
-additionalProperties: false
-required:
- - version
- - actions
- - variables
--- a/taskcluster/docs/actions.rst
+++ b/taskcluster/docs/actions.rst
@@ -1,13 +1,14 @@
Actions
=======
-This section shows how to define an action in-tree such that it shows up in
-supported user interfaces like Treeherder.
+This document shows how to define an action in-tree such that it shows up in
+supported user interfaces like Treeherder. For details on interface between
+in-tree logic and external user interfaces, see `the actions.json spec`_.
At a very high level, the process looks like this:
* The decision task produces an artifact, ``public/actions.json``, indicating
what actions are available.
* A user interface (for example, Treeherder or the Taskcluster tools) consults
``actions.json`` and presents appropriate choices to the user, if necessary
@@ -15,14 +16,248 @@ At a very high level, the process looks
re-trigger a test case.
* The user interface follows the action description to carry out the action.
In most cases (``action.kind == 'task'``), that entails creating an "action
task", including the provided information. That action task is responsible
for carrying out the named action, and may create new sub-tasks if necessary
(for example, to re-trigger a task).
+Action Task Implementation
+==========================
-.. toctree::
+There are two options for defining actions: creating a callback action, or
+creating a custom action task. A callback action automatically defines an
+action task that will invoke a Python function of your devising.
+
+A custom action task is an arbitrary task definition that will be created
+directly. In cases where the callback would simply call ``queue.createTask``,
+a custom action task can be more efficient.
+
+Creating a Callback Action
+--------------------------
+A *callback action* is an action that calls back into in-tree logic. That is,
+you register the action with name, title, description, context, input schema and a
+python callback. When the action is triggered in a user interface,
+input matching the schema is collected, passed to a new task which then calls
+your python callback, enabling it to do pretty much anything it wants to.
+
+To create a new action you must create a file
+``taskcluster/taskgraph/actions/my-action.py``, that at minimum contains::
+
+ from registry import register_callback_action
+
+ @register_callback_action(
+ name='hello',
+ title='Say Hello',
+ symbol='hw', # Show the callback task in treeherder as 'hw'
+ description="Simple **proof-of-concept** callback action",
+ order=10000, # Order in which it should appear relative to other actions
+ )
+ def hello_world_action(parameters, input, task_group_id, task_id, task):
+ # parameters is an instance of taskgraph.parameters.Parameters
+ # it carries decision task parameters from the original decision task.
+ # input, task_id, and task should all be None
+ print "Hello was triggered from taskGroupId: " + taskGroupId
+
+The example above defines an action that is available in the context-menu for
+the entire task-group (result-set or push in Treeherder terminology). To create
+an action that shows up in the context menu for a task we would specify the
+``context`` parameter.
+
+
+Setting the Action Context
+..........................
+The context parameter should be a list of tag-sets, such as
+``context=[{"platform": "linux"}]``, which will make the task show up in the
+context-menu for any task with ``task.tags.platform = 'linux'``. Below is
+some examples of context parameters and the resulting conditions on
+``task.tags`` (tags used below are just illustrative).
+
+``context=[{"platform": "linux"}]``:
+ Requires ``task.tags.platform = 'linux'``.
+``context=[{"kind": "test", "platform": "linux"}]``:
+ Requires ``task.tags.platform = 'linux'`` **and** ``task.tags.kind = 'test'``.
+``context=[{"kind": "test"}, {"platform": "linux"}]``:
+ Requires ``task.tags.platform = 'linux'`` **or** ``task.tags.kind = 'test'``.
+``context=[{}]``:
+ Requires nothing and the action will show up in the context menu for all tasks.
+``context=[]``:
+ Is the same as not setting the context parameter, which will make the action
+ show up in the context menu for the task-group.
+ (i.e., the action is not specific to some task)
+
+The example action below will be shown in the context-menu for tasks with
+``task.tags.platform = 'linux'``::
+
+ from registry import register_callback_action
+
+ @register_callback_action(
+ name='retrigger',
+ title='Retrigger',
+ symbol='re-c', # Show the callback task in treeherder as 're-c'
+ description="Create a clone of the task",
+ order=1,
+ context=[{'platform': 'linux'}]
+ )
+ def retrigger_action(parameters, input, task_group_id, task_id, task):
+ # input will be None
+ print "Retriggering: {}".format(task_id)
+ print "task definition: {}".format(task)
+
+When the ``context`` parameter is set, the ``task_id`` and ``task`` parameters
+will provided to the callback. In this case the ``task_id`` and ``task``
+parameters will be the ``taskId`` and *task definition* of the task from whose
+context-menu the action was triggered.
+
+Typically, the ``context`` parameter is used for actions that operate on
+tasks, such as retriggering, running a specific test case, creating a loaner,
+bisection, etc. You can think of the context as a place the action should
+appear, but it's also very much a form of input the action can use.
+
+
+Specifying an Input Schema
+..........................
+In call examples so far the ``input`` parameter for the callbacks has been
+``None``. To make an action that takes input you must specify an input schema.
+This is done by passing a JSON schema as the ``schema`` parameter.
+
+When designing a schema for the input it is important to exploit as many of the
+JSON schema validation features as reasonably possible. Furthermore, it is
+*strongly* encouraged that the ``title`` and ``description`` properties in
+JSON schemas is used to provide a detailed explanation of what the input
+value will do. Authors can reasonably expect JSON schema ``description``
+properties to be rendered as markdown before being presented.
+
+The example below illustrates how to specify an input schema. Notice that while
+this example doesn't specify a ``context`` it is perfectly legal to specify
+both ``input`` and ``context``::
+
+ from registry import register_callback_action
- action-spec
- action-uis
- action-implementation
+ @register_callback_action(
+ name='run-all',
+ title='Run All Tasks',
+ symbol='ra-c', # Show the callback task in treeherder as 'ra-c'
+ description="**Run all tasks** that have been _optimized_ away.",
+ order=1,
+ input={
+ 'title': 'Action Options',
+ 'description': 'Options for how you wish to run all tasks',
+ 'properties': {
+ 'priority': {
+ 'title': 'priority'
+ 'description': 'Priority that should be given to the tasks',
+ 'type': 'string',
+ 'enum': ['low', 'normal', 'high'],
+ 'default': 'low',
+ },
+ 'runTalos': {
+ 'title': 'Run Talos'
+ 'description': 'Do you wish to also include talos tasks?',
+ 'type': 'boolean',
+ 'default': 'false',
+ }
+ },
+ 'required': ['priority', 'runTalos'],
+ 'additionalProperties': False,
+ },
+ )
+ def retrigger_action(parameters, input, task_group_id, task_id, task):
+ print "Create all pruned tasks with priority: {}".format(input['priority'])
+ if input['runTalos']:
+ print "Also running talos jobs..."
+
+When the ``schema`` parameter is given the callback will always be called with
+an ``input`` parameter that satisfies the previously given JSON schema.
+It is encouraged to set ``additionalProperties: false``, as well as specifying
+all properties as ``required`` in the JSON schema. Furthermore, it's good
+practice to provide ``default`` values for properties, as user interface generators
+will often take advantage of such properties.
+
+Once you have specified input and context as applicable for your action you can
+do pretty much anything you want from within your callback. Whether you want
+to create one or more tasks or run a specific piece of code like a test.
+
+Conditional Availability
+........................
+The decision parameters ``taskgraph.parameters.Parameters`` passed to
+the callback are also available when the decision task generates the list of
+actions to be displayed in the user interface. When registering an action
+callback the ``availability`` option can be used to specify a callable
+which, given the decision parameters, determines if the action should be available.
+The feature is illustrated below::
+
+ from registry import register_callback_action
+
+ @register_callback_action(
+ name='hello',
+ title='Say Hello',
+ symbol='hw', # Show the callback task in treeherder as 'hw'
+ description="Simple **proof-of-concept** callback action",
+ order=2,
+ # Define an action that is only included if this is a push to try
+ available=lambda parameters: parameters.get('project', None) == 'try',
+ )
+ def try_only_action(parameters, input, task_group_id, task_id, task):
+ print "My try-only action"
+
+Properties of ``parameters`` are documented in the
+:doc:`parameters section <parameters>`. You can also examine the
+``parameters.yml`` artifact created by decisions tasks.
+
+
+Creating a Custom Action Task
+------------------------------
+
+It is possible to define an action that doesn't take a callback. Instead, you'll
+then have to provide a task template. For details on how the task template
+language works refer to `the actions.json spec`_, the example below illustrates
+how to create such an action::
+
+ from registry import register_task_action
+
+ @register_task_action(
+ name='retrigger',
+ title='Retrigger',
+ description="Create a clone of the task",
+ order=1,
+ context=[{'platform': 'linux'}],
+ input={
+ 'title': 'priority'
+ 'description': 'Priority that should be given to the tasks',
+ 'type': 'string',
+ 'enum': ['low', 'normal', 'high'],
+ 'default': 'low',
+ },
+ )
+ def task_template_builder(parameters):
+ # The task template builder may return None to signal that the action
+ # isn't available.
+ if parameters.get('project', None) != 'try':
+ return None
+ return {
+ 'created': {'$fromNow': ''},
+ 'deadline': {'$fromNow': '1 hour'},
+ 'expires': {'$fromNow': '14 days'},
+ 'provisionerId': '...',
+ 'workerType': '...',
+ 'priority': '${input}',
+ 'payload': {
+ 'command': '...',
+ 'env': {
+ 'TASK_DEFINITION': {'$json': {'eval': 'task'}}
+ },
+ ...
+ },
+ # It's now your responsibility to include treeherder routes, as well
+ # additional metadata for treeherder in task.extra.treeherder.
+ ...
+ },
+
+This kind of action is useful for creating simple derivative tasks, but is
+limited by the expressiveness of the template language. On the other hand, it
+is more efficient than an action callback as it does not involve an
+intermediate action task before creating the task the user requested.
+
+For further details on the template language, see `the actions.json spec`_.
+
+.. _the actions.json spec: https://docs.taskcluster.net/manual/tasks/actions/spec