From 80ae859f9b8ef64e26c0b1a7a73a068f523c709a Mon Sep 17 00:00:00 2001 From: Jerop Date: Fri, 18 Sep 2020 13:59:58 -0400 Subject: [PATCH] When Expressions Status When a Task is skipped because its When Expressions evaluated to false, its resolved When Expressions are listed alongside the PipelineTaskName in the SkippedTasks section of the PipelineRunStatus. When a Task is executed bacause its When Expressions evaluate to true, its resolved When Expressions are listed in the TaskRuns section of the PipelineRunStatus. Further details in https://github.com/tektoncd/community/blob/master/teps/0007-conditions-beta.md#status-1 Closes https://github.com/tektoncd/pipeline/issues/3139 --- docs/pipelineruns.md | 18 ++++++- .../pipeline/v1beta1/pipelinerun_types.go | 6 +++ .../pipeline/v1beta1/zz_generated.deepcopy.go | 18 ++++++- .../pipelinerun/pipelinerun_test.go | 52 ++++++++++++++++++- .../pipelinerun/resources/pipelinerunstate.go | 9 +++- 5 files changed, 96 insertions(+), 7 deletions(-) diff --git a/docs/pipelineruns.md b/docs/pipelineruns.md index ab13668b9d7..c7429fb5f0d 100644 --- a/docs/pipelineruns.md +++ b/docs/pipelineruns.md @@ -458,8 +458,8 @@ False|PipelineRunTimeout|Yes|The `PipelineRun` timed out. When a `PipelineRun` changes status, [events](events.md#pipelineruns) are triggered accordingly. When a `PipelineRun` has `Tasks` with [WhenExpressions](pipelines.md#guard-task-execution-using-whenexpressions): -- If the `WhenExpressions` evaluate to `true`, the `Task` is executed and the `TaskRun` will be listed in the `Task Runs` section of the `status` of the `PipelineRun`. -- If the `WhenExpressions` evaluate to `false`, the `Task` is skipped and it is listed in the `Skipped Tasks` section of the `status` of the `PipelineRun`. +- If the `WhenExpressions` evaluate to `true`, the `Task` is executed then the `TaskRun` and its resolved `WhenExpressions` will be listed in the `Task Runs` section of the `status` of the `PipelineRun`. +- If the `WhenExpressions` evaluate to `false`, the `Task` is skipped then its name and its resolved `WhenExpressions` will be listed in the `Skipped Tasks` section of the `status` of the `PipelineRun`. ```yaml Conditions: @@ -470,11 +470,25 @@ Conditions: Type: Succeeded Skipped Tasks: Name: skip-this-task + When Expressions: + Input: foo + Operator: in + Values: + bar + Input: foo + Operator: notin + Values: + foo Task Runs: pipelinerun-to-skip-task-run-this-task-r2djj: Pipeline Task Name: run-this-task Status: ... + When Expressions: + Input: foo + Operator: in + Values: + foo ``` ## Cancelling a `PipelineRun` diff --git a/pkg/apis/pipeline/v1beta1/pipelinerun_types.go b/pkg/apis/pipeline/v1beta1/pipelinerun_types.go index ab05558931b..9a37bbccc83 100644 --- a/pkg/apis/pipeline/v1beta1/pipelinerun_types.go +++ b/pkg/apis/pipeline/v1beta1/pipelinerun_types.go @@ -342,6 +342,9 @@ type PipelineRunStatusFields struct { type SkippedTask struct { // Name is the Pipeline Task name Name string `json:"name"` + // WhenExpressions is the list of checks guarding the execution of the PipelineTask + // +optional + WhenExpressions []WhenExpression `json:"whenExpressions,omitempty"` } // PipelineRunResult used to describe the results of a pipeline @@ -363,6 +366,9 @@ type PipelineRunTaskRunStatus struct { // ConditionChecks maps the name of a condition check to its Status // +optional ConditionChecks map[string]*PipelineRunConditionCheckStatus `json:"conditionChecks,omitempty"` + // WhenExpressions is the list of checks guarding the execution of the PipelineTask + // +optional + WhenExpressions []WhenExpression `json:"whenExpressions,omitempty"` } // PipelineRunConditionCheckStatus returns the condition check status diff --git a/pkg/apis/pipeline/v1beta1/zz_generated.deepcopy.go b/pkg/apis/pipeline/v1beta1/zz_generated.deepcopy.go index f04e41d45ab..9b7f057dc54 100644 --- a/pkg/apis/pipeline/v1beta1/zz_generated.deepcopy.go +++ b/pkg/apis/pipeline/v1beta1/zz_generated.deepcopy.go @@ -733,7 +733,9 @@ func (in *PipelineRunStatusFields) DeepCopyInto(out *PipelineRunStatusFields) { if in.SkippedTasks != nil { in, out := &in.SkippedTasks, &out.SkippedTasks *out = make([]SkippedTask, len(*in)) - copy(*out, *in) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } } return } @@ -771,6 +773,13 @@ func (in *PipelineRunTaskRunStatus) DeepCopyInto(out *PipelineRunTaskRunStatus) (*out)[key] = outVal } } + if in.WhenExpressions != nil { + in, out := &in.WhenExpressions, &out.WhenExpressions + *out = make([]WhenExpression, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } return } @@ -1172,6 +1181,13 @@ func (in *SidecarState) DeepCopy() *SidecarState { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SkippedTask) DeepCopyInto(out *SkippedTask) { *out = *in + if in.WhenExpressions != nil { + in, out := &in.WhenExpressions, &out.WhenExpressions + *out = make([]WhenExpression, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } return } diff --git a/pkg/reconciler/pipelinerun/pipelinerun_test.go b/pkg/reconciler/pipelinerun/pipelinerun_test.go index 7a883e0f90c..46197c60f74 100644 --- a/pkg/reconciler/pipelinerun/pipelinerun_test.go +++ b/pkg/reconciler/pipelinerun/pipelinerun_test.go @@ -762,7 +762,12 @@ func TestUpdateTaskRunsState(t *testing.T) { // from a TaskRun associated to the PipelineRun pr := tb.PipelineRun("test-pipeline-run", tb.PipelineRunNamespace("foo"), tb.PipelineRunSpec("test-pipeline")) pipelineTask := v1beta1.PipelineTask{ - Name: "unit-test-1", + Name: "unit-test-1", + WhenExpressions: []v1beta1.WhenExpression{{ + Input: "foo", + Operator: selection.In, + Values: []string{"foo", "bar"}, + }}, TaskRef: &v1beta1.TaskRef{Name: "unit-test-task"}, } task := tb.Task("unit-test-task", tb.TaskSpec( @@ -792,6 +797,11 @@ func TestUpdateTaskRunsState(t *testing.T) { Conditions: []apis.Condition{{Type: apis.ConditionSucceeded}}, }, }, + WhenExpressions: []v1beta1.WhenExpression{{ + Input: "foo", + Operator: selection.In, + Values: []string{"foo", "bar"}, + }}, } expectedPipelineRunStatus := v1beta1.PipelineRunStatus{ PipelineRunStatusFields: v1beta1.PipelineRunStatusFields{ @@ -809,7 +819,7 @@ func TestUpdateTaskRunsState(t *testing.T) { }} pr.Status.InitializeConditions() status := state.GetTaskRunsStatus(pr) - if d := cmp.Diff(status, expectedPipelineRunStatus.TaskRuns); d != "" { + if d := cmp.Diff(expectedPipelineRunStatus.TaskRuns, status); d != "" { t.Fatalf("Expected PipelineRun status to match TaskRun(s) status, but got a mismatch: %s", diff.PrintWantGot(d)) } @@ -2076,9 +2086,28 @@ func TestReconcileWithWhenExpressionsWithParameters(t *testing.T) { t.Errorf("expected to see TaskRun %v created. Diff %s", expectedTaskRunName, diff.PrintWantGot(d)) } + actualWhenExpressionsInTaskRun := pipelineRun.Status.PipelineRunStatusFields.TaskRuns[expectedTaskRunName].WhenExpressions + expectedWhenExpressionsInTaskRun := []v1beta1.WhenExpression{{ + Input: "foo", + Operator: "notin", + Values: []string{"bar"}, + }, { + Input: "yes", + Operator: "in", + Values: []string{"yes"}, + }} + if d := cmp.Diff(expectedWhenExpressionsInTaskRun, actualWhenExpressionsInTaskRun); d != "" { + t.Errorf("expected to see When Expressions %v created. Diff %s", expectedTaskRunName, diff.PrintWantGot(d)) + } + actualSkippedTasks := pipelineRun.Status.SkippedTasks expectedSkippedTasks := []v1beta1.SkippedTask{{ Name: "hello-world-2", + WhenExpressions: v1beta1.WhenExpressions{{ + Input: "yes", + Operator: "notin", + Values: []string{"yes"}, + }}, }} if d := cmp.Diff(actualSkippedTasks, expectedSkippedTasks); d != "" { t.Errorf("expected to find Skipped Tasks %v. Diff %s", expectedSkippedTasks, diff.PrintWantGot(d)) @@ -2197,9 +2226,28 @@ func TestReconcileWithWhenExpressionsWithTaskResults(t *testing.T) { t.Errorf("expected to see TaskRun %v created. Diff %s", expectedTaskRunName, diff.PrintWantGot(d)) } + actualWhenExpressionsInTaskRun := pipelineRun.Status.PipelineRunStatusFields.TaskRuns[expectedTaskRunName].WhenExpressions + expectedWhenExpressionsInTaskRun := []v1beta1.WhenExpression{{ + Input: "aResultValue", + Operator: "in", + Values: []string{"aResultValue"}, + }, { + Input: "aResultValue", + Operator: "in", + Values: []string{"aResultValue"}, + }} + if d := cmp.Diff(expectedWhenExpressionsInTaskRun, actualWhenExpressionsInTaskRun); d != "" { + t.Errorf("expected to see When Expressions %v created. Diff %s", expectedTaskRunName, diff.PrintWantGot(d)) + } + actualSkippedTasks := pipelineRun.Status.SkippedTasks expectedSkippedTasks := []v1beta1.SkippedTask{{ Name: "c-task", + WhenExpressions: v1beta1.WhenExpressions{{ + Input: "aResultValue", + Operator: "in", + Values: []string{"missing"}, + }}, }, { Name: "d-task", }} diff --git a/pkg/reconciler/pipelinerun/resources/pipelinerunstate.go b/pkg/reconciler/pipelinerun/resources/pipelinerunstate.go index 1909274a0dc..1fbc1593813 100644 --- a/pkg/reconciler/pipelinerun/resources/pipelinerunstate.go +++ b/pkg/reconciler/pipelinerun/resources/pipelinerunstate.go @@ -75,6 +75,7 @@ func (state PipelineRunState) GetTaskRunsStatus(pr *v1beta1.PipelineRun) map[str if prtrs == nil { prtrs = &v1beta1.PipelineRunTaskRunStatus{ PipelineTaskName: rprt.PipelineTask.Name, + WhenExpressions: rprt.PipelineTask.WhenExpressions, } } @@ -281,10 +282,14 @@ func (facts *PipelineRunFacts) GetPipelineConditionStatus(pr *v1beta1.PipelineRu } func (facts *PipelineRunFacts) GetSkippedTasks() []v1beta1.SkippedTask { - skipped := []v1beta1.SkippedTask{} + var skipped []v1beta1.SkippedTask for _, rprt := range facts.State { if rprt.Skip(facts) { - skipped = append(skipped, v1beta1.SkippedTask{Name: rprt.PipelineTask.Name}) + skippedTask := v1beta1.SkippedTask{ + Name: rprt.PipelineTask.Name, + WhenExpressions: rprt.PipelineTask.WhenExpressions, + } + skipped = append(skipped, skippedTask) } } return skipped