Hooks for jobs and providers¶
Information
This reference documentation applies to all channel handlers and provider plugins part of OpenTestFactory. Externally provided channel handlers and provider plugins may or may not support hooks.
If, as a plugin writer you are using the opentf-toolkit
package, your channel handlers
and provider plugins support this configuration.
Hooks define steps that run before and/or after a specific event occurs.
Those steps are regular steps. For more information about step syntax, see “Workflow syntax for OpenTestFactory orchestrator.”
Events that trigger hooks are job setups, job teardowns, and function calls.
Events¶
Jobs setup events¶
A channel: setup
event occurs before the workspace is prepared:
channel: setup
By default, each time a job initiates on an execution environment, an empty workspace is configured and reserved for the job. This workspace is then discarded when the job is completed.
The channel: setup
event provides a mechanism to tailor the process of workspace preparation.
Hooks triggered by this event can force the use of a specific workspace and configure it.
Their before
steps run before the workspace is prepared. Their after
steps run after
the workspace is prepared but before the job’s first step run.
A specific use-workspace: {path}
step is allowed in the before
steps. It sets the
workspace path. If multiple use-workspace
steps are defined, the last one is used. When
the workspace path is explicitly set, no attempt is made to clean its content. It is up to
the hook to ensure that the workspace is properly prepared.
Note
If the workspace path is explicitly set, its content will be preserved after the job ends.
Jobs teardown events¶
A channel: teardown
event occurs after a job ends and before the workspace is deleted:
channel: teardown
Hooks triggered by this event can prevent the workspace deletion and can refine the cleanup operations.
Their before
steps run before the workspace is cleaned up. Their after
steps run after
the workspace is cleaned up.
A specific keep-workspace: {bool}
step is allowed in the before
steps. It prevents
the workspace from being deleted if the value evaluates to true
. If multiple
keep-workspace
steps are defined, the last one is used.
Note
If the workspace path was explicitly set, its content will be preserved even if
keep-workspace
is not specified or set to false
.
Functions events¶
Whenever a function prefix/name@version
is called in a workflow the following event occurs:
categoryPrefix: prefix
category: name
categoryVersion: version
Hooks triggered by this event allow you to customize the function call.
Their before
steps run before the function is called. Their after
steps run after
the function is called.
When defining the events that trigger a hook, you can omit the categoryVersion
specifier.
That way, all versions of the function will trigger the hook.
There must be at least one of category
or categoryPrefix
specified. It can be the _
placeholder (in which case all names or prefixes trigger the hook).
Scope¶
Hooks can be defined in a channel handler or provider plugin configuration file, or directly in a workflow.
Hooks defined in a channel handler or provider plugin configuration file or in a file referred
to by the {handler}_CHANNEL_HOOKS
or {provider_name}_PROVIDER_HOOKS
environment variable
only apply to jobs or functions handled by the plugin.
Hooks defined in a workflow only apply to jobs and functions defined or used in the workflow.
Sequence¶
The hooks
sections define an ordered list of hooks. Whenever an event that allows for hooks
occurs, relevant hooks are tested in order. All hooks that match are applied.
If two or more hooks match, the before
blocks are added in order and the after
blocks are added in reverse order:
before_steps from workflow-defined hooks
before_steps from {provider or handler}-defined hook 1
before_steps from {provider or handler}-defined hook 2
steps from event
after_steps from {provider or handler}-defined hook 2
after_steps from {provider or handler}-defined hook 1
after_steps from workflow-defined hooks
Mandatory and optional sections¶
A hook must have at least a name
and events
section and at least a before
or an after
section (it may have both). It may have an if
section. Those additional sections may be empty
or omitted if not used.
hooks:
- name: mona
events:
- ...
if:
before:
- ...
after:
- ...
Important
If the if
conditional is omitted, if: success()
is assumed. That is, the hook is
applied if and only if the job is in success (that is, all previous steps were either
successful or were carrying a continue-on-error: true
annotation).
Examples¶
Job hooks¶
In the following examples, you will define a job hook that keeps the workspace used for a job if the job fails.
The first example defines job hooks at the channel handler level. This configuration should be done when you deploy the orchestrator. For more information about this configuration, see “Agent channel plugin.”
The second example defines the job hook in a workflow.
Defining job hooks using a definition file¶
Tip
If the content of the referred file changes, the hooks definitions used by the Agent channel plugin will change accordingly. You do not need to restart the orchestrator.
You can provide a separate file for the hooks definitions when you deploy the orchestrator.
This file can have any name, as long as it is accessible from your plugin and the specified
AGENTCHANNEL_CHANNEL_HOOKS
environment variable refers to it:
AGENTCHANNEL_CHANNEL_HOOKS=/app/hooks/channel_hooks.yaml
The hooks definition file is as follows:
hooks:
- name: keep workspace on failure
if: always()
events:
- channel: teardown
before:
- keep-workspace: true
if: failure()
- run: echo hook
if: always()
Defining job hooks in a workflow¶
You can also define hooks directly in your workflow. In this case, they will apply only for the jobs defined or generated in the workflow.
metadata:
name: job hooks demo
hooks:
- name: keep workspace on failure
if: always()
events:
- channel: teardown
before:
- keep-workspace: true
if: failure()
- run: echo hook
if: always()
jobs:
my_job:
runs-on: windows
steps:
- run: echo Hi there
- run: ohno
Observable effects¶
Assuming the following workflow (or the one given in the ‘Defining job hooks in a workflow’ section if you are trying hooks defined in a workflow):
metadata:
name: job hooks demo
jobs:
my_job:
runs-on: windows
steps:
- run: echo Hi there
- run: ohno
If there is no ohno
command on the agent, the my_job
job will fail. The keep
workspace on failure
hook will be triggered and will prevent the workspace from being
deleted. The echo hook
step will be executed and its output will be displayed in the
job logs:
Workflow 1c46de26-25df-4a26-86dd-5e98d02569ad is running.
Workflow hooks demo
(running in namespace 'default')
[2023-06-22T16:46:50] [job ...] Requesting execution environment providing windows in namespace 'default' for job 'my_job'
[2023-06-22T16:46:50] [job ...] Running command: echo Hi there
[2023-06-22T16:46:53] [job ...] Running command: ohno
[2023-06-22T16:46:53] [job ...] Hi there
[2023-06-22T16:46:53] [job ...] 'ohno' n'est pas reconnu en tant que commande interne
[2023-06-22T16:46:53] [job ...] ou externe, un programme exécutable ou un fichier de commandes.
[2023-06-22T16:46:53] [job ...] Status code was: 1
[2023-06-22T16:46:53] [job ...] Running command: echo hook
[2023-06-22T16:46:53] [job ...] hook
[2023-06-22T16:46:53] [job ...] ERROR: At least one step in job 6ca11248-a555-4a77-a186-d89d9958df04 returned a non-zero value.
[2023-06-22T16:46:53] [job ...] Releasing execution environment for job 'my_job'
[2023-06-22T16:46:53] [job ...] Keeping workspace 'C:\Users\me\work\6ca11248-a555-4a77-a186-d89d9958df04' on execution environment
Workflow failed.
Provider hooks¶
In the following examples, you will define hooks for Cucumber functions.
The first example define hooks at the provider level. This configuration should be done when you deploy the orchestrator. Please see “Common provider settings” for more information.
The second example defines hooks in a workflow.
Defining provider hooks using a definition file¶
Note
This is the recommended way to define provider hooks.
Tip
If the content of the referred file changes, the hooks definitions used by the Cucumber provider plugin will change accordingly. You do not need to restart the provider plugin.
You can provide a separate file for the hooks definitions when you deploy the orchestrator.
This file can have any name, as long as it is accessible from your plugin and the specified
CUCUMBER_PROVIDER_HOOKS
environment variable refers to it:
CUCUMBER_PROVIDER_HOOKS=/app/hooks/cucumber_hooks.yaml
The hooks definition is as follows:
hooks:
- name: my hook
events:
- categoryPrefix: cucumber
category: cucumber
if: (contains(inputs.reporters, 'junit')) && (runner.os == 'windows')
before:
- run: echo hello windows
- run: del foobar.html
after:
- run: echo ::attach::foobar.html
- run: cleanup
if: always()
- name: my other hook
events:
- category: _
after:
- uses: actions/delete-file
with:
path: foo/bar
Defining functions hooks in a workflow¶
Finally, you can define hooks directly in your workflow:
metadata:
name: hooks demo
hooks:
- name: my hook
events:
- categoryPrefix: cucumber
category: cucumber
if: (contains(inputs.reporters, 'junit')) && (runner.os == 'windows')
before:
- run: echo hello windows
- run: del foobar.html
after:
- run: echo ::attach::foobar.html
- run: cleanup
if: always()
- name: my other hook
events:
- category: cucumber # if we were using the '_' placeholder, the hook
# would be triggered by all functions called in the
# workflow
after:
- uses: actions/delete-file
with:
path: foo/bar
jobs:
my_job:
runs-on: windows
steps:
- run: echo Hi there
- uses: cucumber/cucumber@v1
with:
reporters: [foo, junit]
- run: echo Bye
my_second_job:
runs-on: windows
steps:
- uses: cucumber/params@v1
Observable effects¶
Assuming the following workflow (if the hooks are defined at the provider level):
Note
Use the workflow example given in the ‘Defining functions hooks in a workflow’ above if you want to define the hooks in the workflow itself.
metadata:
name: hooks demo
jobs:
my_job:
runs-on: windows
steps:
- run: echo Hi there
- uses: cucumber/cucumber@v1
with:
reporters: [foo, junit]
- run: echo Bye
my_second_job:
runs-on: windows
steps:
- uses: cucumber/params@v1
The my_job
job will execute the following steps, in order:
- run: echo Hi there
- run: hello windows # added by 'my hook'
- run: del foobar.html # added by 'my hook'
- run: <what cucumber/cucumber does>
- run: <what actions/delete-file does> # added by 'my other hook'
- run: echo ::attach::foobar.html # added by 'my hook'
- run: cleanup # added by 'my hook'
If Cucumber returns a non-zero status code, the actions/delete-file
and echo ::attach::
steps will be skipped, but the cleanup
one will run nonetheless, as it includes an
if: always()
clause.
The my_second_job
job will execute the following steps, in order:
- run: <what cucumber/params does>
- run: <what actions/delete-file does> # added by 'my other hook'