Task Context Transforms#
The taskgraph.transforms.task_context transform can be used to
resolve keys and/or substitute values into any field in a task with data
that is not known until taskgraph runs.
This data can be provided in a few ways, as described below.
Schema#
All tasks must conform to the task_context schema.
Usage#
from-parameters#
Context can be pulled from parameters that are provided to taskgraph.
First, add the transform to the transforms key in your kind.yml file:
transforms:
- taskgraph.transforms.task_context
# ...
Then create a task-context section in your task definition, e.g:
tasks:
build:
description:
by-foo:
bar: super special description for bar tasks
default: my description of {foo}
task-context:
from-parameters:
foo: foo
substitution-fields:
- description
When taskgraph is run the value of foo in the parameters it is provided
will be substituted into the description. For example, if the following parameters
are used:
foo: bar
…the description will end up with a value of “super special description for bar tasks”.
When foo is set to any other value (eg: bar) the description will end with the
default value with the value of foo substituted in (eg: my description of bar).
This pattern is often used to configure things vary based on how tasks are created. For example, the following can be used to adjust the scopes a task is given depending on the GitHub event that created the decision task:
tasks:
build:
task-context:
from-parameters:
tasks_for: tasks_for
substitution-fields:
- scopes
scopes:
by-tasks-for:
github-push:
- secrets:get:project/foo/api_token
default: []
When using from-parameters you may also provide an ordered list of keys to
look for in the parameters, with the first one found being used. For example,
with the this kind:
tasks:
build:
description: my description {foo}
task-context:
from-parameters:
foo:
- foo
- default
substitution-fields:
- description
…the description will bring in the value foo from the parameters if
present, or default otherwise.
from-object#
You may also specify context as direct keys and values in the task-context
configuration in from-object . This can be useful in kinds that define
most of their contents in task-defaults, but have some values that may
differ for various concrete tasks in the kind.
For example:
task-defaults:
description: my description {extra_desc}
task-context:
substitution-fields:
- description
tasks:
build1:
task-context:
from-object:
extra_desc: build1
build2:
task-context:
from-object:
extra_desc: build2
This will give build1 and build2 descriptions with their extra_desc
included while allowing them to share the rest of their task definition.
from-custom#
Context may be provided by custom providers, which must be registered prior to this transform being run. This allows the creation of context that is derived from parameters, code constants, or anything else accessible to taskgraph.
For example, you may have a custom context handler set-up in
taskcluster/my_taskgraph/custom_context.py:
NON_PRODUCTION_BRANCHES = ["maple", "pine"]
@custom_context("release-level")
def release_level_context(config, task):
# Despite being level 3, some branches are not truly considered "production"
# in the sense of creating releases that ship to users.
if config.params["level"] == "1" or config.params["project"] in NON_PRODUCTION_BRANCHES:
return "staging"
return "production"
In your register function you will need to ensure you import this module.
Eg: taskcluster/my_taskgraph/__init__.py:
def register(graph_config):
from my_taskgraph import custom_contexts # trigger custom task-context registration
Now you can use release-level as context in a kind:
task-defaults:
task-context:
from-custom:
- release-level
substitution-fields:
- scopes
scopes:
by-release-level:
staging:
- secrets:get:staging_creds
production:
- secrets:get:production_creds
from-file#
Context may also be provided from a defined yaml file. The provided file should usually only contain top level keys and values (eg: nested objects will not be interpolated - they will be substituted as text representations of the object).
For example, with this kind definition:
tasks:
build:
description: my description {foo}
task-context:
from-file: some_file.yaml
substitution-fields:
- description
And this in some_file.yaml:
foo: from a file
…description will end up with “my description from a file”.
Implicit Context#
Finally, the name of the task is added to the context implicitly. For example:
task-defaults:
description: run {name}
task-context:
substitution-fields:
- description
tasks:
foo: {}
bar: {}
This will evaluate the description correctly, even though there are no
task-context keys defined on the individual tasks.
Order of Operations & Precedence#
Keys will be resolved on substitution-fields first, then substitution
will be performed on the resolved value.
If the same key is found in multiple places the order of precedence is as
follows: from-parameters, from-object keys, from-custom providers, from-file and finally
implicit context.
That is to say: parameters will always override anything else.