diff --git a/pkg/reconciler/pipelinerun/pipelinerun_test.go b/pkg/reconciler/pipelinerun/pipelinerun_test.go index 2cffc61939c..16ca139eb01 100644 --- a/pkg/reconciler/pipelinerun/pipelinerun_test.go +++ b/pkg/reconciler/pipelinerun/pipelinerun_test.go @@ -175,13 +175,16 @@ func getTaskRunByName(t *testing.T, taskRuns map[string]*v1beta1.TaskRun, expect return tr } -// getTaskRunsForPipelineRun returns the set of TaskRuns associated with the input PipelineRun. -// It will fatal the test if an error occurred. -func getTaskRunsForPipelineRun(ctx context.Context, t *testing.T, clients test.Clients, namespace string, prName string) map[string]*v1beta1.TaskRun { +// getTaskRunsForPipelineRun returns the set of TaskRuns associated with the input PipelineRun and optional +// input of a PipelineTask Label selector. It will fatal the test if an error occurred. +func getTaskRunsForPipelineRun(ctx context.Context, t *testing.T, clients test.Clients, namespace string, prName string, ptLabel string) map[string]*v1beta1.TaskRun { t.Helper() - + labelSelector := pipeline.PipelineRunLabelKey + "=" + prName + if ptLabel != "" { + labelSelector += "," + pipeline.PipelineTaskLabelKey + "=" + ptLabel + } opt := metav1.ListOptions{ - LabelSelector: pipeline.PipelineRunLabelKey + "=" + prName, + LabelSelector: labelSelector, } taskRuns, err := clients.Pipeline.TektonV1beta1().TaskRuns(namespace).List(ctx, opt) @@ -330,7 +333,7 @@ spec: } reconciledRun, clients := prt.reconcileRun(namespace, prName, wantEvents, false) - taskRuns := getTaskRunsForPipelineRun(prt.TestAssets.Ctx, t, clients, namespace, prName) + taskRuns := getTaskRunsForPipelineRun(prt.TestAssets.Ctx, t, clients, namespace, prName, "") // Ensure that there are 2 TaskRuns associated with this PipelineRun validateTaskRunsCount(t, taskRuns, 2) @@ -603,7 +606,7 @@ spec: reconciledRun, clients := prt.reconcileRun(namespace, prName, wantEvents, false) // Check that the expected TaskRun was created - taskRuns := getTaskRunsForPipelineRun(prt.TestAssets.Ctx, t, clients, namespace, prName) + taskRuns := getTaskRunsForPipelineRun(prt.TestAssets.Ctx, t, clients, namespace, prName, "") validateTaskRunsCount(t, taskRuns, 1) actual := getTaskRunByName(t, taskRuns, trName) @@ -1151,7 +1154,7 @@ status: } reconciledRun, clients := prt.reconcileRun(namespace, pipelineRunName, wantEvents, false) - taskRuns := getTaskRunsForPipelineRun(prt.TestAssets.Ctx, t, clients, namespace, pipelineRunName) + taskRuns := getTaskRunsForPipelineRun(prt.TestAssets.Ctx, t, clients, namespace, pipelineRunName, "") validateTaskRunsCount(t, taskRuns, 1) // This PipelineRun should still be complete and the status should reflect that @@ -2862,7 +2865,7 @@ spec: _, clients := prt.reconcileRun(namespace, prName, []string{}, false) // Check that the expected TaskRun was created - taskRuns := getTaskRunsForPipelineRun(prt.TestAssets.Ctx, t, clients, namespace, prName) + taskRuns := getTaskRunsForPipelineRun(prt.TestAssets.Ctx, t, clients, namespace, prName, "") validateTaskRunsCount(t, taskRuns, 1) actual := getTaskRunByName(t, taskRuns, trName) @@ -3114,7 +3117,7 @@ spec: _, clients := prt.reconcileRun("foo", prName, []string{}, false) // Check that the expected TaskRun was created - taskRuns := getTaskRunsForPipelineRun(prt.TestAssets.Ctx, t, clients, namespace, prName) + taskRuns := getTaskRunsForPipelineRun(prt.TestAssets.Ctx, t, clients, namespace, prName, "") validateTaskRunsCount(t, taskRuns, 1) actual := getTaskRunByName(t, taskRuns, trName) @@ -5012,7 +5015,7 @@ status: defer prt.Cancel() reconciledRun, clients := prt.reconcileRun(namespace, prOutOfSyncName, []string{}, false) - taskRuns := getTaskRunsForPipelineRun(prt.TestAssets.Ctx, t, clients, namespace, prOutOfSyncName) + taskRuns := getTaskRunsForPipelineRun(prt.TestAssets.Ctx, t, clients, namespace, prOutOfSyncName, "") validateTaskRunsCount(t, taskRuns, 2) // This PipelineRun should still be running and the status should reflect that @@ -6380,7 +6383,7 @@ metadata: reconciledRun, clients := prt.reconcileRun(namespace, prName, wantEvents, false) // Check that the expected TaskRun was created - taskRuns := getTaskRunsForPipelineRun(prt.TestAssets.Ctx, t, clients, namespace, prName) + taskRuns := getTaskRunsForPipelineRun(prt.TestAssets.Ctx, t, clients, namespace, prName, "") validateTaskRunsCount(t, taskRuns, 1) actual := getTaskRunByName(t, taskRuns, trName) @@ -6459,7 +6462,7 @@ spec: reconciledRun, clients := prt.reconcileRun(namespace, prName, nil, false) // Check that the expected TaskRun was created - taskRuns := getTaskRunsForPipelineRun(prt.TestAssets.Ctx, t, clients, namespace, prName) + taskRuns := getTaskRunsForPipelineRun(prt.TestAssets.Ctx, t, clients, namespace, prName, "") validateTaskRunsCount(t, taskRuns, 1) actual := getTaskRunByName(t, taskRuns, trName) @@ -7357,7 +7360,7 @@ spec: _, clients := prt.reconcileRun(namespace, prName, []string{}, false) - taskRuns := getTaskRunsForPipelineRun(prt.TestAssets.Ctx, t, clients, namespace, prName) + taskRuns := getTaskRunsForPipelineRun(prt.TestAssets.Ctx, t, clients, namespace, prName, "") validateTaskRunsCount(t, taskRuns, 1) actual := getTaskRunByName(t, taskRuns, trName) @@ -7434,7 +7437,7 @@ spec: _, clients := prt.reconcileRun(namespace, prName, []string{}, false) - taskRuns := getTaskRunsForPipelineRun(prt.TestAssets.Ctx, t, clients, namespace, prName) + taskRuns := getTaskRunsForPipelineRun(prt.TestAssets.Ctx, t, clients, namespace, prName, "") validateTaskRunsCount(t, taskRuns, 1) actual := getTaskRunByName(t, taskRuns, trName) @@ -10358,7 +10361,7 @@ spec: reconciledRun, clients := prt.reconcileRun(namespace, prName, wantEvents, false) // Check that the expected TaskRun was created - taskRuns := getTaskRunsForPipelineRun(prt.TestAssets.Ctx, t, clients, namespace, prName) + taskRuns := getTaskRunsForPipelineRun(prt.TestAssets.Ctx, t, clients, namespace, prName, "") // Ensure that there are 2 TaskRuns associated with this PipelineRun validateTaskRunsCount(t, taskRuns, 2) @@ -10849,3 +10852,344 @@ spec: t.Errorf("Expected PipelineRun to be create run failed, but condition reason is %s", reconciledRun.Status.GetCondition(apis.ConditionSucceeded)) } } + +func TestReconciler_PipelineTaskMatrixResultsWithArrayIndexing(t *testing.T) { + names.TestingSeed() + task := parse.MustParseV1beta1Task(t, ` +metadata: + name: mytask + namespace: foo +spec: + params: + - name: platform + default: mac + steps: + - name: echo + image: alpine + script: | + echo "$(params.platform)" +`) + taskwithresults := parse.MustParseV1beta1Task(t, ` +metadata: + name: taskwithresults + namespace: foo +spec: + results: + - name: platforms + type: array + steps: + - name: produce-a-list-of-platforms + image: bash:latest + script: | + #!/usr/bin/env bash + echo -n "[\"linux\",\"mac\",\"windows\"]" | tee $(results.platforms.path) +`) + + cms := []*corev1.ConfigMap{withEnabledAlphaAPIFields(newFeatureFlagsConfigMap())} + cms = append(cms, withMaxMatrixCombinationsCount(newDefaultsConfigMap(), 10)) + tests := []struct { + name string + pName string + p *v1beta1.Pipeline + tr *v1beta1.TaskRun + expectedTaskRuns []*v1beta1.TaskRun + expectedPipelineRun *v1beta1.PipelineRun + }{{ + name: "indexing results in params", + pName: "p-dag", + p: parse.MustParseV1beta1Pipeline(t, fmt.Sprintf(` +metadata: + name: %s + namespace: foo +spec: + tasks: + - name: pt-with-result + params: + - name: platforms + type: array + taskRef: + name: taskwithresults + - name: echo-platforms + params: + - name: platforms + value: + - $(tasks.pt-with-result.results.platforms[0]) + - $(tasks.pt-with-result.results.platforms[1]) + - $(tasks.pt-with-result.results.platforms[2]) + taskRef: + name: mytask +`, "p-dag")), + tr: mustParseTaskRunWithObjectMeta(t, + taskRunObjectMeta("pr-pt-with-result", "foo", + "pr", "p-dag", "pt-with-result", false), + ` +spec: + serviceAccountName: test-sa + taskRef: + name: taskwithresults +status: + conditions: + - type: Succeeded + status: "True" + reason: Succeeded + message: All Tasks have completed executing + taskResults: + - name: platforms + value: + - linux + - mac + - windows +`), + expectedTaskRuns: []*v1beta1.TaskRun{ + mustParseTaskRunWithObjectMeta(t, + taskRunObjectMeta("pr-echo-platforms", "foo", + "pr", "p", "echo-platforms", false), + ` +spec: + params: + - name: platforms + value: + - linux + - mac + - windows + serviceAccountName: test-sa + taskRef: + name: mytask + kind: Task +`), + }, + expectedPipelineRun: parse.MustParseV1beta1PipelineRun(t, ` +metadata: + name: pr + namespace: foo + annotations: {} + labels: + tekton.dev/pipeline: p-dag +spec: + serviceAccountName: test-sa + pipelineRef: + name: p-dag +status: + pipelineSpec: + tasks: + - name: pt-with-result + params: + - name: platforms + type: array + taskRef: + name: taskwithresults + kind: Task + - name: echo-platforms + taskRef: + name: mytask + kind: Task + params: + - name: platforms + value: + - $(tasks.pt-with-result.results.platforms[0]) + - $(tasks.pt-with-result.results.platforms[1]) + - $(tasks.pt-with-result.results.platforms[2]) + conditions: + - type: Succeeded + status: "Unknown" + reason: "Running" + message: "Tasks Completed: 1 (Failed: 0, Cancelled 0), Incomplete: 1, Skipped: 0" + childReferences: + - apiVersion: tekton.dev/v1beta1 + kind: TaskRun + name: pr-pt-with-result + pipelineTaskName: pt-with-result + - apiVersion: tekton.dev/v1beta1 + kind: TaskRun + name: pr-echo-platforms + pipelineTaskName: echo-platforms +`), + }, { + name: "indexing results in matrix.params", + pName: "p-dag-2", + p: parse.MustParseV1beta1Pipeline(t, fmt.Sprintf(` +metadata: + name: %s + namespace: foo +spec: + tasks: + - name: pt-with-result + params: + - name: platforms + type: array + taskRef: + name: taskwithresults + - name: echo-platforms + matrix: + params: + - name: platform + value: + - $(tasks.pt-with-result.results.platforms[0]) + - $(tasks.pt-with-result.results.platforms[1]) + - $(tasks.pt-with-result.results.platforms[2]) + taskRef: + name: mytask +`, "p-dag-2")), + tr: mustParseTaskRunWithObjectMeta(t, + taskRunObjectMeta("pr-pt-with-result", "foo", + "pr", "p-dag-2", "pt-with-result", false), + ` +spec: + serviceAccountName: test-sa + taskRef: + name: taskwithresults +status: + conditions: + - type: Succeeded + status: "True" + reason: Succeeded + message: All Tasks have completed executing + taskResults: + - name: platforms + value: + - linux + - mac + - windows +`), + expectedTaskRuns: []*v1beta1.TaskRun{ + mustParseTaskRunWithObjectMeta(t, + taskRunObjectMeta("pr-echo-platforms-0", "foo", + "pr", "p", "echo-platforms", false), + ` +spec: + params: + - name: platform + value: linux + serviceAccountName: test-sa + taskRef: + name: mytask + kind: Task +`), + mustParseTaskRunWithObjectMeta(t, + taskRunObjectMeta("pr-echo-platforms-1", "foo", + "pr", "p", "echo-platforms", false), + ` +spec: + params: + - name: platform + value: mac + serviceAccountName: test-sa + taskRef: + name: mytask + kind: Task +`), + mustParseTaskRunWithObjectMeta(t, + taskRunObjectMeta("pr-echo-platforms-2", "foo", + "pr", "p", "echo-platforms", false), + ` +spec: + params: + - name: platform + value: windows + serviceAccountName: test-sa + taskRef: + name: mytask + kind: Task +`), + }, + expectedPipelineRun: parse.MustParseV1beta1PipelineRun(t, ` +metadata: + name: pr + namespace: foo + annotations: {} + labels: + tekton.dev/pipeline: p-dag-2 +spec: + serviceAccountName: test-sa + pipelineRef: + name: p-dag-2 +status: + pipelineSpec: + tasks: + - name: pt-with-result + params: + - name: platforms + type: array + taskRef: + name: taskwithresults + kind: Task + - name: echo-platforms + taskRef: + name: mytask + kind: Task + matrix: + params: + - name: platform + value: + - $(tasks.pt-with-result.results.platforms[0]) + - $(tasks.pt-with-result.results.platforms[1]) + - $(tasks.pt-with-result.results.platforms[2]) + conditions: + - type: Succeeded + status: "Unknown" + reason: "Running" + message: "Tasks Completed: 1 (Failed: 0, Cancelled 0), Incomplete: 1, Skipped: 0" + childReferences: + - apiVersion: tekton.dev/v1beta1 + kind: TaskRun + name: pr-pt-with-result + pipelineTaskName: pt-with-result + - apiVersion: tekton.dev/v1beta1 + kind: TaskRun + name: pr-echo-platforms-0 + pipelineTaskName: echo-platforms + - apiVersion: tekton.dev/v1beta1 + kind: TaskRun + name: pr-echo-platforms-1 + pipelineTaskName: echo-platforms + - apiVersion: tekton.dev/v1beta1 + kind: TaskRun + name: pr-echo-platforms-2 + pipelineTaskName: echo-platforms +`), + }} + for _, tt := range tests { + t.Run(tt.pName, func(t *testing.T) { + pr := parse.MustParseV1beta1PipelineRun(t, fmt.Sprintf(` +metadata: + name: pr + namespace: foo +spec: + serviceAccountName: test-sa + pipelineRef: + name: %s +`, tt.pName)) + d := test.Data{ + PipelineRuns: []*v1beta1.PipelineRun{pr}, + Pipelines: []*v1beta1.Pipeline{tt.p}, + Tasks: []*v1beta1.Task{task, taskwithresults}, + ConfigMaps: cms, + } + if tt.tr != nil { + d.TaskRuns = []*v1beta1.TaskRun{tt.tr} + } + prt := newPipelineRunTest(t, d) + defer prt.Cancel() + _, clients := prt.reconcileRun("foo", "pr", []string{}, false) + + taskRuns := getTaskRunsForPipelineRun(prt.TestAssets.Ctx, t, clients, pr.Namespace, pr.Name, "echo-platforms") + validateTaskRunsCount(t, taskRuns, len(tt.expectedTaskRuns)) + for _, expectedTaskRun := range tt.expectedTaskRuns { + trName := expectedTaskRun.Name + actual := getTaskRunByName(t, taskRuns, trName) + expectedTaskRun.Labels["tekton.dev/pipeline"] = tt.pName + expectedTaskRun.Labels["tekton.dev/memberOf"] = "tasks" + if d := cmp.Diff(expectedTaskRun, actual, ignoreResourceVersion, ignoreTypeMeta); d != "" { + t.Errorf("expected to see TaskRun %v created. Diff %s", expectedTaskRun.Name, diff.PrintWantGot(d)) + } + } + pipelineRun, err := clients.Pipeline.TektonV1beta1().PipelineRuns("foo").Get(prt.TestAssets.Ctx, "pr", metav1.GetOptions{}) + if err != nil { + t.Fatalf("Got an error getting reconciled run out of fake client: %s", err) + } + if d := cmp.Diff(tt.expectedPipelineRun, pipelineRun, ignoreResourceVersion, ignoreTypeMeta, ignoreLastTransitionTime, ignoreStartTime, ignoreFinallyStartTime, cmpopts.EquateEmpty()); d != "" { + t.Errorf("expected PipelineRun was not created. Diff %s", diff.PrintWantGot(d)) + } + }) + } +}