Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[TEP-0048] Add support for default results #5620

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 40 additions & 2 deletions docs/pipeline-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -1669,7 +1669,7 @@ Used to distinguish between a single string and an array of strings.</p>
<h3 id="tekton.dev/v1.ParamValue">ParamValue
</h3>
<p>
(<em>Appears on:</em><a href="#tekton.dev/v1.Param">Param</a>, <a href="#tekton.dev/v1.ParamSpec">ParamSpec</a>, <a href="#tekton.dev/v1.PipelineResult">PipelineResult</a>, <a href="#tekton.dev/v1.PipelineRunResult">PipelineRunResult</a>, <a href="#tekton.dev/v1.TaskRunResult">TaskRunResult</a>)
(<em>Appears on:</em><a href="#tekton.dev/v1.Param">Param</a>, <a href="#tekton.dev/v1.ParamSpec">ParamSpec</a>, <a href="#tekton.dev/v1.PipelineResult">PipelineResult</a>, <a href="#tekton.dev/v1.PipelineRunResult">PipelineRunResult</a>, <a href="#tekton.dev/v1.TaskResult">TaskResult</a>, <a href="#tekton.dev/v1.TaskRunResult">TaskRunResult</a>)
</p>
<div>
<p>ResultValue is a type alias of ParamValue</p>
Expand Down Expand Up @@ -4476,6 +4476,22 @@ string
<p>Description is a human-readable description of the result</p>
</td>
</tr>
<tr>
<td>
<code>default</code><br/>
<em>
<a href="#tekton.dev/v1.ParamValue">
ParamValue
</a>
</em>
</td>
<td>
<em>(Optional)</em>
<p>This is an alpha field. You must set the &ldquo;enable-api-fields&rdquo; feature flag to &ldquo;alpha&rdquo;
for this field to be supported.</p>
<p>Default is the value a result produces if no result is produced by Task</p>
</td>
</tr>
</tbody>
</table>
<h3 id="tekton.dev/v1.TaskRunDebug">TaskRunDebug
Expand Down Expand Up @@ -8761,7 +8777,7 @@ Used to distinguish between a single string and an array of strings.</p>
<h3 id="tekton.dev/v1beta1.ParamValue">ParamValue
</h3>
<p>
(<em>Appears on:</em><a href="#tekton.dev/v1beta1.Param">Param</a>, <a href="#tekton.dev/v1beta1.ParamSpec">ParamSpec</a>, <a href="#tekton.dev/v1beta1.PipelineResult">PipelineResult</a>, <a href="#tekton.dev/v1beta1.PipelineRunResult">PipelineRunResult</a>, <a href="#tekton.dev/v1beta1.TaskRunResult">TaskRunResult</a>)
(<em>Appears on:</em><a href="#tekton.dev/v1beta1.Param">Param</a>, <a href="#tekton.dev/v1beta1.ParamSpec">ParamSpec</a>, <a href="#tekton.dev/v1beta1.PipelineResult">PipelineResult</a>, <a href="#tekton.dev/v1beta1.PipelineRunResult">PipelineRunResult</a>, <a href="#tekton.dev/v1beta1.TaskResult">TaskResult</a>, <a href="#tekton.dev/v1beta1.TaskRunResult">TaskRunResult</a>)
</p>
<div>
<p>ResultValue is a type alias of ParamValue</p>
Expand Down Expand Up @@ -12417,8 +12433,30 @@ string
<p>Description is a human-readable description of the result</p>
</td>
</tr>
<tr>
<td>
<code>default</code><br/>
<em>
<a href="#tekton.dev/v1beta1.ParamValue">
ParamValue
</a>
</em>
</td>
<td>
<em>(Optional)</em>
<p>This is an alpha field. You must set the &ldquo;enable-api-fields&rdquo; feature flag to &ldquo;alpha&rdquo;
for this field to be supported.</p>
<p>Default is the value a result produces if no result is produced by Task</p>
</td>
</tr>
</tbody>
</table>
<h3 id="tekton.dev/v1beta1.TaskRunConditionType">TaskRunConditionType
(<code>string</code> alias)</h3>
<div>
<p>TaskRunConditionType is an enum used to store TaskRun custom conditions
conditions such as one used in spire results verification</p>
</div>
<h3 id="tekton.dev/v1beta1.TaskRunDebug">TaskRunDebug
</h3>
<p>
Expand Down
42 changes: 42 additions & 0 deletions docs/tasks.md
Original file line number Diff line number Diff line change
Expand Up @@ -847,6 +847,48 @@ available size will less than 4096 bytes.
As a general rule-of-thumb, if a result needs to be larger than a kilobyte, you should likely use a
[`Workspace`](#specifying-workspaces) to store and pass it between `Tasks` within a `Pipeline`.

#### Default value

> **Note**: This is an alpha gated feature.

Results declarations (within Tasks and Pipelines) can include default values which will be used if the Result is
not produced, for example to specify defaults for both string params and array params
([full example](../examples/v1beta1/taskruns/alpha/default-result.yaml)) :

```yaml
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: task-with-default-result
spec:
results:
- name: branch
default: main
```

**Note**: If a Task doesn't specify any default value for a particular `Result`
and also fails to emit that `Result`, in that case, the following `Task` is going
to be marked as `Failed` as specified in [TEP-0048](https://github.com/tektoncd/community/blob/main/teps/0048-task-results-without-results.md). Below is the example in which the TaskRun
is going to fail as one of the Result wasn't produced.
vinamra28 marked this conversation as resolved.
Show resolved Hide resolved

```yaml
apiVersion: tekton.dev/v1beta1
kind: TaskRun
metadata:
generateName: test-tr-
spec:
taskSpec:
results:
- name: result1
description: will be produced
- name: result2
description: will not be produced
steps:
- name: failing-step
image: busybox
script: "echo -n 123 | tee $(results.result1.path)"
```

### Specifying `Volumes`

Specifies one or more [`Volumes`](https://kubernetes.io/docs/concepts/storage/volumes/) that the `Steps` in your
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
name: pipelinerun-emit-default-results
spec:
pipelineSpec:
tasks:
- name: task1
taskSpec:
results:
- name: array-results
type: array
description: The array results
default:
- "1"
- "2"
- "3"
steps:
- name: write-array
image: bash:latest
script: |
#!/usr/bin/env bash
echo -n "this script won't emit array result"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted to highlight the issue #3497 which probably seems to go against this example?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The discussion in that issue hasn't come to a conclusion so this might be ok for now. I wonder if your examples could genuinely error out and the steps have an onError --> continue and then have the default result use?

- name: task2
taskSpec:
results:
- name: object-results
type: object
description: The object results
properties:
foo: {type: string}
hello: {type: string}
default:
foo: bar
hello: world
steps:
- name: write-array
image: bash:latest
script: |
#!/usr/bin/env bash
echo -n "this script won't emit object result"
results:
- name: array-results
type: array
description: whole array
value: $(tasks.task1.results.array-results[*])
- name: array-results-from-array-indexing-and-object-elements
type: array
description: whole array
value:
[
"$(tasks.task1.results.array-results[0])",
"$(tasks.task2.results.object-results.foo)",
]
- 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-results-from-array-indexing-and-object-elements
type: object
description: whole object
value:
key1: $(tasks.task1.results.array-results[1])
key2: $(tasks.task2.results.object-results.hello)
- name: object-element
type: string
description: object element
value: $(tasks.task2.results.object-results.foo)
33 changes: 33 additions & 0 deletions examples/v1beta1/taskruns/alpha/default-result.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
apiVersion: tekton.dev/v1beta1
kind: TaskRun
metadata:
generateName: default-result-run-
spec:
taskSpec:
results:
- name: result1
description: will be produced
- name: string-result
description: will not be produced by step but has default value
default: "string value"
- name: array-result
description: default array result will be produced
default:
- "foo"
- "bar"
- name: eight-results
type: object
properties:
IMAGE_URL: {type: string}
IMAGE_DIGEST: {type: string}
default:
IMAGE_URL: "default.com"
IMAGE_DIGEST: "defaultsha"
steps:
- name: failing-step
onError: continue
image: busybox
script: |
echo -n 123 | tee $(results.result1.path)
exit 1
echo -n 456 | tee $(results.string-result.path)
Comment on lines +30 to +33
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

8 changes: 7 additions & 1 deletion pkg/apis/pipeline/v1/openapi_generated.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions pkg/apis/pipeline/v1/result_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@ type TaskResult struct {
// Description is a human-readable description of the result
// +optional
Description string `json:"description,omitempty"`

// This is an alpha field. You must set the "enable-api-fields" feature flag to "alpha"
// for this field to be supported.
//
// Default is the value a result produces if no result is produced by Task
// +optional
Default *ResultValue `json:"default,omitempty"`
}

// TaskRunResult used to describe the results of a task
Expand Down
4 changes: 4 additions & 0 deletions pkg/apis/pipeline/v1/swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -1615,6 +1615,10 @@
"name"
],
"properties": {
"default": {
"description": "This is an alpha field. You must set the \"enable-api-fields\" feature flag to \"alpha\" for this field to be supported.\n\nDefault is the value a result produces if no result is produced by Task",
"$ref": "#/definitions/v1.ParamValue"
},
"description": {
"description": "Description is a human-readable description of the result",
"type": "string"
Expand Down
5 changes: 5 additions & 0 deletions pkg/apis/pipeline/v1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 7 additions & 1 deletion pkg/apis/pipeline/v1beta1/openapi_generated.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

34 changes: 34 additions & 0 deletions pkg/apis/pipeline/v1beta1/result_conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,23 @@ func (r TaskResult) convertTo(ctx context.Context, sink *v1.TaskResult) {
properties[k] = v1.PropertySpec{Type: v1.ParamType(v.Type)}
}
sink.Properties = properties
if r.Default != nil {
sink.Default = &v1.ParamValue{
Type: v1.ParamType(r.Default.Type),
}
switch r.Default.Type {
case ParamTypeString:
sink.Default.StringVal = r.Default.StringVal
case ParamTypeArray:
sink.Default.ArrayVal = r.Default.ArrayVal
default: // In case of ParamTypeObject
defaults := make(map[string]string)
for k, v := range r.Default.ObjectVal {
defaults[k] = v
}
sink.Default.ObjectVal = defaults
}
}
}

func (r *TaskResult) convertFrom(ctx context.Context, source v1.TaskResult) {
Expand All @@ -26,4 +43,21 @@ func (r *TaskResult) convertFrom(ctx context.Context, source v1.TaskResult) {
properties[k] = PropertySpec{Type: ParamType(v.Type)}
}
r.Properties = properties
if source.Default != nil {
vinamra28 marked this conversation as resolved.
Show resolved Hide resolved
r.Default = &ParamValue{
Type: ParamType(source.Default.Type),
}
switch source.Default.Type {
case v1.ParamTypeString:
r.Default.StringVal = source.Default.StringVal
case v1.ParamTypeArray:
r.Default.ArrayVal = source.Default.ArrayVal
default:
defaults := make(map[string]string)
for k, v := range source.Default.ObjectVal {
defaults[k] = v
}
r.Default.ObjectVal = defaults
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems to be the same logic as in lines 18:34. May be wrap it into a function and call it here?

}
7 changes: 7 additions & 0 deletions pkg/apis/pipeline/v1beta1/result_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@ type TaskResult struct {
// Description is a human-readable description of the result
// +optional
Description string `json:"description,omitempty"`

// This is an alpha field. You must set the "enable-api-fields" feature flag to "alpha"
// for this field to be supported.
//
// Default is the value a result produces if no result is produced by Task
// +optional
Default *ResultValue `json:"default,omitempty"`
}

// TaskRunResult used to describe the results of a task
Expand Down
5 changes: 5 additions & 0 deletions pkg/apis/pipeline/v1beta1/result_validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ func (tr TaskResult) Validate(ctx context.Context) (errs *apis.FieldError) {
if !resultNameFormatRegex.MatchString(tr.Name) {
return apis.ErrInvalidKeyName(tr.Name, "name", fmt.Sprintf("Name must consist of alphanumeric characters, '-', '_', and must start and end with an alphanumeric character (e.g. 'MyName', or 'my-name', or 'my_name', regex used for validation is '%s')", ResultNameFormat))
}
// Default results in alpha feature
if tr.Default != nil {
errs = errs.Also(version.ValidateEnabledAPIFields(ctx, "default results", config.AlphaAPIFields))
return errs
}
// Array and Object is alpha feature
if tr.Type == ResultsTypeArray || tr.Type == ResultsTypeObject {
errs := validateObjectResult(tr)
Expand Down
Loading