Skip to content

Commit

Permalink
Referencing StepActions in Steps
Browse files Browse the repository at this point in the history
This PR allows the Step to reference a StepAction CRD deployed on the cluster. This capability is gated behind a feature flag `enable-step-actions`.  Remote resolution of StepActions will be implemented in a follow-up PR.

This is the second item on the implementation Issue #7259
  • Loading branch information
chitrangpatel committed Oct 25, 2023
1 parent 8123d63 commit 2533c02
Show file tree
Hide file tree
Showing 25 changed files with 1,462 additions and 25 deletions.
86 changes: 86 additions & 0 deletions docs/pipeline-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -3270,6 +3270,35 @@ github.com/tektoncd/pipeline/pkg/apis/config.FeatureFlags
</tr>
</tbody>
</table>
<h3 id="tekton.dev/v1.Ref">Ref
</h3>
<p>
(<em>Appears on:</em><a href="#tekton.dev/v1.Step">Step</a>)
</p>
<div>
<p>Ref can be used to refer to a specific instance of a StepAction.</p>
</div>
<table>
<thead>
<tr>
<th>Field</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<code>name</code><br/>
<em>
string
</em>
</td>
<td>
<p>Name of the referenced step</p>
</td>
</tr>
</tbody>
</table>
<h3 id="tekton.dev/v1.RefSource">RefSource
</h3>
<p>
Expand Down Expand Up @@ -4353,6 +4382,20 @@ StepOutputConfig
<p>Stores configuration for the stderr stream of the step.</p>
</td>
</tr>
<tr>
<td>
<code>ref</code><br/>
<em>
<a href="#tekton.dev/v1.Ref">
Ref
</a>
</em>
</td>
<td>
<em>(Optional)</em>
<p>Contains the reference to an existing stepaction</p>
</td>
</tr>
</tbody>
</table>
<h3 id="tekton.dev/v1.StepOutputConfig">StepOutputConfig
Expand Down Expand Up @@ -11758,6 +11801,35 @@ github.com/tektoncd/pipeline/pkg/apis/config.FeatureFlags
</tr>
</tbody>
</table>
<h3 id="tekton.dev/v1beta1.Ref">Ref
</h3>
<p>
(<em>Appears on:</em><a href="#tekton.dev/v1beta1.Step">Step</a>)
</p>
<div>
<p>Ref can be used to refer to a specific instance of a StepAction.</p>
</div>
<table>
<thead>
<tr>
<th>Field</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<code>name</code><br/>
<em>
string
</em>
</td>
<td>
<p>Name of the referenced step</p>
</td>
</tr>
</tbody>
</table>
<h3 id="tekton.dev/v1beta1.RefSource">RefSource
</h3>
<p>
Expand Down Expand Up @@ -12954,6 +13026,20 @@ StepOutputConfig
<p>Stores configuration for the stderr stream of the step.</p>
</td>
</tr>
<tr>
<td>
<code>ref</code><br/>
<em>
<a href="#tekton.dev/v1beta1.Ref">
Ref
</a>
</em>
</td>
<td>
<em>(Optional)</em>
<p>Contains the reference to an existing stepaction</p>
</td>
</tr>
</tbody>
</table>
<h3 id="tekton.dev/v1beta1.StepOutputConfig">StepOutputConfig
Expand Down
84 changes: 84 additions & 0 deletions docs/stepactions.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,87 @@ spec:
command: ["ls"]
args:: ["-lh"]
```
## Referencing a StepAction
`StepActions` can be referenced from the `Step` using the `ref` field, as follows:

```yaml
apiVersion: tekton.dev/v1
kind: TaskRun
metadata:
name: step-action-run
spec:
TaskSpec:
steps:
- name: action-runner
ref:
name: step-action
```

Upon resolution and execution of the `TaskRun`, the `Status` will look something like:

```yaml
status:
completionTime: "2023-10-24T20:28:42Z"
conditions:
- lastTransitionTime: "2023-10-24T20:28:42Z"
message: All Steps have completed executing
reason: Succeeded
status: "True"
type: Succeeded
podName: step-action-run-pod
provenance:
featureFlags:
EnableStepActions: true
...
startTime: "2023-10-24T20:28:32Z"
steps:
- container: step-action-runner
imageID: docker.io/library/alpine@sha256:eece025e432126ce23f223450a0326fbebde39cdf496a85d8c016293fc851978
name: action-runner
terminated:
containerID: containerd://46a836588967202c05b594696077b147a0eb0621976534765478925bb7ce57f6
exitCode: 0
finishedAt: "2023-10-24T20:28:42Z"
reason: Completed
startedAt: "2023-10-24T20:28:42Z"
taskSpec:
steps:
- computeResources: {}
image: alpine
name: action-runner
script: |
echo "I am a Step Action!!!"
```

If a `Step` is referencing a `StepAction`, it cannot contain the fields supported by `StepActions`. This includes:
- `image`
- `command`
- `args`
- `script`
- `env`

Using any of the above fields and referencing a `StepAction` in the same `Step` is not allowed and will cause an validation error.

```yaml
# This is not allowed and will result in a validation error.
# Because the image is expected to be provided by the StepAction
# and not inlined.
apiVersion: tekton.dev/v1
kind: TaskRun
metadata:
name: step-action-run
spec:
TaskSpec:
steps:
- name: action-runner
ref:
name: step-action
image: ubuntu
```
Executing the above `TaskRun` will result in an error that looks like:

```
Error from server (BadRequest): error when creating "STDIN": admission webhook "validation.webhook.pipeline.tekton.dev" denied the request: validation failed: image cannot be used with Ref: spec.taskSpec.steps[0].image
```
19 changes: 19 additions & 0 deletions examples/v1/taskruns/alpha/stepaction.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
apiVersion: tekton.dev/v1alpha1
kind: StepAction
metadata:
name: step-action
spec:
image: alpine
script: |
echo "I am a Step Action!!!"
---
apiVersion: tekton.dev/v1
kind: TaskRun
metadata:
name: step-action-run
spec:
TaskSpec:
steps:
- name: action-runner
ref:
name: step-action
9 changes: 9 additions & 0 deletions pkg/apis/pipeline/v1/container_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,15 @@ type Step struct {
// Stores configuration for the stderr stream of the step.
// +optional
StderrConfig *StepOutputConfig `json:"stderrConfig,omitempty"`
// Contains the reference to an existing stepaction
//+optional
Ref *Ref `json:"ref,omitempty"`
}

// Ref can be used to refer to a specific instance of a StepAction.
type Ref struct {
// Name of the referenced step
Name string `json:"name,omitempty"`
}

// OnErrorType defines a list of supported exiting behavior of a container on error
Expand Down
29 changes: 28 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.

14 changes: 14 additions & 0 deletions pkg/apis/pipeline/v1/swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -1093,6 +1093,16 @@
}
}
},
"v1.Ref": {
"description": "Ref can be used to refer to a specific instance of a StepAction.",
"type": "object",
"properties": {
"name": {
"description": "Name of the referenced step",
"type": "string"
}
}
},
"v1.RefSource": {
"description": "RefSource contains the information that can uniquely identify where a remote built definition came from i.e. Git repositories, Tekton Bundles in OCI registry and hub.",
"type": "object",
Expand Down Expand Up @@ -1445,6 +1455,10 @@
"description": "OnError defines the exiting behavior of a container on error can be set to [ continue | stopAndFail ]",
"type": "string"
},
"ref": {
"description": "Contains the reference to an existing stepaction",
"$ref": "#/definitions/v1.Ref"
},
"script": {
"description": "Script is the contents of an executable file to execute.\n\nIf Script is not empty, the Step cannot have an Command and the Args will be passed to the Script.",
"type": "string"
Expand Down
48 changes: 42 additions & 6 deletions pkg/apis/pipeline/v1/task_validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -268,17 +268,53 @@ func validateSteps(ctx context.Context, steps []Step) (errs *apis.FieldError) {
}

func validateStep(ctx context.Context, s Step, names sets.String) (errs *apis.FieldError) {
if s.Image == "" {
errs = errs.Also(apis.ErrMissingField("Image"))
}

if s.Script != "" {
if s.Ref != nil {
if !config.FromContextOrDefaults(ctx).FeatureFlags.EnableStepActions {
return apis.ErrGeneric("feature flag %s should be set to true to reference StepActions in Steps.", config.EnableStepActions)
}
if s.Image != "" {
errs = errs.Also(&apis.FieldError{
Message: "image cannot be used with Ref",
Paths: []string{"image"},
})
}
if len(s.Command) > 0 {
errs = errs.Also(&apis.FieldError{
Message: "script cannot be used with command",
Message: "command cannot be used with Ref",
Paths: []string{"command"},
})
}
if len(s.Args) > 0 {
errs = errs.Also(&apis.FieldError{
Message: "args cannot be used with Ref",
Paths: []string{"args"},
})
}
if s.Script != "" {
errs = errs.Also(&apis.FieldError{
Message: "script cannot be used with Ref",
Paths: []string{"script"},
})
}
if s.Env != nil {
errs = errs.Also(&apis.FieldError{
Message: "env cannot be used with Ref",
Paths: []string{"env"},
})
}
} else {
if s.Image == "" {
errs = errs.Also(apis.ErrMissingField("Image"))
}

if s.Script != "" {
if len(s.Command) > 0 {
errs = errs.Also(&apis.FieldError{
Message: "script cannot be used with command",
Paths: []string{"script"},
})
}
}
}

if s.Name != "" {
Expand Down
Loading

0 comments on commit 2533c02

Please sign in to comment.