StepActions
Overview
StepActionsis a stable feature.
A StepAction is the reusable and scriptable unit of work that is performed by a Step.
A Step is not reusable, the work it performs is reusable and referenceable. Steps are in-lined in the Task definition and either perform work directly or perform a StepAction. A StepAction cannot be run stand-alone (unlike a TaskRun or a PipelineRun). It has to be referenced by a Step. Another way to think about this is that a Step is not composed of StepActions (unlike a Task being composed of Steps and Sidecars). Instead, a Step is an actionable component, meaning that it has the ability to refer to a StepAction. The author of the StepAction must be able to compose a Step using a StepAction and provide all the necessary context (or orchestration) to it.
Configuring a StepAction
A StepAction definition supports the following fields:
- Required
apiVersion- Specifies the API version. For example,tekton.dev/v1alpha1.kind- Identifies this resource object as aStepActionobject.metadata- Specifies metadata that uniquely identifies theStepActionresource object. For example, aname.spec- Specifies the configuration information for thisStepActionresource object.image- Specifies the image to use for theStep.- The container image must abide by the container contract.
- Optional
command- cannot be used at the same time as using
script.
- cannot be used at the same time as using
argsscript- cannot be used at the same time as using
command.
- cannot be used at the same time as using
envparamsresultsworkingDirsecurityContextvolumeMountsdescription
The example below demonstrates the use of most of the above-mentioned fields:
apiVersion: tekton.dev/v1beta1
kind: StepAction
metadata:
name: example-stepaction-name
spec:
env:
- name: HOME
value: /home
image: ubuntu
command: ["ls"]
args: ["-lh"]
Declaring Parameters
Like with Tasks, a StepAction must declare all the parameters that it uses. The same rules for Parameter name, type (including object, array and string) apply as when declaring them in Tasks. A StepAction can also provide default value to a Parameter.
Parameters are passed to the StepAction from its corresponding Step referencing it.
apiVersion: tekton.dev/v1beta1
kind: StepAction
metadata:
name: stepaction-using-params
spec:
params:
- name: gitrepo
type: object
properties:
url:
type: string
commit:
type: string
- name: flags
type: array
- name: outputPath
type: string
default: "/workspace"
image: some-git-image
args: [
"-url=$(params.gitrepo.url)",
"-revision=$(params.gitrepo.commit)",
"-output=$(params.outputPath)",
"$(params.flags[*])",
]
🌱
paramscannot be directly used in ascriptinStepActions. Directly substitutingparamsinscriptsmakes the workload prone to shell attacks. Therefore, we do not allow direct usage ofparamsinscriptsinStepActions. Instead, rely on passingparamstoenvvariables and reference them inscripts. We cannot do the same forinlined-stepsbecause it breaksv1 APIcompatibility for existing users.
Passing Params to StepAction
A StepAction may require params. In this case, a Task needs to ensure that the StepAction has access to all the required params.
When referencing a StepAction, a Step can also provide it with params, just like how a TaskRun provides params to the underlying Task.
apiVersion: tekton.dev/v1
kind: Task
metadata:
name: step-action
spec:
params:
- name: param-for-step-action
description: "this is a param that the step action needs."
steps:
- name: action-runner
ref:
name: step-action
params:
- name: step-action-param
value: $(params.param-for-step-action)
Note: If a Step declares params for an inlined Step, it will also lead to a validation error. This is because an inlined Step gets its params from the TaskRun.
Parameter Substitution Precedence
When applying parameters to a StepAction, the substitutions are applied in the following order:
- TaskRun parameter values in step parameters
- Step-provided parameter values
- Default values that reference other parameters
- Simple default values
- Step result references
This order ensures that:
- TaskRun parameters are available for step parameter substitution
- Step-provided values take precedence over defaults
- Parameter references in defaults are resolved before simple defaults
- Step result references are resolved last to allow referencing results from previous steps
Emitting Results
A StepAction also declares the results that it will emit.
apiVersion: tekton.dev/v1alpha1
kind: StepAction
metadata:
name: stepaction-declaring-results
spec:
results:
- name: current-date-unix-timestamp
description: The current date in unix timestamp format
- name: current-date-human-readable
description: The current date in human readable format
image: bash:latest
script: |
#!/usr/bin/env bash
date +%s | tee $(results.current-date-unix-timestamp.path)
date | tee $(results.current-date-human-readable.path)
It is possible that a StepAction with Results is used multiple times in the same Task or multiple StepActions in the same Task produce Results with the same name. Resolving the Result names becomes critical otherwise there could be unexpected outcomes. The Task needs to be able to resolve these Result names clashes by mapping it to a different Result name. For this reason, we introduce the capability to store results on a Step level.
StepActions can also emit Results to $(step.results.<resultName>.path).
apiVersion: tekton.dev/v1alpha1
kind: StepAction
metadata:
name: stepaction-declaring-results
spec:
results:
- name: current-date-unix-timestamp
description: The current date in unix timestamp format
- name: current-date-human-readable
description: The current date in human readable format
image: bash:latest
script: |
#!/usr/bin/env bash
date +%s | tee $(step.results.current-date-unix-timestamp.path)
date | tee $(step.results.current-date-human-readable.path)
Results from the above StepAction can be fetched by the Task or in another Step/StepAction via $(steps.<stepName>.results.<resultName>).
Fetching Emitted Results from StepActions
A Task can fetch Results produced by the StepActions (i.e. only Results emitted to $(step.results.<resultName>.path), NOT $(results.<resultName>.path)) using variable replacement syntax. We introduce a field to Task Results called Value whose value can be set to the variable $(steps.<stepName>.results.<resultName>).
apiVersion: tekton.dev/v1
kind: Task
metadata:
name: task-fetching-results
spec:
results:
- name: git-url
description: "url of git repo"
value: $(steps.git-clone.results.url)
- name: registry-url
description: "url of docker registry"
value: $(steps.kaniko.results.url)
steps:
- name: git-clone
ref:
name: clone-step-action
- name: kaniko
ref:
name: kaniko-step-action
Results emitted to $(step.results.<resultName>.path) are not automatically available as TaskRun Results. The Task must explicitly fetch it from the underlying Step referencing StepActions.
For example, lets assume that in the previous example, the “kaniko” StepAction also produced a Result named “digest”. In that case, the Task should also fetch the “digest” from “kaniko” Step.
apiVersion: tekton.dev/v1
kind: Task
metadata:
name: task-fetching-results
spec:
results:
- name: git-url
description: "url of git repo"
value: $(steps.git-clone.results.url)
- name: registry-url
description: "url of docker registry"
value: $(steps.kaniko.results.url)
- name: digest
description: "digest of the image"
value: $(steps.kaniko.results.digest)
steps:
- name: git-clone
ref:
name: clone-step-action
- name: kaniko
ref:
name: kaniko-step-action
Passing Results between Steps
StepResults (i.e. results written to $(step.results.<result-name>.path), NOT $(results.<result-name>.path)) can be shared with following steps via replacement variable $(steps.<step-name>.results.<result-name>).
Pipeline supports two new types of results and parameters: array []string and object map[string]string.
| Result Type | Parameter Type | Specification | enable-api-fields |
|---|---|---|---|
| string | string | $(steps.<step-name>.results.<result-name>) |
stable |
| array | array | $(steps.<step-name>.results.<result-name>[*]) |
alpha or beta |
| array | string | $(steps.<step-name>.results.<result-name>[i]) |
alpha or beta |
| object | string | $(tasks.<task-name>.results.<result-name>.key) |
alpha or beta |
Note: Whole Array Results (using star notation) cannot be referred in script and env.
The example below shows how you could pass step results from a step into following steps, in this case, into a StepAction.
apiVersion: tekton.dev/v1
kind: TaskRun
metadata:
name: step-action-run
spec:
TaskSpec:
steps:
- name: inline-step
results:
- name: result1
type: array
- name: result2
type: string
- name: result3
type: object
properties:
IMAGE_URL:
type: string
IMAGE_DIGEST:
type: string
image: alpine
script: |
echo -n "[\"image1\", \"image2\", \"image3\"]" | tee $(step.results.result1.path)
echo -n "foo" | tee $(step.results.result2.path)
echo -n "{\"IMAGE_URL\":\"ar.com\", \"IMAGE_DIGEST\":\"sha234\"}" | tee $(step.results.result3.path)
- name: action-runner
ref:
name: step-action
params:
- name: param1
value: $(steps.inline-step.results.result1[*])
- name: param2
value: $(steps.inline-step.results.result2)
- name: param3
value: $(steps.inline-step.results.result3[*])
Note: Step Results can only be referenced in a Step's/StepAction's env, command and args. Referencing in any other field will throw an error.
Declaring WorkingDir
You can declare workingDir in a StepAction:
apiVersion: tekton.dev/v1alpha1
kind: StepAction
metadata:
name: example-stepaction-name
spec:
image: gcr.io/tekton-releases/github.com/tektoncd/pipeline/cmd/git-init:latest
workingDir: /workspace
script: |
# clone the repo
...
The Task using the StepAction has more context about how the Steps have been orchestrated. As such, the Task should be able to update the workingDir of the StepAction so that the StepAction is executed from the correct location.
The StepAction can parametrize the workingDir and work relative to it. This way, the Task does not really need control over the workingDir, it just needs to pass the path as a parameter.
apiVersion: tekton.dev/v1alpha1
kind: StepAction
metadata:
name: example-stepaction-name
spec:
image: ubuntu
params:
- name: source
description: "The path to the source code."
workingDir: $(params.source)
Declaring SecurityContext
You can declare securityContext in a StepAction:
apiVersion: tekton.dev/v1alpha1
kind: StepAction
metadata:
name: example-stepaction-name
spec:
image: gcr.io/tekton-releases/github.com/tektoncd/pipeline/cmd/git-init:latest
securityContext:
runAsUser: 0
script: |
# clone the repo
...
Note that the securityContext from StepAction will overwrite the securityContext from TaskRun.
Declaring VolumeMounts
You can define VolumeMounts in StepActions. The name of the VolumeMount MUST be a single reference to a string Parameter. For example, $(params.registryConfig) is valid while $(params.registryConfig)-foo and "unparametrized-name" are invalid. This is to ensure reusability of StepActions such that Task authors have control of which Volumes they bind to the VolumeMounts.
apiVersion: tekton.dev/v1alpha1
kind: StepAction
metadata:
name: myStep
spec:
params:
- name: registryConfig
- name: otherConfig
volumeMounts:
- name: $(params.registryConfig)
mountPath: /registry-config
- name: $(params.otherConfig)
mountPath: /other-config
image: ...
script: ...
Declaring description
The description field is an optional field that allows you to add a user-facing name to the step that may be used to populate a UI.
apiVersion: tekton.dev/v1
kind: StepAction
metadata:
name: myStep
spec:
description: my step
params: ...
volumeMounts: ...
image: ...
script: ...
Referencing a StepAction
StepActions can be referenced from the Step using the ref field, as follows:
apiVersion: tekton.dev/v1
kind: TaskRun
metadata:
name: step-action-run
spec:
taskSpec:
steps:
- name: action-runner
ref:
name: step-action
Upon resolution and execution of the TaskRun, the Status will look something like:
status:
completionTime: "2023-10-24T20:28:42Z"
conditions:
- lastTransitionTime: "2023-10-24T20:28:42Z"
message: All Steps have completed executing
reason: Succeeded
status: "True"
type: Succeeded
podName: step-action-run-pod
provenance:
featureFlags:
...
startTime: "2023-10-24T20:28:32Z"
steps:
- container: step-action-runner
imageID: docker.io/library/alpine@sha256:eece025e432126ce23f223450a0326fbebde39cdf496a85d8c016293fc851978
name: action-runner
terminationReason: Completed
terminated:
containerID: containerd://46a836588967202c05b594696077b147a0eb0621976534765478925bb7ce57f6
exitCode: 0
finishedAt: "2023-10-24T20:28:42Z"
reason: Completed
startedAt: "2023-10-24T20:28:42Z"
taskSpec:
steps:
- computeResources: {}
image: alpine
name: action-runner
If a Step is referencing a StepAction, it cannot contain the fields supported by StepActions. This includes:
imagecommandargsscriptenvvolumeMounts
Using any of the above fields and referencing a StepAction in the same Step is not allowed and will cause a validation error.
# This is not allowed and will result in a validation error
# because the image is expected to be provided by the StepAction
# and not inlined.
apiVersion: tekton.dev/v1
kind: TaskRun
metadata:
name: step-action-run
spec:
taskSpec:
steps:
- name: action-runner
ref:
name: step-action
image: ubuntu
Executing the above TaskRun will result in an error that looks like:
Error from server (BadRequest): error when creating "STDIN": admission webhook "validation.webhook.pipeline.tekton.dev" denied the request: validation failed: image cannot be used with Ref: spec.taskSpec.steps[0].image
When a Step is referencing a StepAction, it can contain the following fields:
computeResourcesworkspaces(Isolated workspaces)volumeDevicesimagePullPolicyonErrorstdoutConfigstderrConfigsecurityContextenvFromtimeoutrefparams
Using any of the above fields and referencing a StepAction is allowed and will not cause an error. For example, the TaskRun below will execute without any errors:
apiVersion: tekton.dev/v1
kind: TaskRun
metadata:
name: step-action-run
spec:
taskSpec:
steps:
- name: action-runner
ref:
name: step-action
params:
- name: step-action-param
value: hello
computeResources:
requests:
memory: 1Gi
cpu: 500m
timeout: 1h
onError: continue
Specifying Remote StepActions
A ref field may specify a StepAction in a remote location such as git.
Support for specific types of remote will depend on the Resolvers your
cluster’s operator has installed. For more information including a tutorial, please check resolution docs. The below example demonstrates referencing a StepAction in git:
apiVersion: tekton.dev/v1
kind: TaskRun
metadata:
generateName: step-action-run-
spec:
taskSpec:
steps:
- name: action-runner
ref:
resolver: git
params:
- name: url
value: https://github.com/repo/repo.git
- name: revision
value: main
- name: pathInRepo
value: remote_step.yaml
The default resolver type can be configured by the default-resolver-type field in the config-defaults ConfigMap (alpha feature). See additional-configs.md for details.
Feedback
Was this page helpful?