Skip to content

Provider configuration

Information

This configuration documentation applies to all provider plugins part of OpenTestFactory. Externally provided provider plugins may or may not support this configuration.

If, as a provider plugin writer you are using the opentf-toolkit, your provider plugin supports this configuration.

A provider plugin configuration file may have a hooks section. This section, if defined, specifies steps that will run before and/or after a function is executed.

Those steps are regular steps. For more information about step syntax, see “Workflow syntax for OpenTestFactory orchestrator.”

Hooks defined in a provider plugin configuration file only applies to functions offered by the plugin.

The hooks section

The hooks section contains an ordered list of hooks. Whenever a function provided by the plugin is called, those 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-defined hook 1
    before_steps from provider-defined hook 2
      steps from function
    after_steps from provider-defined hook 2
  after_steps from provider-defined hook 1
after_steps from workflow-defined hooks

By default, hooks apply to all functions defined that match the specified events. It is possible to further limit their scopes by using the if conditional.

The events keyword allows to limit the scope of a hook by specifying the function it applies to. The value is used as follows:

  • categoryPrefix: only applies to functions having this prefix.
  • category: only applies to functions having this category.
  • categoryVersion: only applies to functions having this version.

If categoryPrefix is not specified, category is required.

categoryVersion can only be specified if at least category or categoryPrefix is specified.

If a hook applies to all categories, use _ as a placeholder, as in:

  events:
  - category: _

You can use the if conditional to prevent a hook from applying unless a condition is met. You can use any supported context and expression to create a conditional.

When you use expressions in an if conditional, you may omit the expression syntax (${{ }}) because the orchestrator automatically evaluates the if conditional as an expression. For more information, see “Context and expression syntax for OpenTestFactory workflows.”

If the expression evaluates to true, the before and/or after changes occur and the following entry, if present, is tested.

If the expression does not evaluate to true, the hook entry is skipped and the following entry, if present, is tested.

There must be a before block or an after block, or both. If present, they specify a non-empty list of steps.

You can define this hooks section in your configuration file, typically /app/conf/{provider_name}.yaml (in lower-case) or you can define a {provider_name}_PROVIDER_HOOKS environment variable (in upper-case) that refers to a file containing the hooks definition.

Hooks defined via the {provider_name}_PROVIDER_HOOKS environment variable replace the ones possibly defined in the provider’s configuration file.

You can find the list of providers part of the reference implementation in the Providers section. If no specific instructions is provided in your provider’s documentation, the provider name to use is the ‘short’ name used as the documentation title (for example, cucumber for the Cucumber provider plugin).

Examples

In the following examples you will define hooks for the Cucumber plugin.

Defining hooks in the provider configuration file

Add a hooks section in your provider configuration file for the Cucumber plugin (typically /app/conf/cucumber.yaml):

apiVersion: opentestfactory.org/v1beta1
kind: ProviderConfig
current-context: ...
contexts:
  ...
hooks:
  - name: my hook
    events:
    - categoryPrefix: cucumber
      category: cucumber
    if: ('junit' in inputs.reporters) && (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: _
    before:
    - uses: actions/delete-file
      with:
        path: foo/${{ inputs.yada }}/bar

Defining hooks using a separate definition file

Alternatively, you can provide a separate file for the hooks definition. This file can have any name, as long as it is accessible from your plugin and the CUCUMBER_PROVIDER_HOOKS environment variable is set to its path:

CUCUMBER_PROVIDER_HOOKS=/app/hooks/cucumber_hooks.yaml

The hooks definition is exactly as above:

/app/hooks/cucumber_hooks.yaml
hooks:
  - name: my hook
    events:
    - categoryPrefix: cucumber
      category: cucumber
    if: ('junit' in inputs.reporters) && (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: _
    before:
    - uses: actions/delete-file
      with:
        path: foo/${{ inputs.yada }}/bar

Observable effects

Assuming the following workflow:

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
- run: del foobar.html
- run: <what cucumber/cucumber does>
- run: echo ::attach::foobar.html
- run: cleanup

If Cucumber returns a non-zero status code, the echo ::attach:: step 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 actions/delete-file does>
- run: <what cucumber/params does>