Matrix Transforms#
The taskgraph.transforms.matrix transforms can be used to split a base
task into many subtasks based on a defined matrix.
These transforms are useful if you need to have many tasks that are very similar except for some small configuration differences.
Usage#
Add the transform to the transforms key in your kind.yml file:
transforms:
- taskgraph.transforms.matrix
# ...
Then create a matrix section in your task definition, e.g:
tasks:
test:
matrix:
os: ["win", "mac", "linux"]
# rest of task definition
This will split the test task into three; test-win, test-mac and
test-linux.
Matrix with Multiple Rows#
You can add as many rows as you like to the matrix, and every combination of tasks will be generated. For example, the following matrix:
tasks:
test:
matrix:
os: ["win", "mac", "linux"]
python: ["py312", "py311"]
# rest of task definition
Will generate these tasks:
test-win-py312test-win-py311test-mac-py312test-mac-py311test-linux-py312test-linux-py311
Note that the name of the tasks will be built based on the order of rows in the matrix.
Substituting Matrix Context into the Task Definition#
Of course these tasks will be identical, so you’ll want to change other parts of the task definition based on the matrix values.
Substituting Values in Yaml#
The simplest way to change a matrix task’s definition, is to use the built-in yaml substitution:
tasks:
test:
matrix:
os: ["win", "mac", "linux"]
description: Run {matrix[os]} tests
worker-type: {matrix[os]}-worker
Limiting Substitution#
By default, all keys and values in the task definition will be checked for
substitution parameters. But in some cases, it might be desirable to limit which
keys get substituted, such as when using the matrix transforms alongside
other transforms that perform substitution, such as the
task_context or
chunking transforms.
To limit the fields that will be evaluated for substitution, you can pass in the
substitution-fields config:
tasks:
test:
matrix:
substitution-fields: ["worker-type"]
os: ["win"]
description: Run {matrix[os]} tests
worker-type: {matrix[os]}-worker
In the example above, worker-type will evaluate to win-worker, whereas
the description will be the literal string Run {matrix[os]} tests. Dot
notation can be used in substitution-fields to limit substitution to some
sub configuration of the task definition.
Substituting Values in a Later Transform#
For more advanced cases, you may wish to use a later transform to act on the
result of the matrix evaluation. To accomplish this, the matrix transforms
will set a matrix attribute that contains all matrix values applicable to
the task.
For example, let’s say you have a kind.yml like:
transforms:
- taskgraph.transforms.matrix
- custom_taskgraph.transforms.custom
# ...
tasks:
test:
matrix:
os: ["win", "mac", "linux"]
Then in your custom.py transform file, you could add:
@transforms.add
def set_worker_type_and_description(config, tasks):
for task in tasks:
matrix = task["attributes"]["matrix"]
task["description"] = f"Run {matrix['os']} tests"
task["worker-type"] = f"{matrix['os']}-worker"
yield task
This example will yield the exact same result as the yaml example above, but it allows for more complex logic.
Excluding Matrix Combinations#
Sometimes you might not want to generate every possible combination of tasks,
and there may be some you wish to exclude. This can be accomplished using the
exclude config:
tasks:
test:
matrix:
os: ["win", "mac"]
arch: ["x86", "arm64"]
python: ["py312", "py311"]
exclude:
- os: mac
arch: x86
- os: win
arch: arm64
python: py311
This will cause all combinations where os == mac and arch == x86 to be
skipped, as well as the specific combination where os == win and arch ==
arm64 and python == py311. This means the following tasks will be generated:
test-win-x86-py311
test-win-x86-py312
test-win-arm64-py312
test-mac-arm64-py311
test-mac-arm64-py312
Customizing Task Names#
By default, the matrix transforms will append each matrix value to the
task’s name, separated by a dash. If some other format is desired, you can specify
the set-name config:
tasks:
test:
matrix:
set-name: "test-{matrix[os]}/{matrix[python]}"
os: ["win"]
python: ["py312"]
Instead of creating a task with the name test-win-py312, the name will be
test-win/py312.