Answer:
<!--
---
linkTitle: "Pipelines"
weight: 203
---
-->

# Pipelines

- [Pipelines](#pipelines)
  - [Overview](#overview)
  - [Configuring a `Pipeline`](#configuring-a-pipeline)
  - [Specifying `Workspaces`](#specifying-workspaces)
  - [Specifying `Parameters`](#specifying-parameters)
  - [Adding `Tasks` to the `Pipeline`](#adding-tasks-to-the-pipeline)
    - [Specifying Display Name](#specifying-displayname-in-pipelinetasks)
    - [Specifying Remote Tasks](#specifying-remote-tasks)
    - [Specifying `Pipelines` in `PipelineTasks`](#specifying-pipelines-in-pipelinetasks)
    - [Specifying `Parameters` in `PipelineTasks`](#specifying-parameters-in-pipelinetasks)
    - [Specifying `Matrix` in `PipelineTasks`](#specifying-matrix-in-pipelinetasks)
    - [Specifying `Workspaces` in `PipelineTasks`](#specifying-workspaces-in-pipelinetasks)
    - [Tekton Bundles](#tekton-bundles)
    - [Using the `runAfter` field](#using-the-runafter-field)
    - [Using the `retries` field](#using-the-retries-field)
    - [Using the `onError` field](#using-the-onerror-field)
    - [Produce results with `OnError`](#produce-results-with-onerror)
    - [Guard `Task` execution using `when` expressions](#guard-task-execution-using-when-expressions)
      - [Guarding a `Task` and its dependent `Tasks`](#guarding-a-task-and-its-dependent-tasks)
        - [Cascade `when` expressions to the specific dependent `Tasks`](#cascade-when-expressions-to-the-specific-dependent-tasks)
        - [Compose using Pipelines in Pipelines](#compose-using-pipelines-in-pipelines)
      - [Guarding a `Task` only](#guarding-a-task-only)
    - [Configuring the failure timeout](#configuring-the-failure-timeout)
  - [Using variable substitution](#using-variable-substitution)
    - [Using the `retries` and `retry-count` variable substitutions](#using-the-retries-and-retry-count-variable-substitutions)
  - [Using `Results`](#using-results)
    - [Passing one Task's `Results` into the `Parameters` or `when` expressions of another](#passing-one-tasks-results-into-the-parameters-or-when-expressions-of-another)
    - [Emitting `Results` from a `Pipeline`](#emitting-results-from-a-pipeline)
  - [Configuring the `Task` execution order](#configuring-the-task-execution-order)
  - [Adding a description](#adding-a-description)
  - [Adding `Finally` to the `Pipeline`](#adding-finally-to-the-pipeline)
    - [Specifying Display Name](#specifying-displayname-in-finally-tasks)
    - [Specifying `Workspaces` in `finally` tasks](#specifying-workspaces-in-finally-tasks)
    - [Specifying `Parameters` in `finally` tasks](#specifying-parameters-in-finally-tasks)
    - [Specifying `matrix` in `finally` tasks](#specifying-matrix-in-finally-tasks)
    - [Consuming `Task` execution results in `finally`](#consuming-task-execution-results-in-finally)
    - [Consuming `Pipeline` result with `finally`](#consuming-pipeline-result-with-finally)
    - [`PipelineRun` Status with `finally`](#pipelinerun-status-with-finally)
    - [Using Execution `Status` of `pipelineTask`](#using-execution-status-of-pipelinetask)
    - [Using Aggregate Execution `Status` of All `Tasks`](#using-aggregate-execution-status-of-all-tasks)
    - [Guard `finally` `Task` execution using `when` expressions](#guard-finally-task-execution-using-when-expressions)
      - [`when` expressions using `Parameters` in `finally` `Tasks`](#when-expressions-using-parameters-in-finally-tasks)
      - [`when` expressions using `Results` in `finally` 'Tasks`](#when-expressions-using-results-in-finally-tasks)
      - [`when` expressions using `Execution Status` of `PipelineTask` in `finally` `tasks`](#when-expressions-using-execution-status-of-pipelinetask-in-finally-tasks)
      - [`when` expressions using `Aggregate Execution Status` of `Tasks` in `finally` `tasks`](#when-expressions-using-aggregate-execution-status-of-tasks-in-finally-tasks)
    - [Known Limitations](#known-limitations)
      - [Cannot configure the `finally` task execution order](#cannot-configure-the-finally-task-execution-order)
  - [Using Custom Tasks](#using-custom-tasks)
    - [Specifying the target Custom Task](#specifying-the-target-custom-task)
    - [Specifying a Custom Task Spec in-line (or embedded)](#specifying-a-custom-task-spec-in-line-or-embedded)
    - [Specifying parameters](#specifying-parameters-1)
    - [Specifying matrix](#specifying-matrix)
    - [Specifying workspaces](#specifying-workspaces-1)
    - [Using `Results`](#using-results-1)
    - [Specifying `Timeout`](#specifying-timeout)
    - [Specifying `Retries`](#specifying-retries)
    - [Known Custom Tasks](#known-custom-tasks)
  - [Code examples](#code-examples)

## Overview

A `Pipeline` is a collection of `Tasks` that you define and arrange in a specific order
of execution as part of your continuous integration flow. Each `Task` in a `Pipeline`
executes as a `Pod` on your Kubernetes cluster. You can configure various execution
conditions to fit your business needs.

## Configuring a `Pipeline`

A `Pipeline` definition supports the following fields:

- Required:
  - [`apiVersion`][kubernetes-overview] - Specifies the API version, for example
    `tekton.dev/v1beta1`.
  - [`kind`][kubernetes-overview] - Identifies this resource object as a `Pipeline` object.
  - [`metadata`][kubernetes-overview] - Specifies metadata that uniquely identifies the
    `Pipeline` object. For example, a `name`.
  - [`spec`][kubernetes-overview] - Specifies the configuration information for
    this `Pipeline` object. This must include:
      - [`tasks`](#adding-tasks-to-the-pipeline) - Specifies the `Tasks` that comprise the `Pipeline`
        and the details of their execution.
- Optional:
  - [`params`](#specifying-parameters) - Specifies the `Parameters` that the `Pipeline` requires.
  - [`workspaces`](#specifying-workspaces) - Specifies a set of Workspaces that the `Pipeline` requires.
  - [`tasks`](#adding-tasks-to-the-pipeline):
      - [`name`](#adding-tasks-to-the-pipeline) - the name of this `Task` within the context of this `Pipeline`.
      - [`displayName`](#specifying-displayname-in-pipelinetasks) - a user-facing name of this `Task` within the context of this `Pipeline`.
      - [`description`](#adding-tasks-to-the-pipeline) - a description of this `Task` within the context of this `Pipeline`.
      - [`taskRef`](#adding-tasks-to-the-pipeline) - a reference to a `Task` definition.
      - [`taskSpec`](#adding-tasks-to-the-pipeline) - a specification of a `Task`.
      - [`runAfter`](#using-the-runafter-field) - Indicates that a `Task` should execute after one or more other
        `Tasks` without output linking.
      - [`retries`](#using-the-retries-field) - Specifies the number of times to retry the execution of a `Task` after
        a failure. Does not apply to execution cancellations.
      - [`when`](#guard-finally-task-execution-using-when-expressions) - Specifies `when` expressions that guard
        the execution of a `Task`; allow execution only when all `when` expressions evaluate to true.
      - [`timeout`](#configuring-the-failure-timeout) - Specifies the timeout before a `Task` fails.
      - [`params`](#specifying-parameters-in-pipelinetasks) - Specifies the `Parameters` that a `Task` requires.
      - [`workspaces`](#specifying-workspaces-in-pipelinetasks) - Specifies the `Workspaces` that a `Task` requires.
      - [`matrix`](#specifying-matrix-in-pipelinetasks) - Specifies the `Parameters` used to fan out a `Task` into
        multiple `TaskRuns` or `Runs`.
  - [`results`](#emitting-results-from-a-pipeline) - Specifies the location to which the `Pipeline` emits its execution
    results.
  - [`displayName`](#specifying-a-display-name) - is a user-facing name of the pipeline that may be used to populate a UI.
  - [`description`](#adding-a-description) - Holds an informative description of the `Pipeline` object.
  - [`finally`](#adding-finally-to-the-pipeline) - Specifies one or more `Tasks` to be executed in parallel after
    all other tasks have completed.
    - [`name`](#adding-finally-to-the-pipeline) - the name of this `Task` within the context of this `Pipeline`.
    - [`displayName`](#specifying-displayname-in-finally-tasks) - a user-facing name of this `Task` within the context of this `Pipeline`.
    - [`description`](#adding-finally-to-the-pipeline) - a description of this `Task` within the context of this `Pipeline`.
    - [`taskRef`](#adding-finally-to-the-pipeline) - a reference to a `Task` definition.
    - [`taskSpec`](#adding-finally-to-the-pipeline) - a specification of a `Task`.
    - [`retries`](#using-the-retries-field) - Specifies the number of times to retry the execution of a `Task` after
      a failure. Does not apply to execution cancellations.
    - [`when`](#guard-finally-task-execution-using-when-expressions) - Specifies `when` expressions that guard
      the execution of a `Task`; allow execution only when all `when` expressions evaluate to true.
    - [`timeout`](#configuring-the-failure-timeout) - Specifies the timeout before a `Task` fails.
    - [`params`](#specifying-parameters-in-finally-tasks) - Specifies the `Parameters` that a `Task` requires.
    - [`workspaces`](#specifying-workspaces-in-finally-tasks) - Specifies the `Workspaces` that a `Task` requires.
    - [`matrix`](#specifying-matrix-in-finally-tasks) - Specifies the `Parameters` used to fan out a `Task` into
      multiple `TaskRuns` or `Runs`.

[kubernetes-overview]:
  https://kubernetes.io/docs/concepts/overview/working-with-objects/kubernetes-objects/#required-fields

## Specifying `Workspaces`

`Workspaces` allow you to specify one or more volumes that each `Task` in the `Pipeline`
requires during execution. You specify one or more `Workspaces` in the `workspaces` field.
For example:

```yaml
spec:
  workspaces:
    - name: pipeline-ws1 # The name of the workspace in the Pipeline
  tasks:
    - name: use-ws-from-pipeline
      taskRef:
        name: gen-code # gen-code expects a workspace with name "output"
      workspaces:
        - name: output
          workspace: pipeline-ws1
    - name: use-ws-again
      taskRef:
        name: commit # commit expects a workspace with name "src"
      runAfter:
        - use-ws-from-pipeline # important: use-ws-from-pipeline writes to the workspace first
      workspaces:
        - name: src
          workspace: pipeline-ws1
```

For simplicity you can also map the name of the `Workspace` in `PipelineTask` to match with
the `Workspace` from the `Pipeline`.
For example:

```yaml
apiVersion: tekton.dev/v1 # or tekton.dev/v1beta1
kind: Pipeline
metadata:
  name: pipeline
spec:
  workspaces:
    - name: source
  tasks:
    - name: gen-code
      taskRef:
        name: gen-code # gen-code expects a Workspace named "source"
      workspaces:
        - name: source # <- mapping workspace name
    - name: commit
      taskRef:
        name: commit # commit expects a Workspace named "source"
      workspaces:
        - name: source # <- mapping workspace name
      runAfter:
        - gen-code
```

For more information, see:
- [Using `Workspaces` in `Pipelines`](workspaces.md#using-workspaces-in-pipelines)
- The [`Workspaces` in a `PipelineRun`](../examples/v1/pipelineruns/workspaces.yaml) code example
- The [variables available in a `PipelineRun`](variables.md#variables-available-in-a-pipeline), including `workspaces.<name>.bound`.
- [Mapping `Workspaces`](https://github.com/tektoncd/community/blob/main/teps/0108-mapping-workspaces.md)

## Specifying `Parameters`

(See also [Specifying Parameters in Tasks](tasks.md#specifying-parameters))

You can specify global parameters, such as compilation flags or artifact names, that you want to supply
to the `Pipeline` at execution time. `Parameters` are passed to the `Pipeline` from its corresponding
`PipelineRun` and can replace template values specified within each `Task` in the `Pipeline`.

Parameter names:
- Must only contain alphanumeric characters, hyphens (`-`), and underscores (`_`).
- Must begin with a letter or an underscore (`_`).

For example, `fooIs-Bar_` is a valid parameter name, but `barIsBa$` or `0banana` are not.

Each declared parameter has a `type` field, which can be set to either `array` or `string`.
`array` is useful in cases where the number of compilation flags being supplied to the `Pipeline`
varies throughout its execution. If no value is specified, the `type` field defaults to `string`.
When the actual parameter value is supplied, its parsed type is validated against the `type` field.
The `description` and `default` fields for a `Parameter` are optional.

The following example illustrates the use of `Parameters` in a `Pipeline`.

The following `Pipeline` declares two input parameters :

- `context` which passes its value (a string) to the `Task` to set the value of the `pathToContext` parameter within the `Task`.
- `flags` which passes its value (an array) to the `Task` to set the value of
  the `flags` parameter within the `Task`. The `flags` parameter within the
`Task` **must** also be an array.
If you specify a value for the `default` field and invoke this `Pipeline` in a `PipelineRun`
without specifying a value for `context`, that value will be used.

**Note:** Input parameter values can be used as variables throughout the `Pipeline`
by using [variable substitution](variables.md#variables-available-in-a-pipeline).

```yaml
apiVersion: tekton.dev/v1 # or tekton.dev/v1beta1
kind: Pipeline
metadata:
  name: pipeline-with-parameters
spec:
  params:
    - name: context
      type: string
      description: Path to context
      default: /some/where/or/other
    - name: flags
      type: array
      description: List of flags
  tasks:
    - name: build-skaffold-web
      taskRef:
        name: build-push
      params:
        - name: pathToDockerFile
          value: Dockerfile
        - name: pathToContext
          value: "$(params.context)"
        - name: flags
          value: ["$(params.flags[*])"]
```

The following `PipelineRun` supplies a value for `context`:

```yaml
apiVersion: tekton.dev/v1 # or tekton.dev/v1beta1
kind: PipelineRun
metadata:
  name: pipelinerun-with-parameters
spec:
  pipelineRef:
    name: pipeline-with-parameters
  params:
    - name: "context"
      value: "/workspace/examples/microservices/leeroy-web"
    - name: "flags"
      value:
        - "foo"
        - "bar"
```

#### Param enum
> :seedling: **`enum` is an [alpha](additional-configs.md#alpha-features) feature.** The `enable-param-enum` feature flag must be set to `"true"` to enable this feature.

Parameter declarations can include `enum` which is a predefine set of valid values that can be accepted by the `Pipeline` `Param`. If a `Param` has both `enum` and default value, the default value must be in the `enum` set. For example, the valid/allowed values for `Param` "message" is bounded to `v1` and `v2`:

``` yaml
apiVersion: tekton.dev/v1
kind: Pipeline
metadata:
  name: pipeline-param-enum
spec:
  params:
  - name: message
    enum: ["v1", "v2"]
    default: "v1"
  tasks:
  - name: task1
    params:
      - name: message
        value: $(params.message)
    steps:
    - name: build
      image: bash:3.2
      script: |
        echo "$(params.message)"
```

If the `Param` value passed in by `PipelineRun` is **NOT** in the predefined `enum` list, the `PipelineRun` will fail with reason `InvalidParamValue`.

If a `PipelineTask` references a `Task` with `enum`, the `enums` specified in the Pipeline `spec.params` (pipeline-level `enum`) must be
a **subset** of the `enums` specified in the referenced `Task` (task-level `enum`). An empty pipeline-level `enum` is invalid
in this scenario since an empty `enum` set indicates a "universal set" which allows all possible values. The same rules apply to `Pipelines` with embbeded `Tasks`.

In the below example, the referenced `Task` accepts `v1` and `v2` as valid values, the `Pipeline` further restricts the valid value to `v1`.

``` yaml
apiVersion: tekton.dev/v1
kind: Task
metadata:
  name: param-enum-demo
spec:
  params:
  - name: message
    type: string
    enum: ["v1", "v2"]
  steps:
  - name: build
    image: bash:latest
    script: |
      echo "$(params.message)"
```

``` yaml
apiVersion: tekton.dev/v1
kind: Pipeline
metadata:
  name: pipeline-param-enum
spec:
  params:
  - name: message
    enum: ["v1"]  # note that an empty enum set is invalid
  tasks:
  - name: task1
    params:
      - name: message
        value: $(params.message)
    taskRef:
      name: param-enum-demo
```

Note that this subset restriction only applies to the task-level `params` with a **direct single** reference to pipeline-level `params`. If a task-level `param` references multiple pipeline-level `params`, the subset validation is not applied.

``` yaml
apiVersion: tekton.dev/v1
kind: Pipeline
...
spec:
  params:
  - name: message1
    enum: ["v1"]
  - name: message2
    enum: ["v2"]
  tasks:
  - name: task1
    params:
      - name: message
        value: "$(params.message1) and $(params.message2)"
    taskSpec:
      params: message
      enum: [...] # the message enum is not required to be a subset of message1 or message2
    ...
```

Tekton validates user-provided values in a `PipelineRun` against the `enum` specified in the `PipelineSpec.params`. Tekton also validates
any resolved `param` value against the `enum` specified in each `PipelineTask` before creating the `TaskRun`.

See usage in this [example](../examples/v1/pipelineruns/alpha/param-enum.yaml)

#### Propagated Params

Like with embedded [pipelineruns](pipelineruns.md#propagated-parameters), you can propagate `params` declared in the `pipeline` down to the inlined `pipelineTasks` and its inlined `Steps`. Wherever a resource (e.g. a `pipelineTask`) or a `StepAction` is referenced, the parameters need to be passed explicitly.

For example, the following is a valid yaml.

```yaml
apiVersion: tekton.dev/v1 # or tekton.dev/v1beta1
kind: Pipeline
metadata:
  name: pipelien-propagated-params
spec:
  params:
    - name: HELLO
      default: "Hello World!"
    - name: BYE
      default: "Bye World!"
  tasks:
    - name: echo-hello
      taskSpec:
        steps:
          - name: echo
            image: ubuntu
            script: |
              #!/usr/bin/env bash
              echo "$(params.HELLO)"
    - name: echo-bye
      taskSpec:
        steps:
          - name: echo-action
            ref:
              name: step-action-echo
            params:
              - name: msg
                value: "$(params.BYE)"
```
The same rules defined in [pipelineruns](pipelineruns.md#propagated-parameters) apply here.

## Adding `Tasks` to the `Pipeline`

 Your `Pipeline` definition must reference at least one [`Task`](tasks.md).
Each `Task` within a `Pipeline` must have a [valid](https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names)
`name` and a `taskRef` or a `taskSpec`. For example:

```yaml
tasks:
  - name: build-the-image
    taskRef:
      name: build-push
```

**Note:** Using both `apiVersion` and `kind` will create [CustomRun](customruns.md), don't set `apiVersion` if only referring to [`Task`](tasks.md).

or

```yaml
tasks:
  - name: say-hello
    taskSpec:
      steps:
      - image: ubuntu
        script: echo 'hello there'
```

Note that any `task` specified in `taskSpec` will be the same version as the `Pipeline`.

### Specifying `displayName` in `PipelineTasks`

The `displayName` field is an optional field that allows you to add a user-facing name of the `PipelineTask` that can be
used to populate and distinguish in the dashboard. For example:

```yaml
spec:
  tasks:
    - name: scan
      displayName: "Code Scan"
      taskRef:
        name: sonar-scan
```

The `displayName` also allows you to parameterize the human-readable name of your choice based on the
[params](#specifying-parameters), [the task results](#passing-one-tasks-results-into-the-parameters-or-when-expressions-of-another),
and [the context variables](#context-variables). For example:

```yaml
spec:
  params:
    - name: application
  tasks:
    - name: scan
      displayName: "Code Scan for $(params.application)"
      taskRef:
        name: sonar-scan
    - name: upload-scan-report
      displayName: "Upload Scan Report $(tasks.scan.results.report)"
      taskRef:
        name: upload
```

Specifying task results in the `displayName` does not introduce an inherent resource dependency among `tasks`. The
pipeline author is responsible for specifying dependency explicitly either using [runAfter](#using-the-runafter-field)
or rely on [whenExpressions](#guard-task-execution-using-when-expressions) or [task results in params](#using-results).

Fully resolved `displayName` is also available in the status as part of the `pipelineRun.status.childReferences`. The
clients such as the dashboard, CLI, etc. can retrieve the `displayName` from the `childReferences`. The `displayName` mainly
drives a better user experience and at the same time it is not validated for the content or length by the controller.

### Specifying Remote Tasks

**([beta feature](https://github.com/tektoncd/pipeline/blob/main/docs/install.md#beta-features))**

A `taskRef` field may specify a Task 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](resolution.md). The below example demonstrates referencing a Task in git:

```yaml
tasks:
- name: "go-build"
  taskRef:
    resolver: git
    params:
    - name: url
      value: https://github.com/tektoncd/catalog.git
    - name: revision
      # value can use params declared at the pipeline level or a static value like main
      value: $(params.gitRevision)
    - name: pathInRepo
      value: task/golang-build/0.3/golang-build.yaml
```

### Specifying `Pipelines` in `PipelineTasks`

> :seedling: **Specifying `pipelines` in `PipelineTasks` is an [alpha](additional-configs.md#alpha-features) feature.**
> The `enable-api-fields` feature flag must be set to `"alpha"` to specify `PipelineRef` or `PipelineSpec` in a `PipelineTask`.
> This feature is in **Preview Only** mode and not yet supported/implemented.

Apart from `taskRef` and `taskSpec`, `pipelineRef` and `pipelineSpec` allows you to specify a `pipeline`  in `pipelineTask`.
This allows you to generate a child `pipelineRun` which is inherited by the parent `pipelineRun`.

```
kind: Pipeline
metadata:
  name: security-scans
spec:
  tasks:
    - name: scorecards
      taskSpec:
        steps:
          - image: alpine
            name: step-1
            script: |
              echo "Generating scorecard report ..."
    - name: codeql
      taskSpec:
        steps:
          - image: alpine
            name: step-1
            script: |
              echo "Generating codeql report ..."
---
apiVersion: tekton.dev/v1
kind: Pipeline
metadata:
  name: clone-scan-notify
spec:
  tasks:
    - name: git-clone
      taskSpec:
        steps:
          - image: alpine
            name: step-1
            script: |
              echo "Cloning a repo to run security scans ..."
    - name: security-scans
      runAfter:
        - git-clone
      pipelineRef:
        name: security-scans
---
```
For further information read [Pipelines in Pipelines](./pipelines-in-pipelines.md)

### Specifying `Parameters` in `PipelineTasks`

You can also provide [`Parameters`](tasks.md#specifying-parameters):

```yaml
spec:
  tasks:
    - name: build-skaffold-web
      taskRef:
        name: build-push
      params:
        - name: pathToDockerFile
          value: Dockerfile
        - name: pathToContext
          value: /workspace/examples/microservices/leeroy-web
```

### Specifying `Matrix` in `PipelineTasks`

> :seedling: **`Matrix` is an [beta](additional-configs.md#beta-features) feature.**
> The `enable-api-fields` feature flag can be set to `"beta"` to specify `Matrix` in a `PipelineTask`.

You can also provide [`Parameters`](tasks.md#specifying-parameters) through the `matrix` field:

```yaml
spec:
  tasks:
    - name: browser-test
      taskRef:
        name: browser-test
      matrix:
        params:
        - name: browser
          value:
          - chrome
          - safari
          - firefox
        include:
          - name: build-1
            params:
              - name: browser
                value: chrome
              - name: url
                value: some-url
```

For further information, read [`Matrix`](./matrix.md).

### Specifying `Workspaces` in `PipelineTasks`

You can also provide [`Workspaces`](tasks.md#specifying-workspaces):

```yaml
spec:
  tasks:
    - name: use-workspace
      taskRef:
        name: gen-code # gen-code expects a workspace with name "output"
      workspaces:
        - name: output
          workspace: shared-ws
```

### Tekton Bundles

A `Tekton Bundle` is an OCI artifact that contains Tekton resources like `Tasks` which can be referenced within a `taskRef`.

There is currently a hard limit of 20 objects in a bundle.

You can reference a `Tekton bundle` in a `TaskRef` in both `v1` and `v1beta1` using [remote resolution](./bundle-resolver.md#pipeline-resolution). The example syntax shown below for `v1` uses remote resolution and requires enabling [beta features](./additional-configs.md#beta-features).

```yaml
spec:
  tasks:
    - name: hello-world
      taskRef:
        resolver: bundles
        params:
        - name: bundle
          value: docker.io/myrepo/mycatalog
        - name: name
          value: echo-task
        - name: kind
          value: Task
```

You may also specify a `tag` as you would with a Docker image which will give you a fixed,
repeatable reference to a `Task`.

```yaml
spec:
  taskRef:
    resolver: bundles
    params:
    - name: bundle
      value: docker.io/myrepo/mycatalog:v1.0.1
    - name: name
      value: echo-task
    - name: kind
      value: Task
```

You may also specify a fixed digest instead of a tag.

```yaml
spec:
  taskRef:
    resolver: bundles
    params:
    - name: bundle
      value: docker.io/myrepo/mycatalog@sha256:abc123
    - name: name
      value: echo-task
    - name: kind
      value: Task
```

Any of the above options will fetch the image using the `ImagePullSecrets` attached to the
`ServiceAccount` specified in the `PipelineRun`.
See the [Service Account](pipelineruns.md#specifying-custom-serviceaccount-credentials) section
for details on how to configure a `ServiceAccount` on a `PipelineRun`. The `PipelineRun` will then
run that `Task` without registering it in the cluster allowing multiple versions of the same named
`Task` to be run at once.

`Tekton Bundles` may be constructed with any toolsets that produce valid OCI image artifacts
so long as the artifact adheres to the [contract](tekton-bundle-contracts.md).

### Using the `runAfter` field

If you need your `Tasks` to execute in a specific order within the `Pipeline`,
use the `runAfter` field to indicate that a `Task` must execute after
one or more other `Tasks`.

In the example below, we want to test the code before we build it. Since there
is no output from the `test-app` `Task`, the `build-app` `Task` uses `runAfter`
to indicate that `test-app` must run before it, regardless of the order in which
they are referenced in the `Pipeline` definition.

```yaml
workspaces:
- name: source
tasks:
- name: test-app
  taskRef:
    name: make-test
  workspaces:
  - name: source
    workspace: source
- name: build-app
  taskRef:
    name: kaniko-build
  runAfter:
    - test-app
  workspaces:
  - name: source
    workspace: source
```

### Using the `retries` field

For each `Task` in the `Pipeline`, you can specify the number of times Tekton
should retry its execution when it fails. When a `Task` fails, the corresponding
`TaskRun` sets its `Succeeded` `Condition` to `False`. The `retries` field
instructs Tekton to retry executing the `Task` when this happens. `retries` are executed
even when other `Task`s in the `Pipeline` have failed, unless the `PipelineRun` has
been [cancelled](./pipelineruns.md#cancelling-a-pipelinerun) or
[gracefully cancelled](./pipelineruns.md#gracefully-cancelling-a-pipelinerun).

If you expect a `Task` to encounter problems during execution (for example,
you know that there will be issues with network connectivity or missing
dependencies), set its `retries` field to a suitable value greater than 0.
If you don't explicitly specify a value, Tekton does not attempt to execute
the failed `Task` again.

In the example below, the execution of the `build-the-image` `Task` will be
retried once after a failure; if the retried execution fails, too, the `Task`
execution fails as a whole.

```yaml
tasks:
  - name: build-the-image
    retries: 1
    taskRef:
      name: build-push
```

### Using the `onError` field

When a `PipelineTask` fails, the rest of the `PipelineTasks` are skipped and the `PipelineRun` is declared a failure. If you would like to
ignore such `PipelineTask` failure and continue executing the rest of the `PipelineTasks`, you can specify `onError` for such a `PipelineTask`.

`OnError` can be set to `stopAndFail` (default) and `continue`. The failure of a `PipelineTask` with `stopAndFail` would stop and fail the whole `PipelineRun`.  A `PipelineTask` fails with `continue` does not fail the whole `PipelineRun`, and the rest of the `PipelineTask` will continue to execute.

To ignore a `PipelineTask` failure, set `onError` to `continue`:

``` yaml
apiVersion: tekton.dev/v1
kind: Pipeline
metadata:
  name: demo
spec:
  tasks:
    - name: task1
      onError: continue
      taskSpec:
        steps:
          - name: step1
            image: alpine
            script: |
              exit 1
```

At runtime, the failure is ignored to determine the `PipelineRun` status. The `PipelineRun` `message` contains the ignored failure info:

``` yaml
status:
  conditions:
  - lastTransitionTime: "2023-09-28T19:08:30Z"
    message: 'Tasks Completed: 1 (Failed: 1 (Ignored: 1), Cancelled 0), Skipped: 0'
    reason: Succeeded
    status: "True"
    type: Succeeded
  ...
```

Note that the `TaskRun` status remains as it is irrelevant to `OnError`. Failed but ignored `TaskRuns` result in a `failed` status with reason
`FailureIgnored`.

For example, the `TaskRun` created by the above `PipelineRun` has the following status:

``` bash
$ kubectl get tr demo-run-task1
NAME                                SUCCEEDED   REASON           STARTTIME   COMPLETIONTIME
demo-run-task1                      False       FailureIgnored   12m         12m
```

To specify `onError` for a `step`, please see [specifying onError for a step](./tasks.md#specifying-onerror-for-a-step).

**Note:** Setting [`Retry`](#specifying-retries) and `OnError:continue` at the same time is **NOT** allowed.

### Produce results with `OnError`

When a `PipelineTask` is set to ignore error and the `PipelineTask` is able to initialize a result before failing, the result is made available to the consumer `PipelineTasks`.

``` yaml
  tasks:
    - name: task1
      onError: continue
      taskSpec:
        results:
          - name: result1
        steps:
          - name: step1
            image: alpine
            script: |
              echo -n 123 | tee $(results.result1.path)
              exit 1
```

The consumer `PipelineTasks` can access the result by referencing `$(tasks.task1.results.result1)`.

If the result is **NOT** initialized before failing, and there is a `PipelineTask` consuming it:

``` yaml
  tasks:
    - name: task1
      onError: continue
      taskSpec:
        results:
          - name: result1
        steps:
          - name: step1
            image: alpine
            script: |
              exit 1
              echo -n 123 | tee $(results.result1.path)
```

- If the consuming `PipelineTask` has `OnError:stopAndFail`, the `PipelineRun` will fail with `InvalidTaskResultReference`.
- If the consuming `PipelineTask` has `OnError:continue`, the consuming `PipelineTask` will be skipped with reason `Results were missing`,
and the `PipelineRun` will continue to execute.

### Guard `Task` execution using `when` expressions

To run a `Task` only when certain conditions are met, it is possible to _guard_ task execution using the `when` field. The `when` field allows you to list a series of references to `when` expressions.

The components of `when` expressions are `input`, `operator` and `values`:

| Component  | Description                                                                                | Syntax                                                                                |
|------------|------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `input`    | Input for the `when` expression, defaults to an empty string if not provided.                              | * Static values e.g. `"ubuntu"`<br/> * Variables ([parameters](#specifying-parameters) or [results](#using-results)) e.g. `"$(params.image)"` or `"$(tasks.task1.results.image)"` or `"$(tasks.task1.results.array-results[1])"`                                                                                |
| `operator` | `operator` represents an `input`'s relationship to a set of `values`, a valid `operator` must be provided. | `in` or `notin`                                                                                |
| `values`   | An array of string values, the `values` array must be provided and has to be non-empty.                    | * An array param e.g. `["$(params.images[*])"]`<br/> * An array result of a task `["$(tasks.task1.results.array-results[*])"]`<br/> * `values` can contain static values e.g. `"ubuntu"`<br/> * `values` can contain variables ([parameters](#specifying-parameters) or [results](#using-results)) or [a Workspaces's `bound` state](#specifying-workspaces) e.g. `["$(params.image)"]` or `["$(tasks.task1.results.image)"]` or `["$(tasks.task1.results.array-results[1])"]` |

The [`Parameters`](#specifying-parameters) are read from the `Pipeline` and [`Results`](#using-results) are read directly from previous [`Tasks`](#adding-tasks-to-the-pipeline). Using [`Results`](#using-results) in a `when` expression in a guarded `Task` introduces a resource dependency on the previous `Task` that produced the `Result`.

The declared `when` expressions are evaluated before the `Task` is run. If all the `when` expressions evaluate to `True`, the `Task` is run. If any of the `when` expressions evaluate to `False`, the `Task` is not run and the `Task` is listed in the [`Skipped Tasks` section of the `PipelineRunStatus`](pipelineruns.md#monitoring-execution-status).

In these examples, `first-create-file` task will only be executed if the `path` parameter is `README.md`, `echo-file-exists` task will only be executed if the `exists` result from `check-file` task is `yes` and `run-lint` task will only be executed if the `lint-config` optional workspace has been provided by a PipelineRun.

```yaml
tasks:
  - name: first-create-file
    when:
      - input: "$(params.path)"
        operator: in
        values: ["README.md"]
    taskRef:
      name: first-create-file
---
tasks:
  - name: echo-file-exists
    when:
      - input: "$(tasks.check-file.results.exists)"
        operator: in
        values: ["yes"]
    taskRef:
      name: echo-file-exists
---
tasks:
  - name: run-lint
    when:
      - input: "$(workspaces.lint-config.bound)"
        operator: in
        values: ["true"]
    taskRef:
      name: lint-source
---
tasks:
  - name: deploy-in-blue
    when:
      - input: "blue"
        operator: in
        values: ["$(params.deployments[*])"]
    taskRef:
      name: deployment
```

For an end-to-end example, see [PipelineRun with `when` expressions](../examples/v1/pipelineruns/pipelinerun-with-when-expressions.yaml).

There are a lot of scenarios where `when` expressions can be really useful. Some of these are:
- Checking if the name of a git branch matches
- Checking if the `Result` of a previous `Task` is as expected
- Checking if a git file has changed in the previous commits
- Checking if an image exists in the registry
- Checking if the name of a CI job matches
- Checking if an optional Workspace has been provided

#### Use CEL expression in WhenExpression

> :seedling: **`CEL in WhenExpression` is an [alpha](additional-configs.md#alpha-features) feature.**
> The `enable-cel-in-whenexpression` feature flag must be set to `"true"` to enable the use of `CEL` in `WhenExpression`.

CEL (Common Expression Language) is a declarative language designed for simplicity, speed, safety, and portability which can be used to express a wide variety of conditions and computations.

You can define a CEL expression in `WhenExpression` to guard the execution of a `Task`.  The CEL expression must evaluate to either `true` or `false`. You can use a single line of CEL string to replace current `WhenExpressions`'s `input`+`operator`+`values`. For example:

```yaml
# current WhenExpressions
when:
  - input: "foo"
    operator: "in"
    values: ["foo", "bar"]
  - input: "duh"
    operator: "notin"
    values: ["foo", "bar"]

# with cel
when:
  - cel: "'foo' in ['foo', 'bar']"
  - cel: "!('duh' in ['foo', 'bar'])"
```

CEL can offer more conditional functions, such as numeric comparisons (e.g. `>`, `<=`, etc), logic operators (e.g. `OR`, `AND`), Regex Pattern Matching. For example:

```yaml
  when:
    # test coverage result is larger than 90%
    - cel: "'$(tasks.unit-test.results.test-coverage)' > 0.9"
    # params is not empty, or params2 is 8.5 or 8.6
    - cel: "'$(params.param1)' != '' || '$(params.param2)' == '8.5' || '$(params.param2)' == '8.6'"
    # param branch matches pattern `release/.*`
    - cel: "'$(params.branch)'.matches('release/.*')"
```

##### Variable substitution in CEL

`CEL` supports [string substitutions](https://github.com/tektoncd/pipeline/blob/main/docs/variables.md#variables-available-in-a-pipeline), you can reference string, array indexing or object value of a param/result. For example:

```yaml
  when:
    # string result
    - cel: "$(tasks.unit-test.results.test-coverage) > 0.9"
    # array indexing result
    - cel: "$(tasks.unit-test.results.test-coverage[0]) > 0.9"
    # object result key
    - cel: "'$(tasks.objectTask.results.repo.url)'.matches('github.com/tektoncd/.*')"
    # string param
    - cel: "'$(params.foo)' == 'foo'"
    # array indexing
    - cel: "'$(params.branch[0])' == 'foo'"
    # object param key
    - cel: "'$(params.repo.url)'.matches('github.com/tektoncd/.*')"
```

**Note:** the reference needs to be wrapped with single quotes.
Whole `Array` and `Object` replacements are not supported yet. The following usage is not supported:

```yaml
  when:
    - cel: "'foo' in '$(params.array_params[*])'"
    - cel: "'foo' in '$(params.object_params[*])'"
```
<!-- wokeignore:rule=master -->
In addition to the cases listed above, you can craft any valid CEL expression as defined by the [cel-spec language definition](https://github.com/google/cel-spec/blob/master/doc/langdef.md)

`CEL` expression is validated at admission webhook and a validation error will be returned if the expression is invalid.

**Note:** To use Tekton's [variable substitution](variables.md), you need to wrap the reference with single quotes. This also means that if you pass another CEL expression via `params` or `results`, it won't be executed. Therefore CEL injection is disallowed.

For example:
```
This is valid: '$(params.foo)' == 'foo'
This is invalid: $(params.foo) == 'foo'
CEL's variable substitution is not supported yet and thus invalid: params.foo == 'foo'
```

#### Guarding a `Task` and its dependent `Tasks`

To guard a `Task` and its dependent Tasks:
- cascade the `when` expressions to the specific dependent `Tasks` to be guarded as well
- compose the `Task` and its dependent `Tasks` as a unit to be guarded and executed together using `Pipelines` in `Pipelines`

##### Cascade `when` expressions to the specific dependent `Tasks`

Pick and choose which specific dependent `Tasks` to guard as well, and cascade the `when` expressions to those `Tasks`.

Taking the use case below, a user who wants to guard `manual-approval` and its dependent `Tasks`:

```
                                     tests
                                       |
                                       v
                                 manual-approval
                                 |            |
                                 v        (approver)
                            build-image       |
                                |             v
                                v          slack-msg
                            deploy-image
```

The user can design the `Pipeline` to solve their use case as such:

```yaml
tasks:
#...
- name: manual-approval
  runAfter:
    - tests
  when:
    - input: $(params.git-action)
      operator: in
      values:
        - merge
  taskRef:
    name: manual-approval

- name: build-image
  when:
    - input: $(params.git-action)
      operator: in
      values:
        - merge
  runAfter:
    - manual-approval
  taskRef:
    name: build-image

- name: deploy-image
  when:
    - input: $(params.git-action)
      operator: in
      values:
        - merge
  runAfter:
    - build-image
  taskRef:
    name: deploy-image

- name: slack-msg
  params:
    - name: approver
      value: $(tasks.manual-approval.results.approver)
  taskRef:
    name: slack-msg
```

##### Compose using Pipelines in Pipelines

Compose a set of `Tasks` as a unit of execution using `Pipelines` in `Pipelines`, which allows for guarding a `Task` and
its dependent `Tasks` (as a sub-`Pipeline`) using `when` expressions.

**Note:** `Pipelines` in `Pipelines` is an [experimental feature](https://github.com/tektoncd/experimental/tree/main/pipelines-in-pipelines)

Taking the use case below, a user who wants to guard `manual-approval` and its dependent `Tasks`:

```
                                     tests
                                       |
                                       v
                                 manual-approval
                                 |            |
                                 v        (approver)
                            build-image       |
                                |             v
                                v          slack-msg
                            deploy-image
```

The user can design the `Pipelines` to solve their use case as such:

```yaml
## sub pipeline (approve-build-deploy-slack)
tasks:
  - name: manual-approval
    runAfter:
      - integration-tests
    taskRef:
      name: manual-approval

  - name: build-image
    runAfter:
      - manual-approval
    taskRef:
      name: build-image

  - name: deploy-image
    runAfter:
      - build-image
    taskRef:
      name: deploy-image

  - name: slack-msg
    params:
      - name: approver
        value: $(tasks.manual-approval.results.approver)
    taskRef:
      name: slack-msg

---
## main pipeline
tasks:
#...
- name: approve-build-deploy-slack
  runAfter:
    - tests
  when:
    - input: $(params.git-action)
      operator: in
      values:
        - merge
  taskRef:
    apiVersion: tekton.dev/v1beta1
    kind: Pipeline
    name: approve-build-deploy-slack
```

#### Guarding a `Task` only

When `when` expressions evaluate to `False`, the `Task` will be skipped and:
- The ordering-dependent `Tasks` will be executed
- The resource-dependent `Tasks` (and their dependencies) will be skipped because of missing `Results` from the skipped
  parent `Task`. When we add support for [default `Results`](https://github.com/tektoncd/community/pull/240), then the
  resource-dependent `Tasks` may be executed if the default `Results` from the skipped parent `Task` are specified. In
  addition, if a resource-dependent `Task` needs a file from a guarded parent `Task` in a shared `Workspace`, make sure
  to handle the execution of the child `Task` in case the expected file is missing from the `Workspace` because the
  guarded parent `Task` is skipped.

On the other hand, the rest of the `Pipeline` will continue executing.

```
                                     tests
                                       |
                                       v
                                 manual-approval
                                 |            |
                                 v        (approver)
                            build-image       |
                                |             v
                                v          slack-msg
                            deploy-image
```

Taking the use case above, a user who wants to guard `manual-approval` only can design the `Pipeline` as such:

```yaml
tasks:
#...
- name: manual-approval
  runAfter:
    - tests
  when:
    - input: $(params.git-action)
      operator: in
      values:
        - merge
  taskRef:
    name: manual-approval

- name: build-image
  runAfter:
    - manual-approval
  taskRef:
    name: build-image

- name: deploy-image
  runAfter:
    - build-image
  taskRef:
    name: deploy-image

- name: slack-msg
  params:
    - name: approver
      value: $(tasks.manual-approval.results.approver)
  taskRef:
    name: slack-msg
```

If `manual-approval` is skipped, execution of its dependent `Tasks` (`slack-msg`, `build-image` and `deploy-image`)
would be unblocked regardless:
- `build-image` and `deploy-image` should be executed successfully
- `slack-msg` will be skipped because it is missing the `approver` `Result` from `manual-approval`
  - dependents of `slack-msg` would have been skipped too if it had any of them
  - if `manual-approval` specifies a default `approver` `Result`, such as "None", then `slack-msg` would be executed
    ([supporting default `Results` is in progress](https://github.com/tektoncd/community/pull/240))

### Configuring the failure timeout

You can use the `Timeout` field in the `Task` spec within the `Pipeline` to set the timeout
of the `TaskRun` that executes that `Task` within the `PipelineRun` that executes your `Pipeline.`
The `Timeout` value is a `duration` conforming to Go's [`ParseDuration`](https://golang.org/pkg/time/#ParseDuration)
format. For example, valid values are `1h30m`, `1h`, `1m`, and `60s`.

**Note:** If you do not specify a `Timeout` value, Tekton instead honors the timeout for the [`PipelineRun`](pipelineruns.md#configuring-a-pipelinerun).

In the example below, the `build-the-image` `Task` is configured to time out after 90 seconds:

```yaml
spec:
  tasks:
    - name: build-the-image
      taskRef:
        name: build-push
      timeout: "0h1m30s"
```

## Using variable substitution

Tekton provides variables to inject values into the contents of certain fields.
The values you can inject come from a range of sources including other fields
in the Pipeline, context-sensitive information that Tekton provides, and runtime
information received from a PipelineRun.

The mechanism of variable substitution is quite simple - string replacement is
performed by the Tekton Controller when a PipelineRun is executed.

See the [complete list of variable substitutions for Pipelines](./variables.md#variables-available-in-a-pipeline)
and the [list of fields that accept substitutions](./variables.md#fields-that-accept-variable-substitutions).

For an end-to-end example, see [using context variables](../examples/v1/pipelineruns/using_context_variables.yaml).

### Using the `retries` and `retry-count` variable substitutions

Tekton supports variable substitution for the [`retries`](#using-the-retries-field)
parameter of `PipelineTask`. Variables like `context.pipelineTask.retries` and
`context.task.retry-count` can be added to the parameters of a `PipelineTask`.
`context.pipelineTask.retries` will be replaced by `retries` of the `PipelineTask`, while
`context.task.retry-count` will be replaced by current retry number of the `PipelineTask`.

```yaml
params:
- name: pipelineTask-retries
  value: "$(context.pipelineTask.retries)"
taskSpec:
  params:
  - name: pipelineTask-retries
  steps:
  - image: ubuntu
    name: print-if-retries-exhausted
    script: |
      if [ "$(context.task.retry-count)" == "$(params.pipelineTask-retries)" ]
      then
        echo "This is the last retry."
      fi
      exit 1
```

**Note:** Every `PipelineTask` can only access its own `retries` and `retry-count`. These
values aren't accessible for other `PipelineTask`s.

## Using `Results`

Tasks can emit [`Results`](tasks.md#emitting-results) when they execute. A Pipeline can use these
`Results` for two different purposes:

1. A Pipeline can pass the `Result` of a `Task` into the `Parameters` or `when` expressions of another.
2. A Pipeline can itself emit `Results` and include data from the `Results` of its Tasks.

> **Note** Tekton does not enforce that results are produced at Task level. If a pipeline attempts to
> consume a result that was declared by a Task, but not produced, it will fail. [TEP-0048](https://github.com/tektoncd/community/blob/main/teps/0048-task-results-without-results.md)
> propopses introducing default values for results to help Pipeline authors manage this case.

### Passing one Task's `Results` into the `Parameters` or `when` expressions of another

Sharing `Results` between `Tasks` in a `Pipeline` happens via
[variable substitution](variables.md#variables-available-in-a-pipeline) - one `Task` emits
a `Result` and another receives it as a `Parameter` with a variable such as
`$(tasks.<task-name>.results.<result-name>)`. Pipeline support two new types of
results and parameters: array `[]string` and object `map[string]string`.
Array result is a beta feature and can be enabled by setting `enable-api-fields` to `alpha` or `beta`.

| Result Type | Parameter Type | Specification                                    | `enable-api-fields` |
|-------------|----------------|--------------------------------------------------|---------------------|
| string      | string         | `$(tasks.<task-name>.results.<result-name>)`     | stable              |
| array       | array          | `$(tasks.<task-name>.results.<result-name>[*])`  | alpha or beta       |
| array       | string         | `$(tasks.<task-name>.results.<result-name>[i])`  | alpha or beta       |
| object      | object         | `$(tasks.<task-name>.results.<result-name>[*])`  | alpha or beta              |
| object      | string         | `$(tasks.<task-name>.results.<result-name>.key)` | alpha or beta              |

**Note:** Whole Array and Object `Results` (using star notation) cannot be referred in `script`.

When one `Task` receives the `Results` of another, there is a dependency created between those
two `Tasks`. In order for the receiving `Task` to get data from another `Task's` `Result`,
the `Task` producing the `Result` must run first. Tekton enforces this `Task` ordering
by ensuring that the `Task` emitting the `Result` executes before any `Task` that uses it.

In the snippet below, a param is provided its value from the `commit` `Result` emitted by the
`checkout-source` `Task`. Tekton will make sure that the `checkout-source` `Task` runs
before this one.

```yaml
params:
  - name: foo
    value: "$(tasks.checkout-source.results.commit)"
  - name: array-params
    value: "$(tasks.checkout-source.results.array-results[*])"
  - name: array-indexing-params
    value: "$(tasks.checkout-source.results.array-results[1])"
  - name: object-params
    value: "$(tasks.checkout-source.results.object-results[*])"
  - name: object-element-params
    value: "$(tasks.checkout-source.results.object-results.objectkey)"
```

**Note:** If `checkout-source` exits successfully without initializing `commit` `Result`,
the receiving `Task` fails and causes the `Pipeline` to fail with `InvalidTaskResultReference`:

```
unable to find result referenced by param 'foo' in 'task';: Could not find result with name 'commit' for task run 'checkout-source'
```

In the snippet below, a `when` expression is provided its value from the `exists` `Result` emitted by the
`check-file` `Task`. Tekton will make sure that the `check-file` `Task` runs before this one.

```yaml
when:
  - input: "$(tasks.check-file.results.exists)"
    operator: in
    values: ["yes"]
```

For an end-to-end example, see [`Task` `Results` in a `PipelineRun`](../examples/v1/pipelineruns/task_results_example.yaml).

Note that `when` expressions are whitespace-sensitive.  In particular, when producing results intended for inputs to `when`
expressions that may include newlines at their close (e.g. `cat`, `jq`), you may wish to truncate them.

```yaml
taskSpec:
  params:
  - name: jsonQuery-check
  steps:
  - image: ubuntu
    name: store-name-in-results
    script: |
      curl -s https://my-json-server.typicode.com/typicode/demo/profile | jq -r .name | tr -d '\n' | tee $(results.name.path)
```

### Emitting `Results` from a `Pipeline`

A `Pipeline` can emit `Results` of its own for a variety of reasons - an external
system may need to read them when the `Pipeline` is complete, they might summarise
the most important `Results` from the `Pipeline's` `Tasks`, or they might simply
be used to expose non-critical messages generated during the execution of the `Pipeline`.

A `Pipeline's` `Results` can be composed of one or many `Task` `Results` emitted during
the course of the `Pipeline's` execution. A `Pipeline` `Result` can refer to its `Tasks'`
`Results` using a variable of the form `$(tasks.<task-name>.results.<result-name>)`.

After a `Pipeline` has executed the `PipelineRun` will be populated with the `Results`
emitted by the `Pipeline`. These will be written to the `PipelineRun's`
`status.pipelineResults` field.

In the example below, the `Pipeline` specifies a `results` entry with the name `sum` that
references the `outputValue` `Result` emitted by the `calculate-sum` `Task`.

```yaml
results:
  - name: sum
    description: the sum of all three operands
    value: $(tasks.calculate-sum.results.outputValue)
```

For an end-to-end example, see [`Results` in a `PipelineRun`](../examples/v1/pipelineruns/pipelinerun-results.yaml).

In the example below, the `Pipeline` collects array and object results from `Tasks`.

```yaml
    results:
      - name: array-results
        type: array
        description: whole array
        value: $(tasks.task1.results.array-results[*])
      - name: array-indexing-results
        type: string
        description: array element
        value: $(tasks.task1.results.array-results[1])
      - name: object-results
        type: object
        description: whole object
        value: $(tasks.task2.results.object-results[*])
      - name: object-element
        type: string
        description: object element
        value: $(tasks.task2.results.object-results.foo)
```

For an end-to-end example see [`Array and Object Results` in a `PipelineRun`](../examples/v1/pipelineruns/pipeline-emitting-results.yaml).

A `Pipeline Result` is not emitted if any of the following are true:
- A `PipelineTask` referenced by the `Pipeline Result` failed. The `PipelineRun` will also
have failed.
- A `PipelineTask` referenced by the `Pipeline Result` was skipped.
- A `PipelineTask` referenced by the `Pipeline Result` didn't emit the referenced `Task Result`. This
should be considered a bug in the `Task` and [may fail a `PipelineTask` in future](https://github.com/tektoncd/pipeline/issues/3497).
- The `Pipeline Result` uses a variable that doesn't point to an actual `PipelineTask`. This will
result in an `InvalidTaskResultReference` validation error during `PipelineRun` execution.
- The `Pipeline Result` uses a variable that doesn't point to an actual result in a `PipelineTask`.
This will cause an `InvalidTaskResultReference` validation error during `PipelineRun` execution.

**Note:** Since a `Pipeline Result` can contain references to multiple `Task Results`, if any of those
`Task Result` references are invalid the entire `Pipeline Result` is not emitted.
**Note:** If a `PipelineTask` referenced by the `Pipeline Result` was skipped, the `Pipeline Result` will not be emitted and the `PipelineRun` will not fail due to a missing result.

## Configuring the `Task` execution order

You can connect `Tasks` in a `Pipeline` so that they execute in a Directed Acyclic Graph (DAG).
Each `Task` in the `Pipeline` becomes a node on the graph that can be connected with an edge
so that one will run before another and the execution of the `Pipeline` progresses to completion
without getting stuck in an infinite loop.

This is done using:
- _resource dependencies_:
  - [`results`](#emitting-results-from-a-pipeline) of one `Task` being passed into `params` or `when` expressions of
    another

- _ordering dependencies_:
  - [`runAfter`](#using-the-runafter-field) clauses on the corresponding `Tasks`

For example, the `Pipeline` defined as follows

```yaml
tasks:
- name: lint-repo
  taskRef:
    name: pylint
- name: test-app
  taskRef:
    name: make-test
- name: build-app
  taskRef:
    name: kaniko-build-app
  runAfter:
    - test-app
- name: build-frontend
  taskRef:
    name: kaniko-build-frontend
  runAfter:
    - test-app
- name: deploy-all
  taskRef:
    name: deploy-kubectl
  runAfter:
    - build-app
    - build-frontend
```

executes according to the following graph:

```none
        |            |
        v            v
     test-app    lint-repo
    /        \
   v          v
build-app  build-frontend
   \          /
    v        v
    deploy-all
```

In particular:

1. The `lint-repo` and `test-app` `Tasks` have no `runAfter` clauses
   and start executing simultaneously.
2. Once `test-app` completes, both `build-app` and `build-frontend` start
   executing simultaneously since they both `runAfter` the `test-app` `Task`.
3. The `deploy-all` `Task` executes once both `build-app` and `build-frontend`
   complete, since it is supposed to `runAfter` them both.
4. The entire `Pipeline` completes execution once both `lint-repo` and `deploy-all`
   complete execution.

## Specifying a display name

The `displayName` field is an optional field that allows you to add a user-facing name of the `Pipeline` that can be used to populate a UI. For example:

```yaml
spec:
  displayName: "Code Scan"
  tasks:
    - name: scan
      taskRef:
        name: sonar-scan
```

## Adding a description

The `description` field is an optional field and can be used to provide description of the `Pipeline`.

## Adding `Finally` to the `Pipeline`

You can specify a list of one or more final tasks under `finally` section. `finally` tasks are guaranteed to be executed
in parallel after all `PipelineTasks` under `tasks` have completed regardless of success or error. `finally` tasks are very
similar to `PipelineTasks` under `tasks` section and follow the same syntax. Each `finally` task must have a
[valid](https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names) `name` and a [taskRef or
taskSpec](taskruns.md#specifying-the-target-task). For example:

```yaml
spec:
  tasks:
    - name: tests
      taskRef:
        name: integration-test
  finally:
    - name: cleanup-test
      taskRef:
        name: cleanup
```

### Specifying `displayName` in `finally` tasks

Similar to [specifying `displayName` in `pipelineTasks`](#specifying-displayname-in-pipelinetasks), `finally` tasks also
allows to add a user-facing name of the `finally` task that can be used to populate and distinguish in the dashboard.
For example:

```yaml
spec:
  finally:
    - name: notification
      displayName: "Notify"
      taskRef:
        name: notification
    - name: notification-using-context-variable
      displayName: "Notification from $(context.pipeline.name)"
      taskRef:
        name: notification
```

The `displayName` also allows you to parameterize the human-readable name of your choice based on the
[params](#specifying-parameters), [the task results](#consuming-task-execution-results-in-finally),
and [the context variables](#context-variables).

Fully resolved `displayName` is also available in the status as part of the `pipelineRun.status.childReferences`. The
clients such as the dashboard, CLI, etc. can retrieve the `displayName` from the `childReferences`. The `displayName` mainly
drives a better user experience and at the same time it is not validated for the content or length by the controller.

### Specifying `Workspaces` in `finally` tasks

`finally` tasks can specify [workspaces](workspaces.md) which `PipelineTasks` might have utilized
e.g. a mount point for credentials held in Secrets. To support that requirement, you can specify one or more
`Workspaces` in the `workspaces` field for the `finally` tasks similar to `tasks`.

```yaml
spec:
  workspaces:
    - name: shared-workspace
  tasks:
    - name: clone-app-source
      taskRef:
        name: clone-app-repo-to-workspace
      workspaces:
        - name: shared-workspace
          workspace: shared-workspace
  finally:
    - name: cleanup-workspace
      taskRef:
        name: cleanup-workspace
      workspaces:
        - name: shared-workspace
          workspace: shared-workspace
```

### Specifying `Parameters` in `finally` tasks

Similar to `tasks`, you can specify [`Parameters`](tasks.md#specifying-parameters) in `finally` tasks:

```yaml
spec:
  tasks:
    - name: tests
      taskRef:
        name: integration-test
  finally:
    - name: report-results
      taskRef:
        name: report-results
      params:
        - name: url
          value: "someURL"
```

### Specifying `matrix` in `finally` tasks

> :seedling: **`Matrix` is an [beta](additional-configs.md#beta-features) feature.**
> The `enable-api-fields` feature flag can be set to `"beta"` to specify `Matrix` in a `PipelineTask`.

Similar to `tasks`, you can also provide [`Parameters`](tasks.md#specifying-parameters) through `matrix`
in `finally` tasks:

```yaml
spec:
  tasks:
    - name: tests
      taskRef:
        name: integration-test
  finally:
    - name: report-results
      taskRef:
        name: report-results
      params:
        - name: url
          value: "someURL"
      matrix:
        params:
        - name: slack-channel
          value:
          - "foo"
          - "bar"
        include:
          - name: build-1
            params:
              - name: slack-channel
                value: "foo"
              - name: flags
                value: "-v"
```

For further information, read [`Matrix`](./matrix.md).

### Consuming `Task` execution results in `finally`

`finally` tasks can be configured to consume `Results` of `PipelineTask` from the `tasks` section:

```yaml
spec:
  tasks:
    - name: clone-app-repo
      taskRef:
        name: git-clone
  finally:
    - name: discover-git-commit
      params:
        - name: commit
          value: $(tasks.clone-app-repo.results.commit)
```
**Note:** The scheduling of such `finally` task does not change, it will still be executed in parallel with other
`finally` tasks after all non-`finally` tasks are done.

The controller resolves task results before executing the `finally` task `discover-git-commit`. If the task
`clone-app-repo` failed before initializing `commit` or skipped with [when expression](#guard-task-execution-using-when-expressions)
resulting in uninitialized task result `commit`, the `finally` Task `discover-git-commit` will be included in the list of
`skippedTasks` and continues executing rest of the `finally` tasks. The pipeline exits with `completion` instead of
`success` if a `finally` task is added to the list of `skippedTasks`.

### Consuming `Pipeline` result with `finally`

`finally` tasks can emit `Results` and these results emitted from the `finally` tasks can be configured in the
[Pipeline Results](#emitting-results-from-a-pipeline). References of `Results` from `finally` will follow the same naming conventions as referencing `Results` from `tasks`: ```$(finally.<finally-pipelinetask-name>.result.<result-name>)```.

```yaml
results:
  - name: comment-count-validate
    value: $(finally.check-count.results.comment-count-validate)
finally:
  - name: check-count
    taskRef:
      name: example-task-name
```

In this example, `pipelineResults` in `status` will show the name-value pair for the result `comment-count-validate` which is produced in the `Task` `example-task-name`.

### `PipelineRun` Status with `finally`

With `finally`, `PipelineRun` status is calculated based on `PipelineTasks` under `tasks` section and `finally` tasks.

Without `finally`:

| `PipelineTasks` under `tasks`                                                                           | `PipelineRun` status | Reason      |
|---------------------------------------------------------------------------------------------------------|----------------------|-------------|
| all `PipelineTasks` successful                                                                          | `true`               | `Succeeded` |
| one or more `PipelineTasks` [skipped](#guard-task-execution-using-when-expressions) and rest successful | `true`               | `Completed` |
| single failure of `PipelineTask`                                                                        | `false`              | `failed`    |

With `finally`:

| `PipelineTasks` under `tasks`                                                                          | `finally` tasks                        | `PipelineRun` status | Reason      |
|--------------------------------------------------------------------------------------------------------|----------------------------------------|----------------------|-------------|
| all `PipelineTask` successful                                                                          | all `finally` tasks successful         | `true`               | `Succeeded` |
| all `PipelineTask` successful                                                                          | one or more failure of `finally` tasks | `false`              | `Failed`    |
| one or more `PipelineTask` [skipped](#guard-task-execution-using-when-expressions) and rest successful | all `finally` tasks successful         | `true`               | `Completed` |
| one or more `PipelineTask` [skipped](#guard-task-execution-using-when-expressions) and rest successful | one or more failure of `finally` tasks | `false`              | `Failed`    |
| single failure of `PipelineTask`                                                                       | all `finally` tasks successful         | `false`              | `failed`    |
| single failure of `PipelineTask`                                                                       | one or more failure of `finally` tasks | `false`              | `failed`    |

Overall, `PipelineRun` state transitioning is explained below for respective scenarios:

* All `PipelineTask` and `finally` tasks are successful: `Started` -> `Running` -> `Succeeded`
* At least one `PipelineTask` skipped and rest successful:  `Started` -> `Running` -> `Completed`
* One `PipelineTask` failed / one or more `finally` tasks failed: `Started` -> `Running` -> `Failed`

Please refer to the [table](pipelineruns.md#monitoring-execution-status) under Monitoring Execution Status to learn about
what kind of events are triggered based on the `Pipelinerun` status.

### Using Execution `Status` of `pipelineTask`

A `pipeline` can check the status of a specific `pipelineTask` from the `tasks` section in `finally` through the task
parameters:

```yaml
finally:
  - name: finaltask
    params:
      - name: task1Status
        value: "$(tasks.task1.status)"
    taskSpec:
      params:
        - name: task1Status
      steps:
        - image: ubuntu
          name: print-task-status
          script: |
            if [ $(params.task1Status) == "Failed" ]
            then
              echo "Task1 has failed, continue processing the failure"
            fi
```

This kind of variable can have any one of the values from the following table:

| Status      | Description                                                                                |
|-------------|--------------------------------------------------------------------------------------------------|
| `Succeeded` | `taskRun` for the `pipelineTask` completed successfully                                          |
| `Failed`    | `taskRun` for the `pipelineTask` completed with a failure or cancelled by the user               |
| `None`      | the `pipelineTask` has been skipped or no execution information available for the `pipelineTask` |

For an end-to-end example, see [`status` in a `PipelineRun`](../examples/v1/pipelineruns/pipelinerun-task-execution-status.yaml).

### Using Aggregate Execution `Status` of All `Tasks`

A `pipeline` can check an aggregate status of all the `tasks` section in `finally` through the task parameters:

```yaml
finally:
  - name: finaltask
    params:
      - name: aggregateTasksStatus
        value: "$(tasks.status)"
    taskSpec:
      params:
        - name: aggregateTasksStatus
      steps:
        - image: ubuntu
          name: check-task-status
          script: |
            if [ $(params.aggregateTasksStatus) == "Failed" ]
            then
              echo "Looks like one or more tasks returned failure, continue processing the failure"
            fi
```

This kind of variable can have any one of the values from the following table:

| Status      | Description                                                                                |
|-------------|-----------------------------------------------------------------------------------------------------------------------------------|
| `Succeeded` | all `tasks` have succeeded                                                                                |
| `Failed`    | one ore more `tasks` failed                                                                                |
| `Completed` | all `tasks` completed successfully including one or more skipped tasks                                                            |
| `None`      | no aggregate execution status available (i.e. none of the above), one or more `tasks` could be pending/running/cancelled/timedout |

For an end-to-end example, see [`$(tasks.status)` usage in a `Pipeline`](../examples/v1/pipelineruns/pipelinerun-task-execution-status.yaml).

### Guard `finally` `Task` execution using `when` expressions

Similar to `Tasks`, `finally` `Tasks` can be guarded using [`when` expressions](#guard-task-execution-using-when-expressions)
that operate on static inputs or variables. Like in `Tasks`, `when` expressions in `finally` `Tasks` can operate on
`Parameters` and `Results`. Unlike in `Tasks`, `when` expressions in `finally` `tasks` can also operate on the [`Execution
Status`](#using-execution-status-of-pipelinetask) of `Tasks`.

#### `when` expressions using `Parameters` in `finally` `Tasks`

`when` expressions in `finally` `Tasks` can utilize `Parameters` as demonstrated using [`golang-build`](https://github.com/tektoncd/catalog/tree/main/task/golang-build/0.1)
and [`send-to-channel-slack`](https://github.com/tektoncd/catalog/tree/main/task/send-to-channel-slack/0.1) Catalog
`Tasks`:

```yaml
apiVersion: tekton.dev/v1 # or tekton.dev/v1beta1
kind: PipelineRun
metadata:
  generateName: pipelinerun-
spec:
  pipelineSpec:
    params:
      - name: enable-notifications
        type: string
        description: a boolean indicating whether the notifications should be sent
    tasks:
      - name: golang-build
        taskRef:
          name: golang-build
      # […]
    finally:
      - name: notify-build-failure # executed only when build task fails and notifications are enabled
        when:
          - input: $(tasks.golang-build.status)
            operator: in
            values: ["Failed"]
          - input: $(params.enable-notifications)
            operator: in
            values: ["true"]
        taskRef:
          name: send-to-slack-channel
      # […]
  params:
    - name: enable-notifications
      value: true
```

#### `when` expressions using `Results` in `finally` 'Tasks`

`when` expressions in `finally` `tasks` can utilize `Results`, as demonstrated using [`git-clone`](https://github.com/tektoncd/catalog/tree/main/task/git-clone/0.2)
and [`github-add-comment`](https://github.com/tektoncd/catalog/tree/main/task/github-add-comment/0.2) Catalog `Tasks`:

```yaml
apiVersion: tekton.dev/v1 # or tekton.dev/v1beta1
kind: PipelineRun
metadata:
  generateName: pipelinerun-
spec:
  pipelineSpec:
    tasks:
      - name: git-clone
        taskRef:
          name: git-clone
      - name: go-build
      # […]
    finally:
      - name: notify-commit-sha # executed only when commit sha is not the expected sha
        when:
          - input: $(tasks.git-clone.results.commit)
            operator: notin
            values: [$(params.expected-sha)]
        taskRef:
          name: github-add-comment
      # […]
  params:
    - name: expected-sha
      value: 54dd3984affab47f3018852e61a1a6f9946ecfa
```

If the `when` expressions in a `finally` `task` use `Results` from a skipped or failed non-finally `Tasks`, then the
`finally` `task` would also be skipped and be included in the list of `Skipped Tasks` in the `Status`, [similarly to when using
`Results` in other parts of the `finally` `task`](#consuming-task-execution-results-in-finally).

#### `when` expressions using `Execution Status` of `PipelineTask` in `finally` `tasks`

`when` expressions in `finally` `tasks` can utilize [`Execution Status` of `PipelineTasks`](#using-execution-status-of-pipelinetask),
as demonstrated using [`golang-build`](https://github.com/tektoncd/catalog/tree/main/task/golang-build/0.1) and
[`send-to-channel-slack`](https://github.com/tektoncd/catalog/tree/main/task/send-to-channel-slack/0.1) Catalog `Tasks`:

```yaml
apiVersion: tekton.dev/v1 # or tekton.dev/v1beta1
kind: PipelineRun
metadata:
  generateName: pipelinerun-
spec:
  pipelineSpec:
    tasks:
      - name: golang-build
        taskRef:
          name: golang-build
      # […]
    finally:
      - name: notify-build-failure # executed only when build task fails
        when:
          - input: $(tasks.golang-build.status)
            operator: in
            values: ["Failed"]
        taskRef:
          name: send-to-slack-channel
      # […]
```

For an end-to-end example, see [PipelineRun with `when` expressions](../examples/v1/pipelineruns/pipelinerun-with-when-expressions.yaml).

#### `when` expressions using `Aggregate Execution Status` of `Tasks` in `finally` `tasks`

`when` expressions in `finally` `tasks` can utilize
[`Aggregate Execution Status` of `Tasks`](#using-aggregate-execution-status-of-all-tasks) as demonstrated:

```yaml
finally:
  - name: notify-any-failure # executed only when one or more tasks fail
    when:
      - input: $(tasks.status)
        operator: in
        values: ["Failed"]
    taskRef:
      name: notify-failure
```

For an end-to-end example, see [PipelineRun with `when` expressions](../examples/v1/pipelineruns/pipelinerun-with-when-expressions.yaml).

### Known Limitations

#### Cannot configure the `finally` task execution order

It's not possible to configure or modify the execution order of the `finally` tasks. Unlike `Tasks` in a `Pipeline`,
all `finally` tasks run simultaneously and start executing once all `PipelineTasks` under `tasks` have settled which means
no `runAfter` can be specified in `finally` tasks.

## Using Custom Tasks

Custom Tasks have been promoted from `v1alpha1` to `v1beta1`. Starting from `v0.43.0` to `v0.46.0`, Pipeline Controller is able to create either `v1alpha1` or `v1beta1` Custom Task gated by a feature flag `custom-task-version`, defaulting to `v1beta1`. You can set `custom-task-version` to `v1alpha1` or `v1beta1` to control which version to create.

Starting from `v0.47.0`, feature flag `custom-task-version` is removed and only `v1beta1` Custom Task will be supported. See the [migration doc](migrating-v1alpha1.Run-to-v1beta1.CustomRun.md) for details.

[Custom Tasks](https://github.com/tektoncd/community/blob/main/teps/0002-custom-tasks.md)
can implement behavior that doesn't correspond directly to running a workload in a `Pod` on the cluster.
For example, a custom task might execute some operation outside of the cluster and wait for its execution to complete.

A `PipelineRun` starts a custom task by creating a [`CustomRun`](https://github.com/tektoncd/pipeline/blob/main/docs/customruns.md) instead of a `TaskRun`.
In order for a custom task to execute, there must be a custom task controller running on the cluster
that is responsible for watching and updating `CustomRun`s which reference their type.

### Specifying the target Custom Task

To specify the custom task type you want to execute, the `taskRef` field
must include the custom task's `apiVersion` and `kind` as shown below.
Using `apiVersion` will always create a `CustomRun`. If `apiVersion` is set, `kind` is required as well.

```yaml
spec:
  tasks:
    - name: run-custom-task
      taskRef:
        apiVersion: example.dev/v1alpha1
        kind: Example
```

This creates a `Run/CustomRun` of a custom task of type `Example` in the `example.dev` API group with the version `v1alpha1`.

Validation error will be returned if `apiVersion` or `kind` is missing.

You can also specify the `name` of a custom task resource object previously defined in the cluster.

```yaml
spec:
  tasks:
    - name: run-custom-task
      taskRef:
        apiVersion: example.dev/v1alpha1
        kind: Example
        name: myexample
```

If the `taskRef` specifies a name, the custom task controller should look up the
`Example` resource with that name and use that object to configure the execution.

If the `taskRef` does not specify a name, the custom task controller might support
some default behavior for executing unnamed tasks.

### Specifying a Custom Task Spec in-line (or embedded)

**For `v1alpha1.Run`**
```yaml
spec:
  tasks:
    - name: run-custom-task
      taskSpec:
        apiVersion: example.dev/v1alpha1
        kind: Example
        spec:
          field1: value1
          field2: value2
```

**For `v1beta1.CustomRun`**
```yaml
spec:
  tasks:
    - name: run-custom-task
      taskSpec:
        apiVersion: example.dev/v1alpha1
        kind: Example
        customSpec:
          field1: value1
          field2: value2
```

If the custom task controller supports the in-line or embedded task spec, this will create a `Run/CustomRun` of a custom task of
type `Example` in the `example.dev` API group with the version `v1alpha1`.

If the `taskSpec` is not supported, the custom task controller should produce proper validation errors.

Please take a look at the
developer guide for custom controllers supporting `taskSpec`:
- [guidance for `Run`](runs.md#developer-guide-for-custom-controllers-supporting-spec)
- [guidance for `CustomRun`](customruns.md#developer-guide-for-custom-controllers-supporting-customspec)

`taskSpec` support for `pipelineRun` was designed and discussed in
[TEP-0061](https://github.com/tektoncd/community/blob/main/teps/0061-allow-custom-task-to-be-embedded-in-pipeline.md)

### Specifying parameters

If a custom task supports [`parameters`](tasks.md#specifying-parameters), you can use the
`params` field to specify their values:

```yaml
spec:
  tasks:
    - name: run-custom-task
      taskRef:
        apiVersion: example.dev/v1alpha1
        kind: Example
        name: myexample
      params:
        - name: foo
          value: bah
```

## Context Variables

The `Parameters` in the `Params` field will accept
[context variables](variables.md) that will be substituted, including:

* `PipelineRun` name, namespace and uid
* `Pipeline` name
* `PipelineTask` retries

```yaml
spec:
  tasks:
    - name: run-custom-task
      taskRef:
        apiVersion: example.dev/v1alpha1
        kind: Example
        name: myexample
      params:
        - name: foo
          value: $(context.pipeline.name)
```

### Specifying matrix

> :seedling: **`Matrix` is an [alpha](additional-configs.md#alpha-features) feature.**
> The `enable-api-fields` feature flag must be set to `"alpha"` to specify `Matrix` in a `PipelineTask`.

If a custom task supports [`parameters`](tasks.md#specifying-parameters), you can use the
`matrix` field to specify their values, if you want to fan:

```yaml
spec:
  tasks:
    - name: run-custom-task
      taskRef:
        apiVersion: example.dev/v1alpha1
        kind: Example
        name: myexample
      params:
        - name: foo
          value: bah
      matrix:
        params:
        - name: bar
          value:
            - qux
            - thud
        include:
          - name: build-1
            params:
            - name: common-package
              value: path-to-common-pkg
```

For further information, read [`Matrix`](./matrix.md).

### Specifying workspaces

If the custom task supports it, you can provide [`Workspaces`](workspaces.md#using-workspaces-in-tasks) to share data with the custom task.

```yaml
spec:
  tasks:
    - name: run-custom-task
      taskRef:
        apiVersion: example.dev/v1alpha1
        kind: Example
        name: myexample
      workspaces:
        - name: my-workspace
```

Consult the documentation of the custom task that you are using to determine whether it supports workspaces and how to name them.

### Using `Results`

If the custom task produces results, you can reference them in a Pipeline using the normal syntax,
`$(tasks.<task-name>.results.<result-name>)`.

### Specifying `Timeout`

#### `v1alpha1.Run`
If the custom task supports it as [we recommended](runs.md#developer-guide-for-custom-controllers-supporting-timeout), you can provide `timeout` to specify the maximum running time of a `CustomRun` (including all retry attempts or other operations).

#### `v1beta1.CustomRun`
If the custom task supports it as [we recommended](customruns.md#developer-guide-for-custom-controllers-supporting-timeout), you can provide `timeout` to specify the maximum running time of one `CustomRun` execution.

```yaml
spec:
  tasks:
    - name: run-custom-task
      timeout: 2s
      taskRef:
        apiVersion: example.dev/v1alpha1
        kind: Example
        name: myexample
```

Consult the documentation of the custom task that you are using to determine whether it supports `Timeout`.

### Specifying `Retries`
If the custom task supports it, you can provide `retries` to specify how many times you want to retry the custom task.

```yaml
spec:
  tasks:
    - name: run-custom-task
      retries: 2
      taskRef:
        apiVersion: example.dev/v1alpha1
        kind: Example
        name: myexample
```

Consult the documentation of the custom task that you are using to determine whether it supports `Retries`.

### Known Custom Tasks

We try to list as many known Custom Tasks as possible here so that users can easily find what they want. Please feel free to share the Custom Task you implemented in this table.

#### v1beta1.CustomRun

| Custom Task                      | Description                                                                                |
|:---------------------------------|:---------------------------------------------------------------------------------------------------------------------------------|
| [Wait Task Beta][wait-task-beta] | Waits a given amount of time before succeeding, specified by an input parameter named duration. Support `timeout` and `retries`. |
| [Approvals][approvals-beta]| Pauses the execution of `PipelineRuns` and waits for manual approvals. Version 0.6.0 and up. |

#### v1alpha1.Run

| Custom Task                                      | Description                                                                                |
|:-------------------------------------------------|:-----------------------------------------------------------------------------------------------------------|
| [Pipeline Loops][pipeline-loops]                 | Runs a `Pipeline` in a loop with varying `Parameter` values.                                               |
| [Common Expression Language][cel]                | Provides Common Expression Language support in Tekton Pipelines.                                           |
| [Wait][wait]                                     | Waits a given amount of time, specified by a `Parameter` named "duration", before succeeding.              |
| [Approvals][approvals-alpha]                     | Pauses the execution of `PipelineRuns` and waits for manual approvals. Version up to (and including) 0.5.0 |
| [Pipelines in Pipelines][pipelines-in-pipelines] | Defines and executes a `Pipeline` in a `Pipeline`.                                                         |
| [Task Group][task-group]                         | Groups `Tasks` together as a `Task`.                                                                       |
| [Pipeline in a Pod][pipeline-in-pod]             | Runs `Pipeline` in a `Pod`.                                                                                |

[pipeline-loops]: https://github.com/tektoncd/experimental/tree/f60e1cd8ce22ed745e335f6f547bb9a44580dc7c/pipeline-loops
[task-loops]: https://github.com/tektoncd/experimental/tree/f60e1cd8ce22ed745e335f6f547bb9a44580dc7c/task-loops
[cel]: https://github.com/tektoncd/experimental/tree/f60e1cd8ce22ed745e335f6f547bb9a44580dc7c/cel
[wait]: https://github.com/tektoncd/experimental/tree/f60e1cd8ce22ed745e335f6f547bb9a44580dc7c/wait-task
[approvals-alpha]: https://github.com/automatiko-io/automatiko-approval-task/tree/v0.5.0
[approvals-beta]: https://github.com/automatiko-io/automatiko-approval-task/tree/v0.6.1
[task-group]: https://github.com/openshift-pipelines/tekton-task-group/tree/39823f26be8f59504f242a45b9f2e791d4b36e1c
[pipelines-in-pipelines]: https://github.com/tektoncd/experimental/tree/f60e1cd8ce22ed745e335f6f547bb9a44580dc7c/pipelines-in-pipelines
[pipeline-in-pod]: https://github.com/tektoncd/experimental/tree/f60e1cd8ce22ed745e335f6f547bb9a44580dc7c/pipeline-in-pod
[wait-task-beta]: https://github.com/tektoncd/pipeline/tree/a127323da31bcb933a04a6a1b5dbb6e0411e3dc1/test/custom-task-ctrls/wait-task-beta

## Code examples

For a better understanding of `Pipelines`, study [our code examples](https://github.com/tektoncd/pipeline/tree/main/examples).

---

Except as otherwise noted, the content of this page is licensed under the
[Creative Commons Attribution 4.0 License](https://creativecommons.org/licenses/by/4.0/),
and code samples are licensed under the
[Apache 2.0 License](https://www.apache.org/licenses/LICENSE-2.0).

linkTitle   Pipelines  weight  203            Pipelines     Pipelines   pipelines       Overview   overview       Configuring a  Pipeline    configuring a pipeline       Specifying  Workspaces    specifying workspaces       Specifying  Parameters    specifying parameters       Adding  Tasks  to the  Pipeline    adding tasks to the pipeline         Specifying Display Name   specifying displayname in pipelinetasks         Specifying Remote Tasks   specifying remote tasks         Specifying  Pipelines  in  PipelineTasks    specifying pipelines in pipelinetasks         Specifying  Parameters  in  PipelineTasks    specifying parameters in pipelinetasks         Specifying  Matrix  in  PipelineTasks    specifying matrix in pipelinetasks         Specifying  Workspaces  in  PipelineTasks    specifying workspaces in pipelinetasks         Tekton Bundles   tekton bundles         Using the  runAfter  field   using the runafter field         Using the  retries  field   using the retries field         Using the  onError  field   using the onerror field         Produce results with  OnError    produce results with onerror         Guard  Task  execution using  when  expressions   guard task execution using when expressions           Guarding a  Task  and its dependent  Tasks    guarding a task and its dependent tasks             Cascade  when  expressions to the specific dependent  Tasks    cascade when expressions to the specific dependent tasks             Compose using Pipelines in Pipelines   compose using pipelines in pipelines           Guarding a  Task  only   guarding a task only         Configuring the failure timeout   configuring the failure timeout       Using variable substitution   using variable substitution         Using the  retries  and  retry count  variable substitutions   using the retries and retry count variable substitutions       Using  Results    using results         Passing one Task s  Results  into the  Parameters  or  when  expressions of another   passing one tasks results into the parameters or when expressions of another         Emitting  Results  from a  Pipeline    emitting results from a pipeline       Configuring the  Task  execution order   configuring the task execution order       Adding a description   adding a description       Adding  Finally  to the  Pipeline    adding finally to the pipeline         Specifying Display Name   specifying displayname in finally tasks         Specifying  Workspaces  in  finally  tasks   specifying workspaces in finally tasks         Specifying  Parameters  in  finally  tasks   specifying parameters in finally tasks         Specifying  matrix  in  finally  tasks   specifying matrix in finally tasks         Consuming  Task  execution results in  finally    consuming task execution results in finally         Consuming  Pipeline  result with  finally    consuming pipeline result with finally          PipelineRun  Status with  finally    pipelinerun status with finally         Using Execution  Status  of  pipelineTask    using execution status of pipelinetask         Using Aggregate Execution  Status  of All  Tasks    using aggregate execution status of all tasks         Guard  finally   Task  execution using  when  expressions   guard finally task execution using when expressions            when  expressions using  Parameters  in  finally   Tasks    when expressions using parameters in finally tasks            when  expressions using  Results  in  finally   Tasks    when expressions using results in finally tasks            when  expressions using  Execution Status  of  PipelineTask  in  finally   tasks    when expressions using execution status of pipelinetask in finally tasks            when  expressions using  Aggregate Execution Status  of  Tasks  in  finally   tasks    when expressions using aggregate execution status of tasks in finally tasks         Known Limitations   known limitations           Cannot configure the  finally  task execution order   cannot configure the finally task execution order       Using Custom Tasks   using custom tasks         Specifying the target Custom Task   specifying the target custom task         Specifying a Custom Task Spec in line  or embedded    specifying a custom task spec in line or embedded         Specifying parameters   specifying parameters 1         Specifying matrix   specifying matrix         Specifying workspaces   specifying workspaces 1         Using  Results    using results 1         Specifying  Timeout    specifying timeout         Specifying  Retries    specifying retries         Known Custom Tasks   known custom tasks       Code examples   code examples      Overview  A  Pipeline  is a collection of  Tasks  that you define and arrange in a specific order of execution as part of your continuous integration flow  Each  Task  in a  Pipeline  executes as a  Pod  on your Kubernetes cluster  You can configure various execution conditions to fit your business needs      Configuring a  Pipeline   A  Pipeline  definition supports the following fields     Required        apiVersion   kubernetes overview    Specifies the API version  for example      tekton dev v1beta1         kind   kubernetes overview    Identifies this resource object as a  Pipeline  object        metadata   kubernetes overview    Specifies metadata that uniquely identifies the      Pipeline  object  For example  a  name         spec   kubernetes overview    Specifies the configuration information for     this  Pipeline  object  This must include            tasks    adding tasks to the pipeline    Specifies the  Tasks  that comprise the  Pipeline          and the details of their execution    Optional        params    specifying parameters    Specifies the  Parameters  that the  Pipeline  requires        workspaces    specifying workspaces    Specifies a set of Workspaces that the  Pipeline  requires        tasks    adding tasks to the pipeline             name    adding tasks to the pipeline    the name of this  Task  within the context of this  Pipeline             displayName    specifying displayname in pipelinetasks    a user facing name of this  Task  within the context of this  Pipeline             description    adding tasks to the pipeline    a description of this  Task  within the context of this  Pipeline             taskRef    adding tasks to the pipeline    a reference to a  Task  definition            taskSpec    adding tasks to the pipeline    a specification of a  Task             runAfter    using the runafter field    Indicates that a  Task  should execute after one or more other          Tasks  without output linking            retries    using the retries field    Specifies the number of times to retry the execution of a  Task  after         a failure  Does not apply to execution cancellations            when    guard finally task execution using when expressions    Specifies  when  expressions that guard         the execution of a  Task   allow execution only when all  when  expressions evaluate to true            timeout    configuring the failure timeout    Specifies the timeout before a  Task  fails            params    specifying parameters in pipelinetasks    Specifies the  Parameters  that a  Task  requires            workspaces    specifying workspaces in pipelinetasks    Specifies the  Workspaces  that a  Task  requires            matrix    specifying matrix in pipelinetasks    Specifies the  Parameters  used to fan out a  Task  into         multiple  TaskRuns  or  Runs         results    emitting results from a pipeline    Specifies the location to which the  Pipeline  emits its execution     results        displayName    specifying a display name    is a user facing name of the pipeline that may be used to populate a UI        description    adding a description    Holds an informative description of the  Pipeline  object        finally    adding finally to the pipeline    Specifies one or more  Tasks  to be executed in parallel after     all other tasks have completed          name    adding finally to the pipeline    the name of this  Task  within the context of this  Pipeline           displayName    specifying displayname in finally tasks    a user facing name of this  Task  within the context of this  Pipeline           description    adding finally to the pipeline    a description of this  Task  within the context of this  Pipeline           taskRef    adding finally to the pipeline    a reference to a  Task  definition          taskSpec    adding finally to the pipeline    a specification of a  Task           retries    using the retries field    Specifies the number of times to retry the execution of a  Task  after       a failure  Does not apply to execution cancellations          when    guard finally task execution using when expressions    Specifies  when  expressions that guard       the execution of a  Task   allow execution only when all  when  expressions evaluate to true          timeout    configuring the failure timeout    Specifies the timeout before a  Task  fails          params    specifying parameters in finally tasks    Specifies the  Parameters  that a  Task  requires          workspaces    specifying workspaces in finally tasks    Specifies the  Workspaces  that a  Task  requires          matrix    specifying matrix in finally tasks    Specifies the  Parameters  used to fan out a  Task  into       multiple  TaskRuns  or  Runs     kubernetes overview     https   kubernetes io docs concepts overview working with objects kubernetes objects  required fields     Specifying  Workspaces    Workspaces  allow you to specify one or more volumes that each  Task  in the  Pipeline  requires during execution  You specify one or more  Workspaces  in the  workspaces  field  For example      yaml spec    workspaces        name  pipeline ws1   The name of the workspace in the Pipeline   tasks        name  use ws from pipeline       taskRef          name  gen code   gen code expects a workspace with name  output        workspaces            name  output           workspace  pipeline ws1       name  use ws again       taskRef          name  commit   commit expects a workspace with name  src        runAfter            use ws from pipeline   important  use ws from pipeline writes to the workspace first       workspaces            name  src           workspace  pipeline ws1      For simplicity you can also map the name of the  Workspace  in  PipelineTask  to match with the  Workspace  from the  Pipeline   For example      yaml apiVersion  tekton dev v1   or tekton dev v1beta1 kind  Pipeline metadata    name  pipeline spec    workspaces        name  source   tasks        name  gen code       taskRef          name  gen code   gen code expects a Workspace named  source        workspaces            name  source      mapping workspace name       name  commit       taskRef          name  commit   commit expects a Workspace named  source        workspaces            name  source      mapping workspace name       runAfter            gen code      For more information  see     Using  Workspaces  in  Pipelines   workspaces md using workspaces in pipelines    The   Workspaces  in a  PipelineRun      examples v1 pipelineruns workspaces yaml  code example   The  variables available in a  PipelineRun   variables md variables available in a pipeline   including  workspaces  name  bound      Mapping  Workspaces   https   github com tektoncd community blob main teps 0108 mapping workspaces md      Specifying  Parameters    See also  Specifying Parameters in Tasks  tasks md specifying parameters    You can specify global parameters  such as compilation flags or artifact names  that you want to supply to the  Pipeline  at execution time   Parameters  are passed to the  Pipeline  from its corresponding  PipelineRun  and can replace template values specified within each  Task  in the  Pipeline    Parameter names    Must only contain alphanumeric characters  hyphens        and underscores          Must begin with a letter or an underscore         For example   fooIs Bar   is a valid parameter name  but  barIsBa   or  0banana  are not   Each declared parameter has a  type  field  which can be set to either  array  or  string    array  is useful in cases where the number of compilation flags being supplied to the  Pipeline  varies throughout its execution  If no value is specified  the  type  field defaults to  string   When the actual parameter value is supplied  its parsed type is validated against the  type  field  The  description  and  default  fields for a  Parameter  are optional   The following example illustrates the use of  Parameters  in a  Pipeline    The following  Pipeline  declares two input parameters       context  which passes its value  a string  to the  Task  to set the value of the  pathToContext  parameter within the  Task      flags  which passes its value  an array  to the  Task  to set the value of   the  flags  parameter within the  Task   The  flags  parameter within the  Task    must   also be an array  If you specify a value for the  default  field and invoke this  Pipeline  in a  PipelineRun  without specifying a value for  context   that value will be used     Note    Input parameter values can be used as variables throughout the  Pipeline  by using  variable substitution  variables md variables available in a pipeline       yaml apiVersion  tekton dev v1   or tekton dev v1beta1 kind  Pipeline metadata    name  pipeline with parameters spec    params        name  context       type  string       description  Path to context       default   some where or other       name  flags       type  array       description  List of flags   tasks        name  build skaffold web       taskRef          name  build push       params            name  pathToDockerFile           value  Dockerfile           name  pathToContext           value     params context             name  flags           value      params flags            The following  PipelineRun  supplies a value for  context       yaml apiVersion  tekton dev v1   or tekton dev v1beta1 kind  PipelineRun metadata    name  pipelinerun with parameters spec    pipelineRef      name  pipeline with parameters   params        name   context        value    workspace examples microservices leeroy web        name   flags        value             foo             bar            Param enum    seedling     enum  is an  alpha  additional configs md alpha features  feature    The  enable param enum  feature flag must be set to   true   to enable this feature   Parameter declarations can include  enum  which is a predefine set of valid values that can be accepted by the  Pipeline   Param   If a  Param  has both  enum  and default value  the default value must be in the  enum  set  For example  the valid allowed values for  Param   message  is bounded to  v1  and  v2        yaml apiVersion  tekton dev v1 kind  Pipeline metadata    name  pipeline param enum spec    params      name  message     enum    v1    v2       default   v1    tasks      name  task1     params          name  message         value    params message      steps        name  build       image  bash 3 2       script            echo    params message        If the  Param  value passed in by  PipelineRun  is   NOT   in the predefined  enum  list  the  PipelineRun  will fail with reason  InvalidParamValue    If a  PipelineTask  references a  Task  with  enum   the  enums  specified in the Pipeline  spec params   pipeline level  enum   must be a   subset   of the  enums  specified in the referenced  Task   task level  enum    An empty pipeline level  enum  is invalid in this scenario since an empty  enum  set indicates a  universal set  which allows all possible values  The same rules apply to  Pipelines  with embbeded  Tasks    In the below example  the referenced  Task  accepts  v1  and  v2  as valid values  the  Pipeline  further restricts the valid value to  v1        yaml apiVersion  tekton dev v1 kind  Task metadata    name  param enum demo spec    params      name  message     type  string     enum    v1    v2     steps      name  build     image  bash latest     script          echo    params message            yaml apiVersion  tekton dev v1 kind  Pipeline metadata    name  pipeline param enum spec    params      name  message     enum    v1      note that an empty enum set is invalid   tasks      name  task1     params          name  message         value    params message      taskRef        name  param enum demo      Note that this subset restriction only applies to the task level  params  with a   direct single   reference to pipeline level  params   If a task level  param  references multiple pipeline level  params   the subset validation is not applied       yaml apiVersion  tekton dev v1 kind  Pipeline     spec    params      name  message1     enum    v1       name  message2     enum    v2     tasks      name  task1     params          name  message         value     params message1  and   params message2       taskSpec        params  message       enum          the message enum is not required to be a subset of message1 or message2              Tekton validates user provided values in a  PipelineRun  against the  enum  specified in the  PipelineSpec params   Tekton also validates any resolved  param  value against the  enum  specified in each  PipelineTask  before creating the  TaskRun    See usage in this  example     examples v1 pipelineruns alpha param enum yaml        Propagated Params  Like with embedded  pipelineruns  pipelineruns md propagated parameters   you can propagate  params  declared in the  pipeline  down to the inlined  pipelineTasks  and its inlined  Steps   Wherever a resource  e g  a  pipelineTask   or a  StepAction  is referenced  the parameters need to be passed explicitly    For example  the following is a valid yaml      yaml apiVersion  tekton dev v1   or tekton dev v1beta1 kind  Pipeline metadata    name  pipelien propagated params spec    params        name  HELLO       default   Hello World         name  BYE       default   Bye World     tasks        name  echo hello       taskSpec          steps              name  echo             image  ubuntu             script                     usr bin env bash               echo    params HELLO         name  echo bye       taskSpec          steps              name  echo action             ref                name  step action echo             params                  name  msg                 value     params BYE        The same rules defined in  pipelineruns  pipelineruns md propagated parameters  apply here       Adding  Tasks  to the  Pipeline    Your  Pipeline  definition must reference at least one   Task   tasks md   Each  Task  within a  Pipeline  must have a  valid  https   kubernetes io docs concepts overview working with objects names  names   name  and a  taskRef  or a  taskSpec   For example      yaml tasks      name  build the image     taskRef        name  build push        Note    Using both  apiVersion  and  kind  will create  CustomRun  customruns md   don t set  apiVersion  if only referring to   Task   tasks md    or     yaml tasks      name  say hello     taskSpec        steps          image  ubuntu         script  echo  hello there       Note that any  task  specified in  taskSpec  will be the same version as the  Pipeline        Specifying  displayName  in  PipelineTasks   The  displayName  field is an optional field that allows you to add a user facing name of the  PipelineTask  that can be used to populate and distinguish in the dashboard  For example      yaml spec    tasks        name  scan       displayName   Code Scan        taskRef          name  sonar scan      The  displayName  also allows you to parameterize the human readable name of your choice based on the  params   specifying parameters    the task results   passing one tasks results into the parameters or when expressions of another   and  the context variables   context variables   For example      yaml spec    params        name  application   tasks        name  scan       displayName   Code Scan for   params application         taskRef          name  sonar scan       name  upload scan report       displayName   Upload Scan Report   tasks scan results report         taskRef          name  upload      Specifying task results in the  displayName  does not introduce an inherent resource dependency among  tasks   The pipeline author is responsible for specifying dependency explicitly either using  runAfter   using the runafter field  or rely on  whenExpressions   guard task execution using when expressions  or  task results in params   using results    Fully resolved  displayName  is also available in the status as part of the  pipelineRun status childReferences   The clients such as the dashboard  CLI  etc  can retrieve the  displayName  from the  childReferences   The  displayName  mainly drives a better user experience and at the same time it is not validated for the content or length by the controller       Specifying Remote Tasks      beta feature  https   github com tektoncd pipeline blob main docs install md beta features      A  taskRef  field may specify a Task 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  resolution md   The below example demonstrates referencing a Task in git      yaml tasks    name   go build    taskRef      resolver  git     params        name  url       value  https   github com tektoncd catalog git       name  revision         value can use params declared at the pipeline level or a static value like main       value    params gitRevision        name  pathInRepo       value  task golang build 0 3 golang build yaml          Specifying  Pipelines  in  PipelineTasks      seedling    Specifying  pipelines  in  PipelineTasks  is an  alpha  additional configs md alpha features  feature      The  enable api fields  feature flag must be set to   alpha   to specify  PipelineRef  or  PipelineSpec  in a  PipelineTask     This feature is in   Preview Only   mode and not yet supported implemented   Apart from  taskRef  and  taskSpec    pipelineRef  and  pipelineSpec  allows you to specify a  pipeline   in  pipelineTask   This allows you to generate a child  pipelineRun  which is inherited by the parent  pipelineRun        kind  Pipeline metadata    name  security scans spec    tasks        name  scorecards       taskSpec          steps              image  alpine             name  step 1             script                  echo  Generating scorecard report            name  codeql       taskSpec          steps              image  alpine             name  step 1             script                  echo  Generating codeql report          apiVersion  tekton dev v1 kind  Pipeline metadata    name  clone scan notify spec    tasks        name  git clone       taskSpec          steps              image  alpine             name  step 1             script                  echo  Cloning a repo to run security scans            name  security scans       runAfter            git clone       pipelineRef          name  security scans         For further information read  Pipelines in Pipelines    pipelines in pipelines md        Specifying  Parameters  in  PipelineTasks   You can also provide   Parameters   tasks md specifying parameters       yaml spec    tasks        name  build skaffold web       taskRef          name  build push       params            name  pathToDockerFile           value  Dockerfile           name  pathToContext           value   workspace examples microservices leeroy web          Specifying  Matrix  in  PipelineTasks      seedling     Matrix  is an  beta  additional configs md beta features  feature      The  enable api fields  feature flag can be set to   beta   to specify  Matrix  in a  PipelineTask    You can also provide   Parameters   tasks md specifying parameters  through the  matrix  field      yaml spec    tasks        name  browser test       taskRef          name  browser test       matrix          params            name  browser           value              chrome             safari             firefox         include              name  build 1             params                  name  browser                 value  chrome                 name  url                 value  some url      For further information  read   Matrix     matrix md        Specifying  Workspaces  in  PipelineTasks   You can also provide   Workspaces   tasks md specifying workspaces       yaml spec    tasks        name  use workspace       taskRef          name  gen code   gen code expects a workspace with name  output        workspaces            name  output           workspace  shared ws          Tekton Bundles  A  Tekton Bundle  is an OCI artifact that contains Tekton resources like  Tasks  which can be referenced within a  taskRef    There is currently a hard limit of 20 objects in a bundle   You can reference a  Tekton bundle  in a  TaskRef  in both  v1  and  v1beta1  using  remote resolution    bundle resolver md pipeline resolution   The example syntax shown below for  v1  uses remote resolution and requires enabling  beta features    additional configs md beta features       yaml spec    tasks        name  hello world       taskRef          resolver  bundles         params            name  bundle           value  docker io myrepo mycatalog           name  name           value  echo task           name  kind           value  Task      You may also specify a  tag  as you would with a Docker image which will give you a fixed  repeatable reference to a  Task       yaml spec    taskRef      resolver  bundles     params        name  bundle       value  docker io myrepo mycatalog v1 0 1       name  name       value  echo task       name  kind       value  Task      You may also specify a fixed digest instead of a tag      yaml spec    taskRef      resolver  bundles     params        name  bundle       value  docker io myrepo mycatalog sha256 abc123       name  name       value  echo task       name  kind       value  Task      Any of the above options will fetch the image using the  ImagePullSecrets  attached to the  ServiceAccount  specified in the  PipelineRun   See the  Service Account  pipelineruns md specifying custom serviceaccount credentials  section for details on how to configure a  ServiceAccount  on a  PipelineRun   The  PipelineRun  will then run that  Task  without registering it in the cluster allowing multiple versions of the same named  Task  to be run at once    Tekton Bundles  may be constructed with any toolsets that produce valid OCI image artifacts so long as the artifact adheres to the  contract  tekton bundle contracts md        Using the  runAfter  field  If you need your  Tasks  to execute in a specific order within the  Pipeline   use the  runAfter  field to indicate that a  Task  must execute after one or more other  Tasks    In the example below  we want to test the code before we build it  Since there is no output from the  test app   Task   the  build app   Task  uses  runAfter  to indicate that  test app  must run before it  regardless of the order in which they are referenced in the  Pipeline  definition      yaml workspaces    name  source tasks    name  test app   taskRef      name  make test   workspaces      name  source     workspace  source   name  build app   taskRef      name  kaniko build   runAfter        test app   workspaces      name  source     workspace  source          Using the  retries  field  For each  Task  in the  Pipeline   you can specify the number of times Tekton should retry its execution when it fails  When a  Task  fails  the corresponding  TaskRun  sets its  Succeeded   Condition  to  False   The  retries  field instructs Tekton to retry executing the  Task  when this happens   retries  are executed even when other  Task s in the  Pipeline  have failed  unless the  PipelineRun  has been  cancelled    pipelineruns md cancelling a pipelinerun  or  gracefully cancelled    pipelineruns md gracefully cancelling a pipelinerun    If you expect a  Task  to encounter problems during execution  for example  you know that there will be issues with network connectivity or missing dependencies   set its  retries  field to a suitable value greater than 0  If you don t explicitly specify a value  Tekton does not attempt to execute the failed  Task  again   In the example below  the execution of the  build the image   Task  will be retried once after a failure  if the retried execution fails  too  the  Task  execution fails as a whole      yaml tasks      name  build the image     retries  1     taskRef        name  build push          Using the  onError  field  When a  PipelineTask  fails  the rest of the  PipelineTasks  are skipped and the  PipelineRun  is declared a failure  If you would like to ignore such  PipelineTask  failure and continue executing the rest of the  PipelineTasks   you can specify  onError  for such a  PipelineTask     OnError  can be set to  stopAndFail   default  and  continue   The failure of a  PipelineTask  with  stopAndFail  would stop and fail the whole  PipelineRun    A  PipelineTask  fails with  continue  does not fail the whole  PipelineRun   and the rest of the  PipelineTask  will continue to execute   To ignore a  PipelineTask  failure  set  onError  to  continue        yaml apiVersion  tekton dev v1 kind  Pipeline metadata    name  demo spec    tasks        name  task1       onError  continue       taskSpec          steps              name  step1             image  alpine             script                  exit 1      At runtime  the failure is ignored to determine the  PipelineRun  status  The  PipelineRun   message  contains the ignored failure info       yaml status    conditions      lastTransitionTime   2023 09 28T19 08 30Z      message   Tasks Completed  1  Failed  1  Ignored  1   Cancelled 0   Skipped  0      reason  Succeeded     status   True      type  Succeeded            Note that the  TaskRun  status remains as it is irrelevant to  OnError   Failed but ignored  TaskRuns  result in a  failed  status with reason  FailureIgnored    For example  the  TaskRun  created by the above  PipelineRun  has the following status       bash   kubectl get tr demo run task1 NAME                                SUCCEEDED   REASON           STARTTIME   COMPLETIONTIME demo run task1                      False       FailureIgnored   12m         12m      To specify  onError  for a  step   please see  specifying onError for a step    tasks md specifying onerror for a step      Note    Setting   Retry    specifying retries  and  OnError continue  at the same time is   NOT   allowed       Produce results with  OnError   When a  PipelineTask  is set to ignore error and the  PipelineTask  is able to initialize a result before failing  the result is made available to the consumer  PipelineTasks        yaml   tasks        name  task1       onError  continue       taskSpec          results              name  result1         steps              name  step1             image  alpine             script                  echo  n 123   tee   results result1 path                exit 1      The consumer  PipelineTasks  can access the result by referencing    tasks task1 results result1     If the result is   NOT   initialized before failing  and there is a  PipelineTask  consuming it       yaml   tasks        name  task1       onError  continue       taskSpec          results              name  result1         steps              name  step1             image  alpine             script                  exit 1               echo  n 123   tee   results result1 path         If the consuming  PipelineTask  has  OnError stopAndFail   the  PipelineRun  will fail with  InvalidTaskResultReference     If the consuming  PipelineTask  has  OnError continue   the consuming  PipelineTask  will be skipped with reason  Results were missing   and the  PipelineRun  will continue to execute       Guard  Task  execution using  when  expressions  To run a  Task  only when certain conditions are met  it is possible to  guard  task execution using the  when  field  The  when  field allows you to list a series of references to  when  expressions   The components of  when  expressions are  input    operator  and  values      Component    Description                                                                                Syntax                                                                                input       Input for the  when  expression  defaults to an empty string if not provided                                   Static values e g    ubuntu   br     Variables   parameters   specifying parameters  or  results   using results   e g      params image    or     tasks task1 results image    or     tasks task1 results array results 1                                                                                operator     operator  represents an  input  s relationship to a set of  values   a valid  operator  must be provided     in  or  notin                                                                                values      An array of string values  the  values  array must be provided and has to be non empty                         An array param e g       params images        br     An array result of a task      tasks task1 results array results        br      values  can contain static values e g    ubuntu   br      values  can contain variables   parameters   specifying parameters  or  results   using results   or  a Workspaces s  bound  state   specifying workspaces  e g       params image     or      tasks task1 results image     or      tasks task1 results array results 1          The   Parameters    specifying parameters  are read from the  Pipeline  and   Results    using results  are read directly from previous   Tasks    adding tasks to the pipeline   Using   Results    using results  in a  when  expression in a guarded  Task  introduces a resource dependency on the previous  Task  that produced the  Result    The declared  when  expressions are evaluated before the  Task  is run  If all the  when  expressions evaluate to  True   the  Task  is run  If any of the  when  expressions evaluate to  False   the  Task  is not run and the  Task  is listed in the   Skipped Tasks  section of the  PipelineRunStatus   pipelineruns md monitoring execution status    In these examples   first create file  task will only be executed if the  path  parameter is  README md    echo file exists  task will only be executed if the  exists  result from  check file  task is  yes  and  run lint  task will only be executed if the  lint config  optional workspace has been provided by a PipelineRun      yaml tasks      name  first create file     when          input     params path           operator  in         values    README md       taskRef        name  first create file     tasks      name  echo file exists     when          input     tasks check file results exists           operator  in         values    yes       taskRef        name  echo file exists     tasks      name  run lint     when          input     workspaces lint config bound           operator  in         values    true       taskRef        name  lint source     tasks      name  deploy in blue     when          input   blue          operator  in         values      params deployments           taskRef        name  deployment      For an end to end example  see  PipelineRun with  when  expressions     examples v1 pipelineruns pipelinerun with when expressions yaml    There are a lot of scenarios where  when  expressions can be really useful  Some of these are    Checking if the name of a git branch matches   Checking if the  Result  of a previous  Task  is as expected   Checking if a git file has changed in the previous commits   Checking if an image exists in the registry   Checking if the name of a CI job matches   Checking if an optional Workspace has been provided       Use CEL expression in WhenExpression     seedling     CEL in WhenExpression  is an  alpha  additional configs md alpha features  feature      The  enable cel in whenexpression  feature flag must be set to   true   to enable the use of  CEL  in  WhenExpression    CEL  Common Expression Language  is a declarative language designed for simplicity  speed  safety  and portability which can be used to express a wide variety of conditions and computations   You can define a CEL expression in  WhenExpression  to guard the execution of a  Task    The CEL expression must evaluate to either  true  or  false   You can use a single line of CEL string to replace current  WhenExpressions  s  input   operator   values   For example      yaml   current WhenExpressions when      input   foo      operator   in      values    foo    bar       input   duh      operator   notin      values    foo    bar      with cel when      cel    foo  in   foo    bar        cel      duh  in   foo    bar          CEL can offer more conditional functions  such as numeric comparisons  e g             etc   logic operators  e g   OR    AND    Regex Pattern Matching  For example      yaml   when        test coverage result is larger than 90        cel      tasks unit test results test coverage     0 9        params is not empty  or params2 is 8 5 or 8 6       cel      params param1               params param2       8 5        params param2       8 6         param branch matches pattern  release           cel      params branch   matches  release                  Variable substitution in CEL   CEL  supports  string substitutions  https   github com tektoncd pipeline blob main docs variables md variables available in a pipeline   you can reference string  array indexing or object value of a param result  For example      yaml   when        string result       cel     tasks unit test results test coverage    0 9        array indexing result       cel     tasks unit test results test coverage 0     0 9        object result key       cel      tasks objectTask results repo url   matches  github com tektoncd             string param       cel      params foo       foo         array indexing       cel      params branch 0        foo         object param key       cel      params repo url   matches  github com tektoncd              Note    the reference needs to be wrapped with single quotes  Whole  Array  and  Object  replacements are not supported yet  The following usage is not supported      yaml   when        cel    foo  in    params array params             cel    foo  in    params object params                wokeignore rule master     In addition to the cases listed above  you can craft any valid CEL expression as defined by the  cel spec language definition  https   github com google cel spec blob master doc langdef md     CEL  expression is validated at admission webhook and a validation error will be returned if the expression is invalid     Note    To use Tekton s  variable substitution  variables md   you need to wrap the reference with single quotes  This also means that if you pass another CEL expression via  params  or  results   it won t be executed  Therefore CEL injection is disallowed   For example      This is valid     params foo       foo  This is invalid    params foo      foo  CEL s variable substitution is not supported yet and thus invalid  params foo     foo            Guarding a  Task  and its dependent  Tasks   To guard a  Task  and its dependent Tasks    cascade the  when  expressions to the specific dependent  Tasks  to be guarded as well   compose the  Task  and its dependent  Tasks  as a unit to be guarded and executed together using  Pipelines  in  Pipelines         Cascade  when  expressions to the specific dependent  Tasks   Pick and choose which specific dependent  Tasks  to guard as well  and cascade the  when  expressions to those  Tasks    Taking the use case below  a user who wants to guard  manual approval  and its dependent  Tasks                                             tests                                                                                v                                  manual approval                                                                                v         approver                              build image                                                       v                                 v          slack msg                             deploy image      The user can design the  Pipeline  to solve their use case as such      yaml tasks         name  manual approval   runAfter        tests   when        input    params git action        operator  in       values            merge   taskRef      name  manual approval    name  build image   when        input    params git action        operator  in       values            merge   runAfter        manual approval   taskRef      name  build image    name  deploy image   when        input    params git action        operator  in       values            merge   runAfter        build image   taskRef      name  deploy image    name  slack msg   params        name  approver       value    tasks manual approval results approver    taskRef      name  slack msg            Compose using Pipelines in Pipelines  Compose a set of  Tasks  as a unit of execution using  Pipelines  in  Pipelines   which allows for guarding a  Task  and its dependent  Tasks   as a sub  Pipeline   using  when  expressions     Note     Pipelines  in  Pipelines  is an  experimental feature  https   github com tektoncd experimental tree main pipelines in pipelines   Taking the use case below  a user who wants to guard  manual approval  and its dependent  Tasks                                             tests                                                                                v                                  manual approval                                                                                v         approver                              build image                                                       v                                 v          slack msg                             deploy image      The user can design the  Pipelines  to solve their use case as such      yaml    sub pipeline  approve build deploy slack  tasks      name  manual approval     runAfter          integration tests     taskRef        name  manual approval      name  build image     runAfter          manual approval     taskRef        name  build image      name  deploy image     runAfter          build image     taskRef        name  deploy image      name  slack msg     params          name  approver         value    tasks manual approval results approver      taskRef        name  slack msg         main pipeline tasks         name  approve build deploy slack   runAfter        tests   when        input    params git action        operator  in       values            merge   taskRef      apiVersion  tekton dev v1beta1     kind  Pipeline     name  approve build deploy slack           Guarding a  Task  only  When  when  expressions evaluate to  False   the  Task  will be skipped and    The ordering dependent  Tasks  will be executed   The resource dependent  Tasks   and their dependencies  will be skipped because of missing  Results  from the skipped   parent  Task   When we add support for  default  Results   https   github com tektoncd community pull 240   then the   resource dependent  Tasks  may be executed if the default  Results  from the skipped parent  Task  are specified  In   addition  if a resource dependent  Task  needs a file from a guarded parent  Task  in a shared  Workspace   make sure   to handle the execution of the child  Task  in case the expected file is missing from the  Workspace  because the   guarded parent  Task  is skipped   On the other hand  the rest of the  Pipeline  will continue executing                                            tests                                                                                v                                  manual approval                                                                                v         approver                              build image                                                       v                                 v          slack msg                             deploy image      Taking the use case above  a user who wants to guard  manual approval  only can design the  Pipeline  as such      yaml tasks         name  manual approval   runAfter        tests   when        input    params git action        operator  in       values            merge   taskRef      name  manual approval    name  build image   runAfter        manual approval   taskRef      name  build image    name  deploy image   runAfter        build image   taskRef      name  deploy image    name  slack msg   params        name  approver       value    tasks manual approval results approver    taskRef      name  slack msg      If  manual approval  is skipped  execution of its dependent  Tasks    slack msg    build image  and  deploy image   would be unblocked regardless     build image  and  deploy image  should be executed successfully    slack msg  will be skipped because it is missing the  approver   Result  from  manual approval      dependents of  slack msg  would have been skipped too if it had any of them     if  manual approval  specifies a default  approver   Result   such as  None   then  slack msg  would be executed       supporting default  Results  is in progress  https   github com tektoncd community pull 240        Configuring the failure timeout  You can use the  Timeout  field in the  Task  spec within the  Pipeline  to set the timeout of the  TaskRun  that executes that  Task  within the  PipelineRun  that executes your  Pipeline   The  Timeout  value is a  duration  conforming to Go s   ParseDuration   https   golang org pkg time  ParseDuration  format  For example  valid values are  1h30m    1h    1m   and  60s      Note    If you do not specify a  Timeout  value  Tekton instead honors the timeout for the   PipelineRun   pipelineruns md configuring a pipelinerun    In the example below  the  build the image   Task  is configured to time out after 90 seconds      yaml spec    tasks        name  build the image       taskRef          name  build push       timeout   0h1m30s          Using variable substitution  Tekton provides variables to inject values into the contents of certain fields  The values you can inject come from a range of sources including other fields in the Pipeline  context sensitive information that Tekton provides  and runtime information received from a PipelineRun   The mechanism of variable substitution is quite simple   string replacement is performed by the Tekton Controller when a PipelineRun is executed   See the  complete list of variable substitutions for Pipelines    variables md variables available in a pipeline  and the  list of fields that accept substitutions    variables md fields that accept variable substitutions    For an end to end example  see  using context variables     examples v1 pipelineruns using context variables yaml        Using the  retries  and  retry count  variable substitutions  Tekton supports variable substitution for the   retries    using the retries field  parameter of  PipelineTask   Variables like  context pipelineTask retries  and  context task retry count  can be added to the parameters of a  PipelineTask    context pipelineTask retries  will be replaced by  retries  of the  PipelineTask   while  context task retry count  will be replaced by current retry number of the  PipelineTask       yaml params    name  pipelineTask retries   value     context pipelineTask retries   taskSpec    params      name  pipelineTask retries   steps      image  ubuntu     name  print if retries exhausted     script          if      context task retry count         params pipelineTask retries           then         echo  This is the last retry         fi       exit 1        Note    Every  PipelineTask  can only access its own  retries  and  retry count   These values aren t accessible for other  PipelineTask s      Using  Results   Tasks can emit   Results   tasks md emitting results  when they execute  A Pipeline can use these  Results  for two different purposes   1  A Pipeline can pass the  Result  of a  Task  into the  Parameters  or  when  expressions of another  2  A Pipeline can itself emit  Results  and include data from the  Results  of its Tasks       Note   Tekton does not enforce that results are produced at Task level  If a pipeline attempts to   consume a result that was declared by a Task  but not produced  it will fail   TEP 0048  https   github com tektoncd community blob main teps 0048 task results without results md    propopses introducing default values for results to help Pipeline authors manage this case       Passing one Task s  Results  into the  Parameters  or  when  expressions of another  Sharing  Results  between  Tasks  in a  Pipeline  happens via  variable substitution  variables md variables available in a pipeline    one  Task  emits a  Result  and another receives it as a  Parameter  with a variable such as    tasks  task name  results  result name     Pipeline support two new types of results and parameters  array    string  and object  map string string   Array result is a beta feature and can be enabled by setting  enable api fields  to  alpha  or  beta      Result Type   Parameter Type   Specification                                       enable api fields                                                                                string        string              tasks  task name  results  result name          stable                  array         array               tasks  task name  results  result name          alpha or beta           array         string              tasks  task name  results  result name  i       alpha or beta           object        object              tasks  task name  results  result name          alpha or beta                  object        string              tasks  task name  results  result name  key     alpha or beta                   Note    Whole Array and Object  Results   using star notation  cannot be referred in  script    When one  Task  receives the  Results  of another  there is a dependency created between those two  Tasks   In order for the receiving  Task  to get data from another  Task s   Result   the  Task  producing the  Result  must run first  Tekton enforces this  Task  ordering by ensuring that the  Task  emitting the  Result  executes before any  Task  that uses it   In the snippet below  a param is provided its value from the  commit   Result  emitted by the  checkout source   Task   Tekton will make sure that the  checkout source   Task  runs before this one      yaml params      name  foo     value     tasks checkout source results commit       name  array params     value     tasks checkout source results array results          name  array indexing params     value     tasks checkout source results array results 1        name  object params     value     tasks checkout source results object results          name  object element params     value     tasks checkout source results object results objectkey          Note    If  checkout source  exits successfully without initializing  commit   Result   the receiving  Task  fails and causes the  Pipeline  to fail with  InvalidTaskResultReference        unable to find result referenced by param  foo  in  task    Could not find result with name  commit  for task run  checkout source       In the snippet below  a  when  expression is provided its value from the  exists   Result  emitted by the  check file   Task   Tekton will make sure that the  check file   Task  runs before this one      yaml when      input     tasks check file results exists       operator  in     values    yes        For an end to end example  see   Task   Results  in a  PipelineRun      examples v1 pipelineruns task results example yaml    Note that  when  expressions are whitespace sensitive   In particular  when producing results intended for inputs to  when  expressions that may include newlines at their close  e g   cat    jq    you may wish to truncate them      yaml taskSpec    params      name  jsonQuery check   steps      image  ubuntu     name  store name in results     script          curl  s https   my json server typicode com typicode demo profile   jq  r  name   tr  d   n    tee   results name path           Emitting  Results  from a  Pipeline   A  Pipeline  can emit  Results  of its own for a variety of reasons   an external system may need to read them when the  Pipeline  is complete  they might summarise the most important  Results  from the  Pipeline s   Tasks   or they might simply be used to expose non critical messages generated during the execution of the  Pipeline    A  Pipeline s   Results  can be composed of one or many  Task   Results  emitted during the course of the  Pipeline s  execution  A  Pipeline   Result  can refer to its  Tasks    Results  using a variable of the form    tasks  task name  results  result name      After a  Pipeline  has executed the  PipelineRun  will be populated with the  Results  emitted by the  Pipeline   These will be written to the  PipelineRun s   status pipelineResults  field   In the example below  the  Pipeline  specifies a  results  entry with the name  sum  that references the  outputValue   Result  emitted by the  calculate sum   Task       yaml results      name  sum     description  the sum of all three operands     value    tasks calculate sum results outputValue       For an end to end example  see   Results  in a  PipelineRun      examples v1 pipelineruns pipelinerun results yaml    In the example below  the  Pipeline  collects array and object results from  Tasks       yaml     results          name  array results         type  array         description  whole array         value    tasks task1 results array results             name  array indexing results         type  string         description  array element         value    tasks task1 results array results 1           name  object results         type  object         description  whole object         value    tasks task2 results object results             name  object element         type  string         description  object element         value    tasks task2 results object results foo       For an end to end example see   Array and Object Results  in a  PipelineRun      examples v1 pipelineruns pipeline emitting results yaml    A  Pipeline Result  is not emitted if any of the following are true    A  PipelineTask  referenced by the  Pipeline Result  failed  The  PipelineRun  will also have failed    A  PipelineTask  referenced by the  Pipeline Result  was skipped    A  PipelineTask  referenced by the  Pipeline Result  didn t emit the referenced  Task Result   This should be considered a bug in the  Task  and  may fail a  PipelineTask  in future  https   github com tektoncd pipeline issues 3497     The  Pipeline Result  uses a variable that doesn t point to an actual  PipelineTask   This will result in an  InvalidTaskResultReference  validation error during  PipelineRun  execution    The  Pipeline Result  uses a variable that doesn t point to an actual result in a  PipelineTask   This will cause an  InvalidTaskResultReference  validation error during  PipelineRun  execution     Note    Since a  Pipeline Result  can contain references to multiple  Task Results   if any of those  Task Result  references are invalid the entire  Pipeline Result  is not emitted    Note    If a  PipelineTask  referenced by the  Pipeline Result  was skipped  the  Pipeline Result  will not be emitted and the  PipelineRun  will not fail due to a missing result      Configuring the  Task  execution order  You can connect  Tasks  in a  Pipeline  so that they execute in a Directed Acyclic Graph  DAG   Each  Task  in the  Pipeline  becomes a node on the graph that can be connected with an edge so that one will run before another and the execution of the  Pipeline  progresses to completion without getting stuck in an infinite loop   This is done using     resource dependencies         results    emitting results from a pipeline  of one  Task  being passed into  params  or  when  expressions of     another     ordering dependencies         runAfter    using the runafter field  clauses on the corresponding  Tasks   For example  the  Pipeline  defined as follows     yaml tasks    name  lint repo   taskRef      name  pylint   name  test app   taskRef      name  make test   name  build app   taskRef      name  kaniko build app   runAfter        test app   name  build frontend   taskRef      name  kaniko build frontend   runAfter        test app   name  deploy all   taskRef      name  deploy kubectl   runAfter        build app       build frontend      executes according to the following graph      none                                v            v      test app    lint repo                   v          v build app  build frontend                     v        v     deploy all      In particular   1  The  lint repo  and  test app   Tasks  have no  runAfter  clauses    and start executing simultaneously  2  Once  test app  completes  both  build app  and  build frontend  start    executing simultaneously since they both  runAfter  the  test app   Task   3  The  deploy all   Task  executes once both  build app  and  build frontend     complete  since it is supposed to  runAfter  them both  4  The entire  Pipeline  completes execution once both  lint repo  and  deploy all     complete execution      Specifying a display name  The  displayName  field is an optional field that allows you to add a user facing name of the  Pipeline  that can be used to populate a UI  For example      yaml spec    displayName   Code Scan    tasks        name  scan       taskRef          name  sonar scan         Adding a description  The  description  field is an optional field and can be used to provide description of the  Pipeline       Adding  Finally  to the  Pipeline   You can specify a list of one or more final tasks under  finally  section   finally  tasks are guaranteed to be executed in parallel after all  PipelineTasks  under  tasks  have completed regardless of success or error   finally  tasks are very similar to  PipelineTasks  under  tasks  section and follow the same syntax  Each  finally  task must have a  valid  https   kubernetes io docs concepts overview working with objects names  names   name  and a  taskRef or taskSpec  taskruns md specifying the target task   For example      yaml spec    tasks        name  tests       taskRef          name  integration test   finally        name  cleanup test       taskRef          name  cleanup          Specifying  displayName  in  finally  tasks  Similar to  specifying  displayName  in  pipelineTasks    specifying displayname in pipelinetasks    finally  tasks also allows to add a user facing name of the  finally  task that can be used to populate and distinguish in the dashboard  For example      yaml spec    finally        name  notification       displayName   Notify        taskRef          name  notification       name  notification using context variable       displayName   Notification from   context pipeline name         taskRef          name  notification      The  displayName  also allows you to parameterize the human readable name of your choice based on the  params   specifying parameters    the task results   consuming task execution results in finally   and  the context variables   context variables    Fully resolved  displayName  is also available in the status as part of the  pipelineRun status childReferences   The clients such as the dashboard  CLI  etc  can retrieve the  displayName  from the  childReferences   The  displayName  mainly drives a better user experience and at the same time it is not validated for the content or length by the controller       Specifying  Workspaces  in  finally  tasks   finally  tasks can specify  workspaces  workspaces md  which  PipelineTasks  might have utilized e g  a mount point for credentials held in Secrets  To support that requirement  you can specify one or more  Workspaces  in the  workspaces  field for the  finally  tasks similar to  tasks       yaml spec    workspaces        name  shared workspace   tasks        name  clone app source       taskRef          name  clone app repo to workspace       workspaces            name  shared workspace           workspace  shared workspace   finally        name  cleanup workspace       taskRef          name  cleanup workspace       workspaces            name  shared workspace           workspace  shared workspace          Specifying  Parameters  in  finally  tasks  Similar to  tasks   you can specify   Parameters   tasks md specifying parameters  in  finally  tasks      yaml spec    tasks        name  tests       taskRef          name  integration test   finally        name  report results       taskRef          name  report results       params            name  url           value   someURL           Specifying  matrix  in  finally  tasks     seedling     Matrix  is an  beta  additional configs md beta features  feature      The  enable api fields  feature flag can be set to   beta   to specify  Matrix  in a  PipelineTask    Similar to  tasks   you can also provide   Parameters   tasks md specifying parameters  through  matrix  in  finally  tasks      yaml spec    tasks        name  tests       taskRef          name  integration test   finally        name  report results       taskRef          name  report results       params            name  url           value   someURL        matrix          params            name  slack channel           value               foo               bar          include              name  build 1             params                  name  slack channel                 value   foo                  name  flags                 value    v       For further information  read   Matrix     matrix md        Consuming  Task  execution results in  finally    finally  tasks can be configured to consume  Results  of  PipelineTask  from the  tasks  section      yaml spec    tasks        name  clone app repo       taskRef          name  git clone   finally        name  discover git commit       params            name  commit           value    tasks clone app repo results commit        Note    The scheduling of such  finally  task does not change  it will still be executed in parallel with other  finally  tasks after all non  finally  tasks are done   The controller resolves task results before executing the  finally  task  discover git commit   If the task  clone app repo  failed before initializing  commit  or skipped with  when expression   guard task execution using when expressions  resulting in uninitialized task result  commit   the  finally  Task  discover git commit  will be included in the list of  skippedTasks  and continues executing rest of the  finally  tasks  The pipeline exits with  completion  instead of  success  if a  finally  task is added to the list of  skippedTasks        Consuming  Pipeline  result with  finally    finally  tasks can emit  Results  and these results emitted from the  finally  tasks can be configured in the  Pipeline Results   emitting results from a pipeline   References of  Results  from  finally  will follow the same naming conventions as referencing  Results  from  tasks        finally  finally pipelinetask name  result  result name           yaml results      name  comment count validate     value    finally check count results comment count validate  finally      name  check count     taskRef        name  example task name      In this example   pipelineResults  in  status  will show the name value pair for the result  comment count validate  which is produced in the  Task   example task name          PipelineRun  Status with  finally   With  finally    PipelineRun  status is calculated based on  PipelineTasks  under  tasks  section and  finally  tasks   Without  finally       PipelineTasks  under  tasks                                                                               PipelineRun  status   Reason                                                                                all  PipelineTasks  successful                                                                             true                   Succeeded      one or more  PipelineTasks   skipped   guard task execution using when expressions  and rest successful    true                   Completed      single failure of  PipelineTask                                                                            false                  failed        With  finally       PipelineTasks  under  tasks                                                                              finally  tasks                           PipelineRun  status   Reason                                                                                all  PipelineTask  successful                                                                            all  finally  tasks successful            true                   Succeeded      all  PipelineTask  successful                                                                            one or more failure of  finally  tasks    false                  Failed         one or more  PipelineTask   skipped   guard task execution using when expressions  and rest successful   all  finally  tasks successful            true                   Completed      one or more  PipelineTask   skipped   guard task execution using when expressions  and rest successful   one or more failure of  finally  tasks    false                  Failed         single failure of  PipelineTask                                                                          all  finally  tasks successful            false                  failed         single failure of  PipelineTask                                                                          one or more failure of  finally  tasks    false                  failed        Overall   PipelineRun  state transitioning is explained below for respective scenarios     All  PipelineTask  and  finally  tasks are successful   Started      Running      Succeeded    At least one  PipelineTask  skipped and rest successful    Started      Running      Completed    One  PipelineTask  failed   one or more  finally  tasks failed   Started      Running      Failed   Please refer to the  table  pipelineruns md monitoring execution status  under Monitoring Execution Status to learn about what kind of events are triggered based on the  Pipelinerun  status        Using Execution  Status  of  pipelineTask   A  pipeline  can check the status of a specific  pipelineTask  from the  tasks  section in  finally  through the task parameters      yaml finally      name  finaltask     params          name  task1Status         value     tasks task1 status       taskSpec        params            name  task1Status       steps            image  ubuntu           name  print task status           script                if     params task1Status      Failed                then               echo  Task1 has failed  continue processing the failure              fi      This kind of variable can have any one of the values from the following table     Status        Description                                                                                Succeeded     taskRun  for the  pipelineTask  completed successfully                                               Failed        taskRun  for the  pipelineTask  completed with a failure or cancelled by the user                    None         the  pipelineTask  has been skipped or no execution information available for the  pipelineTask     For an end to end example  see   status  in a  PipelineRun      examples v1 pipelineruns pipelinerun task execution status yaml        Using Aggregate Execution  Status  of All  Tasks   A  pipeline  can check an aggregate status of all the  tasks  section in  finally  through the task parameters      yaml finally      name  finaltask     params          name  aggregateTasksStatus         value     tasks status       taskSpec        params            name  aggregateTasksStatus       steps            image  ubuntu           name  check task status           script                if     params aggregateTasksStatus      Failed                then               echo  Looks like one or more tasks returned failure  continue processing the failure              fi      This kind of variable can have any one of the values from the following table     Status        Description                                                                                Succeeded    all  tasks  have succeeded                                                                                Failed       one ore more  tasks  failed                                                                                Completed    all  tasks  completed successfully including one or more skipped tasks                                                                 None         no aggregate execution status available  i e  none of the above   one or more  tasks  could be pending running cancelled timedout    For an end to end example  see     tasks status   usage in a  Pipeline      examples v1 pipelineruns pipelinerun task execution status yaml        Guard  finally   Task  execution using  when  expressions  Similar to  Tasks    finally   Tasks  can be guarded using   when  expressions   guard task execution using when expressions  that operate on static inputs or variables  Like in  Tasks    when  expressions in  finally   Tasks  can operate on  Parameters  and  Results   Unlike in  Tasks    when  expressions in  finally   tasks  can also operate on the   Execution Status    using execution status of pipelinetask  of  Tasks          when  expressions using  Parameters  in  finally   Tasks    when  expressions in  finally   Tasks  can utilize  Parameters  as demonstrated using   golang build   https   github com tektoncd catalog tree main task golang build 0 1  and   send to channel slack   https   github com tektoncd catalog tree main task send to channel slack 0 1  Catalog  Tasks       yaml apiVersion  tekton dev v1   or tekton dev v1beta1 kind  PipelineRun metadata    generateName  pipelinerun  spec    pipelineSpec      params          name  enable notifications         type  string         description  a boolean indicating whether the notifications should be sent     tasks          name  golang build         taskRef            name  golang build                 finally          name  notify build failure   executed only when build task fails and notifications are enabled         when              input    tasks golang build status              operator  in             values    Failed               input    params enable notifications              operator  in             values    true           taskRef            name  send to slack channel               params        name  enable notifications       value  true            when  expressions using  Results  in  finally   Tasks    when  expressions in  finally   tasks  can utilize  Results   as demonstrated using   git clone   https   github com tektoncd catalog tree main task git clone 0 2  and   github add comment   https   github com tektoncd catalog tree main task github add comment 0 2  Catalog  Tasks       yaml apiVersion  tekton dev v1   or tekton dev v1beta1 kind  PipelineRun metadata    generateName  pipelinerun  spec    pipelineSpec      tasks          name  git clone         taskRef            name  git clone         name  go build                 finally          name  notify commit sha   executed only when commit sha is not the expected sha         when              input    tasks git clone results commit              operator  notin             values     params expected sha           taskRef            name  github add comment               params        name  expected sha       value  54dd3984affab47f3018852e61a1a6f9946ecfa      If the  when  expressions in a  finally   task  use  Results  from a skipped or failed non finally  Tasks   then the  finally   task  would also be skipped and be included in the list of  Skipped Tasks  in the  Status    similarly to when using  Results  in other parts of the  finally   task    consuming task execution results in finally          when  expressions using  Execution Status  of  PipelineTask  in  finally   tasks    when  expressions in  finally   tasks  can utilize   Execution Status  of  PipelineTasks    using execution status of pipelinetask   as demonstrated using   golang build   https   github com tektoncd catalog tree main task golang build 0 1  and   send to channel slack   https   github com tektoncd catalog tree main task send to channel slack 0 1  Catalog  Tasks       yaml apiVersion  tekton dev v1   or tekton dev v1beta1 kind  PipelineRun metadata    generateName  pipelinerun  spec    pipelineSpec      tasks          name  golang build         taskRef            name  golang build                 finally          name  notify build failure   executed only when build task fails         when              input    tasks golang build status              operator  in             values    Failed           taskRef            name  send to slack channel                  For an end to end example  see  PipelineRun with  when  expressions     examples v1 pipelineruns pipelinerun with when expressions yaml          when  expressions using  Aggregate Execution Status  of  Tasks  in  finally   tasks    when  expressions in  finally   tasks  can utilize   Aggregate Execution Status  of  Tasks    using aggregate execution status of all tasks  as demonstrated      yaml finally      name  notify any failure   executed only when one or more tasks fail     when          input    tasks status          operator  in         values    Failed       taskRef        name  notify failure      For an end to end example  see  PipelineRun with  when  expressions     examples v1 pipelineruns pipelinerun with when expressions yaml        Known Limitations       Cannot configure the  finally  task execution order  It s not possible to configure or modify the execution order of the  finally  tasks  Unlike  Tasks  in a  Pipeline   all  finally  tasks run simultaneously and start executing once all  PipelineTasks  under  tasks  have settled which means no  runAfter  can be specified in  finally  tasks      Using Custom Tasks  Custom Tasks have been promoted from  v1alpha1  to  v1beta1   Starting from  v0 43 0  to  v0 46 0   Pipeline Controller is able to create either  v1alpha1  or  v1beta1  Custom Task gated by a feature flag  custom task version   defaulting to  v1beta1   You can set  custom task version  to  v1alpha1  or  v1beta1  to control which version to create   Starting from  v0 47 0   feature flag  custom task version  is removed and only  v1beta1  Custom Task will be supported  See the  migration doc  migrating v1alpha1 Run to v1beta1 CustomRun md  for details    Custom Tasks  https   github com tektoncd community blob main teps 0002 custom tasks md  can implement behavior that doesn t correspond directly to running a workload in a  Pod  on the cluster  For example  a custom task might execute some operation outside of the cluster and wait for its execution to complete   A  PipelineRun  starts a custom task by creating a   CustomRun   https   github com tektoncd pipeline blob main docs customruns md  instead of a  TaskRun   In order for a custom task to execute  there must be a custom task controller running on the cluster that is responsible for watching and updating  CustomRun s which reference their type       Specifying the target Custom Task  To specify the custom task type you want to execute  the  taskRef  field must include the custom task s  apiVersion  and  kind  as shown below  Using  apiVersion  will always create a  CustomRun   If  apiVersion  is set   kind  is required as well      yaml spec    tasks        name  run custom task       taskRef          apiVersion  example dev v1alpha1         kind  Example      This creates a  Run CustomRun  of a custom task of type  Example  in the  example dev  API group with the version  v1alpha1    Validation error will be returned if  apiVersion  or  kind  is missing   You can also specify the  name  of a custom task resource object previously defined in the cluster      yaml spec    tasks        name  run custom task       taskRef          apiVersion  example dev v1alpha1         kind  Example         name  myexample      If the  taskRef  specifies a name  the custom task controller should look up the  Example  resource with that name and use that object to configure the execution   If the  taskRef  does not specify a name  the custom task controller might support some default behavior for executing unnamed tasks       Specifying a Custom Task Spec in line  or embedded     For  v1alpha1 Run       yaml spec    tasks        name  run custom task       taskSpec          apiVersion  example dev v1alpha1         kind  Example         spec            field1  value1           field2  value2        For  v1beta1 CustomRun       yaml spec    tasks        name  run custom task       taskSpec          apiVersion  example dev v1alpha1         kind  Example         customSpec            field1  value1           field2  value2      If the custom task controller supports the in line or embedded task spec  this will create a  Run CustomRun  of a custom task of type  Example  in the  example dev  API group with the version  v1alpha1    If the  taskSpec  is not supported  the custom task controller should produce proper validation errors   Please take a look at the developer guide for custom controllers supporting  taskSpec      guidance for  Run   runs md developer guide for custom controllers supporting spec     guidance for  CustomRun   customruns md developer guide for custom controllers supporting customspec    taskSpec  support for  pipelineRun  was designed and discussed in  TEP 0061  https   github com tektoncd community blob main teps 0061 allow custom task to be embedded in pipeline md       Specifying parameters  If a custom task supports   parameters   tasks md specifying parameters   you can use the  params  field to specify their values      yaml spec    tasks        name  run custom task       taskRef          apiVersion  example dev v1alpha1         kind  Example         name  myexample       params            name  foo           value  bah         Context Variables  The  Parameters  in the  Params  field will accept  context variables  variables md  that will be substituted  including      PipelineRun  name  namespace and uid    Pipeline  name    PipelineTask  retries     yaml spec    tasks        name  run custom task       taskRef          apiVersion  example dev v1alpha1         kind  Example         name  myexample       params            name  foo           value    context pipeline name           Specifying matrix     seedling     Matrix  is an  alpha  additional configs md alpha features  feature      The  enable api fields  feature flag must be set to   alpha   to specify  Matrix  in a  PipelineTask    If a custom task supports   parameters   tasks md specifying parameters   you can use the  matrix  field to specify their values  if you want to fan      yaml spec    tasks        name  run custom task       taskRef          apiVersion  example dev v1alpha1         kind  Example         name  myexample       params            name  foo           value  bah       matrix          params            name  bar           value                qux               thud         include              name  build 1             params                name  common package               value  path to common pkg      For further information  read   Matrix     matrix md        Specifying workspaces  If the custom task supports it  you can provide   Workspaces   workspaces md using workspaces in tasks  to share data with the custom task      yaml spec    tasks        name  run custom task       taskRef          apiVersion  example dev v1alpha1         kind  Example         name  myexample       workspaces            name  my workspace      Consult the documentation of the custom task that you are using to determine whether it supports workspaces and how to name them       Using  Results   If the custom task produces results  you can reference them in a Pipeline using the normal syntax     tasks  task name  results  result name          Specifying  Timeout         v1alpha1 Run  If the custom task supports it as  we recommended  runs md developer guide for custom controllers supporting timeout   you can provide  timeout  to specify the maximum running time of a  CustomRun   including all retry attempts or other operations          v1beta1 CustomRun  If the custom task supports it as  we recommended  customruns md developer guide for custom controllers supporting timeout   you can provide  timeout  to specify the maximum running time of one  CustomRun  execution      yaml spec    tasks        name  run custom task       timeout  2s       taskRef          apiVersion  example dev v1alpha1         kind  Example         name  myexample      Consult the documentation of the custom task that you are using to determine whether it supports  Timeout        Specifying  Retries  If the custom task supports it  you can provide  retries  to specify how many times you want to retry the custom task      yaml spec    tasks        name  run custom task       retries  2       taskRef          apiVersion  example dev v1alpha1         kind  Example         name  myexample      Consult the documentation of the custom task that you are using to determine whether it supports  Retries        Known Custom Tasks  We try to list as many known Custom Tasks as possible here so that users can easily find what they want  Please feel free to share the Custom Task you implemented in this table        v1beta1 CustomRun    Custom Task                        Description                                                                                Wait Task Beta  wait task beta    Waits a given amount of time before succeeding  specified by an input parameter named duration  Support  timeout  and  retries        Approvals  approvals beta   Pauses the execution of  PipelineRuns  and waits for manual approvals  Version 0 6 0 and up          v1alpha1 Run    Custom Task                                        Description                                                                                Pipeline Loops  pipeline loops                    Runs a  Pipeline  in a loop with varying  Parameter  values                                                     Common Expression Language  cel                   Provides Common Expression Language support in Tekton Pipelines                                                 Wait  wait                                        Waits a given amount of time  specified by a  Parameter  named  duration   before succeeding                    Approvals  approvals alpha                        Pauses the execution of  PipelineRuns  and waits for manual approvals  Version up to  and including  0 5 0      Pipelines in Pipelines  pipelines in pipelines    Defines and executes a  Pipeline  in a  Pipeline                                                                Task Group  task group                            Groups  Tasks  together as a  Task                                                                              Pipeline in a Pod  pipeline in pod                Runs  Pipeline  in a  Pod                                                                                pipeline loops   https   github com tektoncd experimental tree f60e1cd8ce22ed745e335f6f547bb9a44580dc7c pipeline loops  task loops   https   github com tektoncd experimental tree f60e1cd8ce22ed745e335f6f547bb9a44580dc7c task loops  cel   https   github com tektoncd experimental tree f60e1cd8ce22ed745e335f6f547bb9a44580dc7c cel  wait   https   github com tektoncd experimental tree f60e1cd8ce22ed745e335f6f547bb9a44580dc7c wait task  approvals alpha   https   github com automatiko io automatiko approval task tree v0 5 0  approvals beta   https   github com automatiko io automatiko approval task tree v0 6 1  task group   https   github com openshift pipelines tekton task group tree 39823f26be8f59504f242a45b9f2e791d4b36e1c  pipelines in pipelines   https   github com tektoncd experimental tree f60e1cd8ce22ed745e335f6f547bb9a44580dc7c pipelines in pipelines  pipeline in pod   https   github com tektoncd experimental tree f60e1cd8ce22ed745e335f6f547bb9a44580dc7c pipeline in pod  wait task beta   https   github com tektoncd pipeline tree a127323da31bcb933a04a6a1b5dbb6e0411e3dc1 test custom task ctrls wait task beta     Code examples  For a better understanding of  Pipelines   study  our code examples  https   github com tektoncd pipeline tree main examples         Except as otherwise noted  the content of this page is licensed under the  Creative Commons Attribution 4 0 License  https   creativecommons org licenses by 4 0    and code samples are licensed under the  Apache 2 0 License  https   www apache org licenses LICENSE 2 0