| # Taskgraph Setup |
| |
| The taskgraph is built from a YAML file. This file has two top-level |
| properties: `components` and `tasks`. The full list of tasks is |
| defined by the `tasks` object; each task is an object with a single |
| property representing the task with the corresponding value an object |
| representing the task properties. Each task requires the following |
| top-level properties: |
| |
| * `provisionerId`: String. Name of Taskcluster provisioner |
| * `schedulerId`: String. Name of Taskcluster scheduler |
| * `deadline`: String. Time until the task expires |
| * `image`: String. Name of docker image to use for task |
| * `maxRunTime`: Number. Maximum time in seconds for which the task can |
| run. |
| * `artifacts`: Object. List of artifacts and directories to upload; see |
| Taskcluster documentation. |
| * `command`: String. Command to run. This is automatically wrapped in a |
| run_tc command |
| * `options`: Optional Object. Options to pass into run_tc |
| - xvfb: Boolean. Enable Xvfb for run |
| - oom-killer: Boolean. Enable xvfb for run |
| - hosts: Boolean. Update hosts file with wpt hosts before run |
| - install-certificates: Boolean. Install wpt certs into OS |
| certificate store for run |
| - browser: List. List of browser names for run |
| - channel: String. Browser channel for run |
| * `trigger`: Object. Conditions on which to consider task. One or more |
| of following properties: |
| - branch: List. List of branch names on which to trigger. |
| - pull-request: No value. Trigger for pull request actions |
| * `schedule-if`: Optional Object. Conditions on which task should be |
| scheduled given it meets the trigger conditions. |
| - `run-job`: List. Job names for which this task should be considered, |
| matching the output from `./wpt test-jobs` |
| * `env`: Optional Object. Environment variables to set when running task. |
| * `depends-on`: Optional list. List of task names that must be complete |
| before the current task is scheduled. |
| * `description`: String. Task description. |
| * `name`: Optional String. Name to use for the task overriding the |
| property name. This is useful in combination with substitutions |
| described below. |
| * `download-artifacts`: Optional Object. An artifact to download from |
| a task that this task depends on. This has the following properties: |
| - `task` - Name of the task producing the artifact |
| - `glob` - A glob pattern for the filename of the artifact |
| - `dest` - A directory reltive to the home directory in which to place |
| the artifact |
| - `extract` - Optional. A boolean indicating whether an archive artifact |
| should be extracted in-place. |
| |
| ## Task Expansions |
| |
| Using the above syntax it's possble to describe each task |
| directly. But typically in a taskgraph there are many common |
| properties between tasks so it's tedious and error prone to repeat |
| information that's common to multiple tasks. Therefore the taskgraph |
| format provides several mechanisms to reuse partial task definitions |
| across multiple tasks. |
| |
| ### Components |
| |
| The other top-level property in the taskgraph format is |
| `components`. The value of this property is an object containing named |
| partial task definitions. Each task definition may contain a property called |
| `use` which is a list of components to use as the basis for the task |
| definition. The components list is evaluated in order. If a property |
| is not previously defined in the output it is added to the output. If |
| it was previously defined, the value is updated according to the type: |
| * Strings and numbers are replaced with a new value |
| * Lists are extended with the additional values |
| * Objects are updated recursively following the above rules |
| This means that types must always match between components and the |
| final value. |
| |
| For example |
| ``` |
| components: |
| example-1: |
| list_prop: |
| - first |
| - second |
| object_prop: |
| key1: value1 |
| key2: base_value |
| example-2: |
| list_prop: |
| - third |
| - fourth |
| object_prop: |
| key3: |
| - value3-1 |
| |
| tasks: |
| - example-task: |
| use: |
| - example-1 |
| - example-2 |
| object_prop: |
| key2: value2 |
| key3: |
| - value3-2 |
| ``` |
| |
| will evaluate to the following task: |
| |
| ``` |
| example-task: |
| list_prop: |
| - first |
| - second |
| - third |
| - fourth |
| object_prop: |
| key1: value1 |
| key2: value2 |
| key3: |
| - value3-1 |
| - value3-2 |
| ``` |
| |
| Note that components cannot currently define `use` properties of their own. |
| |
| ## Substitutions |
| |
| Components and tasks can define a property `vars` that holds variables |
| which are later substituted into the task definition using the syntax |
| `${vars.property-name}`. For example: |
| |
| ``` |
| components: |
| generic-component: |
| prop: ${vars.value} |
| |
| tasks: |
| - first: |
| use: |
| - generic-component |
| vars: |
| value: value1 |
| - second: |
| use: |
| - generic-component |
| vars: |
| value: value2 |
| ``` |
| |
| Results in the following tasks: |
| |
| ``` |
| first: |
| prop: value1 |
| second: |
| prop: value2 |
| ``` |
| |
| ## Maps |
| |
| Instead of defining a task directly, an item in the tasks property may |
| be an object with a single property `$map`. This object itself has two |
| child properties; `for` and `do`. The value of `for` is a list of |
| objects, and the value of `do` is either an object or a list of |
| objects. For each object in the `for` property, a set of tasks is |
| created by taking a copy of that object for each task in the `do` |
| property, updating the object with the properties from the |
| corresponding `do` object, using the same rules as for components |
| above, and then processing as for a normal task. `$map` rules can also |
| be nested. |
| |
| Note: Although `$map` shares a name with the `$map` used in json-e |
| (used. in `.taskcluster.yml`), the semantics are different. |
| |
| For example |
| |
| ``` |
| components: {} |
| tasks: |
| $map: |
| for: |
| - vars: |
| example: value1 |
| - vars: |
| example: value2 |
| do: |
| example-${vars.example} |
| prop: ${vars.example} |
| ``` |
| |
| Results in the tasks |
| |
| ``` |
| example-value1: |
| prop: value1 |
| example-value2: |
| prop: value2 |
| ``` |
| |
| Note that in combination with `$map`, variable substitutions are |
| applied *twice*; once after the `$map` is evaluated and once after the |
| `use` statements are evaluated. |
| |
| ## Chunks |
| |
| A common requirements for tasks is that they are "chunked" into N |
| partial tasks. This is handled specially in the syntax. A top level |
| property `chunks` can be used to define the number of individual |
| chunks to create for a specific task. Each chunked task is created |
| with a `chunks` property set to an object containing an `id` property |
| containing the one-based index of the chunk an a `total` property |
| containing the total number of chunks. These can be substituted into |
| the task definition using the same syntax as for `vars` above |
| e.g. `${chunks.id}`. Note that because task names must be unique, it's |
| common to specify a `name` property on the task that will override the |
| property name e.g. |
| |
| ``` |
| components: {} |
| tasks: |
| - chunked-task: |
| chunks:2 |
| command: "task-run --chunk=${chunks.id} --totalChunks=${chunks.total}" |
| name: task-chunk-${chunks.id} |
| ``` |
| |
| creates tasks: |
| |
| ``` |
| task-chunk-1: |
| command: "task-run --chunk=1 --totalChunks=2" |
| task-chunk-2: |
| command: "task-run --chunk=2 --totalChunks=2" |
| ``` |
| |
| # Overall processing model |
| |
| The overall processing model for tasks is as follows: |
| * Evaluate maps |
| * Perform subsitutions |
| * Evaluate use statements |
| * Expand chunks |
| * Perform subsitutions |
| |
| At each point after maps are evaluated tasks must have a unique name. |