From b6fb30ddbfe598028a7fdeda0db03ad395090b90 Mon Sep 17 00:00:00 2001 From: Andrew Bayer Date: Thu, 14 Apr 2022 12:05:32 -0400 Subject: [PATCH] [TEP-0100] Add new `updatePipelineRunStatusFromChildRefs` function And of course, this is part of https://github.com/tektoncd/community/blob/main/teps/0100-embedded-taskruns-and-runs-status-in-pipelineruns.md, building on a pile of other PRs (#4705, #4734, #4753, #4757). This adds a new function to `pkg/reconciler/pipelinerun/pipelinerun.go`, specifically for updating `pr.Status.ChildReferences` during reconciliation. It's analogous to the existing `updatePipelineRunStatusFromTaskRuns` and `updatePipelineRunStatusFromRuns` functions. This PR doesn't actually call the new function - behavior is exactly the same. But it adds the new function, along with other functions it depends on. In the final step of the implementation, these other functions will also be used in `...FromTaskRuns` and/or `...FromRuns`. I also reworked `pkg/reconciler/pipelinerun/pipelinerun_updatestatus_test.go` to improve its test fixtures, so that they're easier to reuse and instantiated via YAML parsing as much as possible. Signed-off-by: Andrew Bayer --- .../pipeline/v1beta1/pipelinerun_types.go | 15 + pkg/reconciler/pipelinerun/pipelinerun.go | 172 +++ .../pipelinerun_updatestatus_test.go | 992 ++++++++++++------ 3 files changed, 849 insertions(+), 330 deletions(-) diff --git a/pkg/apis/pipeline/v1beta1/pipelinerun_types.go b/pkg/apis/pipeline/v1beta1/pipelinerun_types.go index 30efd134b96..d06a7f57006 100644 --- a/pkg/apis/pipeline/v1beta1/pipelinerun_types.go +++ b/pkg/apis/pipeline/v1beta1/pipelinerun_types.go @@ -422,6 +422,21 @@ type ChildStatusReference struct { WhenExpressions []WhenExpression `json:"whenExpressions,omitempty"` } +// GetConditionChecks returns a map representation of this ChildStatusReference's ConditionChecks, in the same form +// as PipelineRunTaskRunStatus.ConditionChecks. +func (cr ChildStatusReference) GetConditionChecks() map[string]*PipelineRunConditionCheckStatus { + if len(cr.ConditionChecks) == 0 { + return nil + } + ccMap := make(map[string]*PipelineRunConditionCheckStatus) + + for _, cc := range cr.ConditionChecks { + ccMap[cc.ConditionCheckName] = &cc.PipelineRunConditionCheckStatus + } + + return ccMap +} + // PipelineRunStatusFields holds the fields of PipelineRunStatus' status. // This is defined separately and inlined so that other types can readily // consume these fields via duck typing. diff --git a/pkg/reconciler/pipelinerun/pipelinerun.go b/pkg/reconciler/pipelinerun/pipelinerun.go index e1d2e6eefe5..8c1c947a9bc 100644 --- a/pkg/reconciler/pipelinerun/pipelinerun.go +++ b/pkg/reconciler/pipelinerun/pipelinerun.go @@ -1196,6 +1196,53 @@ func (c *Reconciler) updatePipelineRunStatusFromInformer(ctx context.Context, pr return nil } +// filterTaskRunsForPipelineRun returns TaskRuns owned by the PipelineRun and their condition checks +func filterTaskRunsForPipelineRun(logger *zap.SugaredLogger, pr *v1beta1.PipelineRun, trs []*v1beta1.TaskRun) ([]*v1beta1.TaskRun, map[string][]*v1beta1.TaskRun) { + var normalTaskRuns []*v1beta1.TaskRun + conditionTaskRuns := make(map[string][]*v1beta1.TaskRun) + + for _, tr := range trs { + // Only process TaskRuns that are owned by this PipelineRun. + // This skips TaskRuns that are indirectly created by the PipelineRun (e.g. by custom tasks). + if len(tr.OwnerReferences) < 1 || tr.OwnerReferences[0].UID != pr.ObjectMeta.UID { + logger.Debugf("Found a TaskRun %s that is not owned by this PipelineRun", tr.Name) + continue + } + lbls := tr.GetLabels() + pipelineTaskName := lbls[pipeline.PipelineTaskLabelKey] + if _, ok := lbls[pipeline.ConditionCheckKey]; ok { + // Save condition for looping over them after this + if _, ok := conditionTaskRuns[pipelineTaskName]; !ok { + // If it's the first condition taskrun, initialise the slice + conditionTaskRuns[pipelineTaskName] = []*v1beta1.TaskRun{} + } + conditionTaskRuns[pipelineTaskName] = append(conditionTaskRuns[pipelineTaskName], tr) + } else { + normalTaskRuns = append(normalTaskRuns, tr) + } + } + + return normalTaskRuns, conditionTaskRuns +} + +// filterRunsForPipelineRun filters the given slice of Runs, returning only those owned by the given PipelineRun. +func filterRunsForPipelineRun(logger *zap.SugaredLogger, pr *v1beta1.PipelineRun, runs []*v1alpha1.Run) []*v1alpha1.Run { + var runsToInclude []*v1alpha1.Run + + // Loop over all the Runs associated to Tasks + for _, run := range runs { + // Only process Runs that are owned by this PipelineRun. + // This skips Runs that are indirectly created by the PipelineRun (e.g. by custom tasks). + if len(run.OwnerReferences) < 1 || run.OwnerReferences[0].UID != pr.ObjectMeta.UID { + logger.Debugf("Found a Run %s that is not owned by this PipelineRun", run.Name) + continue + } + runsToInclude = append(runsToInclude, run) + } + + return runsToInclude +} + func updatePipelineRunStatusFromTaskRuns(logger *zap.SugaredLogger, pr *v1beta1.PipelineRun, trs []*v1beta1.TaskRun) { // If no TaskRun was found, nothing to be done. We never remove taskruns from the status if trs == nil || len(trs) == 0 { @@ -1286,6 +1333,38 @@ func updatePipelineRunStatusFromTaskRuns(logger *zap.SugaredLogger, pr *v1beta1. } } +// getNewConditionChecksForTaskRun returns a map of condition task name to condition check status for each condition TaskRun +// provided which isn't already present in the existing map of condition checks. +func getNewConditionChecksForTaskRun(logger *zap.SugaredLogger, existingChecks map[string]*v1beta1.PipelineRunConditionCheckStatus, + actualConditionTaskRuns []*v1beta1.TaskRun) map[string]*v1beta1.PipelineRunConditionCheckStatus { + // If we don't have any condition task runs to process, just return nil. + if len(actualConditionTaskRuns) == 0 { + return nil + } + + newChecks := make(map[string]*v1beta1.PipelineRunConditionCheckStatus) + + for i, foundTaskRun := range actualConditionTaskRuns { + lbls := foundTaskRun.GetLabels() + if _, ok := existingChecks[foundTaskRun.Name]; !ok { + // The condition check was not found, so we need to add it + // We only add the condition name, the status can now be gathered by the + // normal reconcile process + if conditionName, ok := lbls[pipeline.ConditionNameKey]; ok { + newChecks[foundTaskRun.Name] = &v1beta1.PipelineRunConditionCheckStatus{ + ConditionName: fmt.Sprintf("%s-%s", conditionName, strconv.Itoa(i)), + } + } else { + // The condition name label is missing, so we cannot recover this + logger.Warnf("found an orphaned condition taskrun %#v with missing %s label", + foundTaskRun, pipeline.ConditionNameKey) + } + } + } + + return newChecks +} + func updatePipelineRunStatusFromRuns(logger *zap.SugaredLogger, pr *v1beta1.PipelineRun, runs []*v1alpha1.Run) { // If no Run was found, nothing to be done. We never remove runs from the status if runs == nil || len(runs) == 0 { @@ -1313,3 +1392,96 @@ func updatePipelineRunStatusFromRuns(logger *zap.SugaredLogger, pr *v1beta1.Pipe } } } + +func updatePipelineRunStatusFromChildRefs(logger *zap.SugaredLogger, pr *v1beta1.PipelineRun, trs []*v1beta1.TaskRun, runs []*v1alpha1.Run) { + // If no TaskRun or Run was found, nothing to be done. We never remove child references from the status. + // We do still return an empty map of TaskRun/Run names keyed by PipelineTask name for later functions. + if len(trs) == 0 && len(runs) == 0 { + return + } + + // Map PipelineTask names to TaskRun child references that were already in the status + childRefByPipelineTask := make(map[string]*v1beta1.ChildStatusReference) + + for i := range pr.Status.ChildReferences { + childRefByPipelineTask[pr.Status.ChildReferences[i].PipelineTaskName] = &pr.Status.ChildReferences[i] + } + + taskRuns, conditionTaskRuns := filterTaskRunsForPipelineRun(logger, pr, trs) + + // Loop over all the TaskRuns associated to Tasks + for _, tr := range taskRuns { + lbls := tr.GetLabels() + pipelineTaskName := lbls[pipeline.PipelineTaskLabelKey] + + if _, ok := childRefByPipelineTask[pipelineTaskName]; !ok { + // This tr was missing from the status. + // Add it without conditions, which are handled in the next loop + logger.Infof("Found a TaskRun %s that was missing from the PipelineRun status", tr.Name) + + // Since this was recovered now, add it to the map, or it might be overwritten + childRefByPipelineTask[pipelineTaskName] = &v1beta1.ChildStatusReference{ + TypeMeta: runtime.TypeMeta{ + APIVersion: v1beta1.SchemeGroupVersion.String(), + Kind: "TaskRun", + }, + Name: tr.Name, + PipelineTaskName: pipelineTaskName, + } + } + } + + // Loop over all the Runs associated to Tasks + for _, r := range filterRunsForPipelineRun(logger, pr, runs) { + lbls := r.GetLabels() + pipelineTaskName := lbls[pipeline.PipelineTaskLabelKey] + + if _, ok := childRefByPipelineTask[pipelineTaskName]; !ok { + // This run was missing from the status. + // Add it without conditions, which are handled in the next loop + logger.Infof("Found a Run %s that was missing from the PipelineRun status", r.Name) + + // Since this was recovered now, add it to the map, or it might be overwritten + childRefByPipelineTask[pipelineTaskName] = &v1beta1.ChildStatusReference{ + TypeMeta: runtime.TypeMeta{ + APIVersion: v1alpha1.SchemeGroupVersion.String(), + Kind: "Run", + }, + Name: r.Name, + PipelineTaskName: pipelineTaskName, + } + } + } + + // Then loop by pipelinetask name over all the TaskRuns associated to Conditions + for pipelineTaskName, actualConditionTaskRuns := range conditionTaskRuns { + // GetTaskRunName will look in first ChildReferences and then TaskRuns to see if there's already a TaskRun name + // for this pipelineTaskName, and if not, it will generate one. + taskRunName := resources.GetTaskRunName(pr.Status.TaskRuns, pr.Status.ChildReferences, pipelineTaskName, pr.Name) + if _, ok := childRefByPipelineTask[pipelineTaskName]; !ok { + childRefByPipelineTask[pipelineTaskName] = &v1beta1.ChildStatusReference{ + TypeMeta: runtime.TypeMeta{ + APIVersion: v1beta1.SchemeGroupVersion.String(), + Kind: "TaskRun", + }, + Name: taskRunName, + PipelineTaskName: pipelineTaskName, + } + } + + for k, v := range getNewConditionChecksForTaskRun(logger, childRefByPipelineTask[pipelineTaskName].GetConditionChecks(), actualConditionTaskRuns) { + // Just append any new condition checks to the relevant ChildStatusReference.ConditionChecks. + childRefByPipelineTask[pipelineTaskName].ConditionChecks = append(childRefByPipelineTask[pipelineTaskName].ConditionChecks, + &v1beta1.PipelineRunChildConditionCheckStatus{ + PipelineRunConditionCheckStatus: *v, + ConditionCheckName: k, + }) + } + } + + var newChildRefs []v1beta1.ChildStatusReference + for k := range childRefByPipelineTask { + newChildRefs = append(newChildRefs, *childRefByPipelineTask[k]) + } + pr.Status.ChildReferences = newChildRefs +} diff --git a/pkg/reconciler/pipelinerun/pipelinerun_updatestatus_test.go b/pkg/reconciler/pipelinerun/pipelinerun_updatestatus_test.go index 20d126ad764..baab33471dd 100644 --- a/pkg/reconciler/pipelinerun/pipelinerun_updatestatus_test.go +++ b/pkg/reconciler/pipelinerun/pipelinerun_updatestatus_test.go @@ -17,16 +17,19 @@ limitations under the License. package pipelinerun import ( + "fmt" "regexp" + "sort" "testing" + "github.com/ghodss/yaml" "github.com/google/go-cmp/cmp" - "github.com/tektoncd/pipeline/pkg/apis/pipeline" "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha1" "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1" "github.com/tektoncd/pipeline/test/diff" - corev1 "k8s.io/api/core/v1" + "github.com/tektoncd/pipeline/test/parse" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" "knative.dev/pkg/apis" duckv1beta1 "knative.dev/pkg/apis/duck/v1beta1" @@ -41,168 +44,119 @@ type updateStatusTaskRunsData struct { simple map[string]*v1beta1.PipelineRunTaskRunStatus } -func getUpdateStatusTaskRunsData() updateStatusTaskRunsData { - // PipelineRunConditionCheckStatus recovered by updatePipelineRunStatusFromTaskRuns - // It does not include the status, which is then retrieved via the regular reconcile - prccs2Recovered := map[string]*v1beta1.PipelineRunConditionCheckStatus{ - "pr-task-2-running-condition-check-xxyyy": { - ConditionName: "running-condition-0", - }, - } - prccs3Recovered := map[string]*v1beta1.PipelineRunConditionCheckStatus{ - "pr-task-3-successful-condition-check-xxyyy": { - ConditionName: "successful-condition-0", - }, +func getUpdateStatusTaskRunsData(t *testing.T) updateStatusTaskRunsData { + prTask1Yaml := ` +pipelineTaskName: task-1 +status: {} +` + prTask2Yaml := ` +conditionChecks: + pr-task-2-running-condition-check-xxyyy: + conditionName: running-condition-0 + status: + check: + running: {} + conditions: + - status: Unknown + type: Succeeded +pipelineTaskName: task-2 +` + prTask3Yaml := ` +conditionChecks: + pr-task-3-successful-condition-check-xxyyy: + conditionName: successful-condition-0 + status: + check: + terminated: + exitCode: 0 + conditions: + - status: "True" + type: Succeeded +pipelineTaskName: task-3 +status: {} +` + + prTask4Yaml := ` +conditionChecks: + pr-task-4-failed-condition-check-xxyyy: + conditionName: failed-condition-0 + status: + check: + terminated: + exitCode: 127 + conditions: + - status: "False" + type: Succeeded +pipelineTaskName: task-4 +` + + prTask3NoStatusYaml := ` +conditionChecks: + pr-task-3-successful-condition-check-xxyyy: + conditionName: successful-condition-0 +pipelineTaskName: task-3 +status: {} +` + + orphanedPRTask2Yaml := ` +conditionChecks: + pr-task-2-running-condition-check-xxyyy: + conditionName: running-condition-0 +pipelineTaskName: task-2 +` + + orphanedPRTask4Yaml := ` +conditionChecks: + pr-task-4-failed-condition-check-xxyyy: + conditionName: failed-condition-0 +pipelineTaskName: task-4 +` + + withConditions := map[string]*v1beta1.PipelineRunTaskRunStatus{ + "pr-task-1-xxyyy": mustParsePipelineRunTaskRunStatus(t, prTask1Yaml), + "pr-task-2-xxyyy": mustParsePipelineRunTaskRunStatus(t, prTask2Yaml), + "pr-task-3-xxyyy": mustParsePipelineRunTaskRunStatus(t, prTask3Yaml), + "pr-task-4-xxyyy": mustParsePipelineRunTaskRunStatus(t, prTask4Yaml), } - prccs4Recovered := map[string]*v1beta1.PipelineRunConditionCheckStatus{ - "pr-task-4-failed-condition-check-xxyyy": { - ConditionName: "failed-condition-0", - }, + + missingTaskRuns := map[string]*v1beta1.PipelineRunTaskRunStatus{ + "pr-task-1-xxyyy": mustParsePipelineRunTaskRunStatus(t, prTask1Yaml), + "pr-task-2-xxyyy": mustParsePipelineRunTaskRunStatus(t, prTask2Yaml), + "pr-task-4-xxyyy": mustParsePipelineRunTaskRunStatus(t, prTask4Yaml), } - // PipelineRunConditionCheckStatus full is used to test the behaviour of updatePipelineRunStatusFromTaskRuns - // when no orphan TaskRuns are found, to check we don't alter good ones - prccs2Full := map[string]*v1beta1.PipelineRunConditionCheckStatus{ - "pr-task-2-running-condition-check-xxyyy": { - ConditionName: "running-condition-0", - Status: &v1beta1.ConditionCheckStatus{ - ConditionCheckStatusFields: v1beta1.ConditionCheckStatusFields{ - Check: corev1.ContainerState{ - Running: &corev1.ContainerStateRunning{}, - }, - }, - Status: duckv1beta1.Status{ - Conditions: []apis.Condition{{Type: apis.ConditionSucceeded, Status: corev1.ConditionUnknown}}, - }, - }, - }, + foundTaskRun := map[string]*v1beta1.PipelineRunTaskRunStatus{ + "pr-task-1-xxyyy": mustParsePipelineRunTaskRunStatus(t, prTask1Yaml), + "pr-task-2-xxyyy": mustParsePipelineRunTaskRunStatus(t, prTask2Yaml), + "pr-task-3-xxyyy": mustParsePipelineRunTaskRunStatus(t, prTask3NoStatusYaml), + "pr-task-4-xxyyy": mustParsePipelineRunTaskRunStatus(t, prTask4Yaml), } - prccs3Full := map[string]*v1beta1.PipelineRunConditionCheckStatus{ - "pr-task-3-successful-condition-check-xxyyy": { - ConditionName: "successful-condition-0", - Status: &v1beta1.ConditionCheckStatus{ - ConditionCheckStatusFields: v1beta1.ConditionCheckStatusFields{ - Check: corev1.ContainerState{ - Terminated: &corev1.ContainerStateTerminated{ExitCode: 0}, - }, - }, - Status: duckv1beta1.Status{ - Conditions: []apis.Condition{{Type: apis.ConditionSucceeded, Status: corev1.ConditionTrue}}, - }, - }, - }, + + recovered := map[string]*v1beta1.PipelineRunTaskRunStatus{ + "orphaned-taskruns-pr-task-2-xxyyy": mustParsePipelineRunTaskRunStatus(t, orphanedPRTask2Yaml), + "orphaned-taskruns-pr-task-4-xxyyy": mustParsePipelineRunTaskRunStatus(t, orphanedPRTask4Yaml), + "pr-task-1-xxyyy": mustParsePipelineRunTaskRunStatus(t, prTask1Yaml), + "pr-task-3-xxyyy": mustParsePipelineRunTaskRunStatus(t, prTask3NoStatusYaml), } - prccs4Full := map[string]*v1beta1.PipelineRunConditionCheckStatus{ - "pr-task-4-failed-condition-check-xxyyy": { - ConditionName: "failed-condition-0", - Status: &v1beta1.ConditionCheckStatus{ - ConditionCheckStatusFields: v1beta1.ConditionCheckStatusFields{ - Check: corev1.ContainerState{ - Terminated: &corev1.ContainerStateTerminated{ExitCode: 127}, - }, - }, - Status: duckv1beta1.Status{ - Conditions: []apis.Condition{{Type: apis.ConditionSucceeded, Status: corev1.ConditionFalse}}, - }, - }, - }, + + simple := map[string]*v1beta1.PipelineRunTaskRunStatus{ + "pr-task-1-xxyyy": mustParsePipelineRunTaskRunStatus(t, prTask1Yaml), } return updateStatusTaskRunsData{ - withConditions: map[string]*v1beta1.PipelineRunTaskRunStatus{ - "pr-task-1-xxyyy": { - PipelineTaskName: "task-1", - Status: &v1beta1.TaskRunStatus{}, - }, - "pr-task-2-xxyyy": { - PipelineTaskName: "task-2", - Status: nil, - ConditionChecks: prccs2Full, - }, - "pr-task-3-xxyyy": { - PipelineTaskName: "task-3", - Status: &v1beta1.TaskRunStatus{}, - ConditionChecks: prccs3Full, - }, - "pr-task-4-xxyyy": { - PipelineTaskName: "task-4", - Status: nil, - ConditionChecks: prccs4Full, - }, - }, - missingTaskRun: map[string]*v1beta1.PipelineRunTaskRunStatus{ - "pr-task-1-xxyyy": { - PipelineTaskName: "task-1", - Status: &v1beta1.TaskRunStatus{}, - }, - "pr-task-2-xxyyy": { - PipelineTaskName: "task-2", - Status: nil, - ConditionChecks: prccs2Full, - }, - "pr-task-4-xxyyy": { - PipelineTaskName: "task-4", - Status: nil, - ConditionChecks: prccs4Full, - }, - }, - foundTaskRun: map[string]*v1beta1.PipelineRunTaskRunStatus{ - "pr-task-1-xxyyy": { - PipelineTaskName: "task-1", - Status: &v1beta1.TaskRunStatus{}, - }, - "pr-task-2-xxyyy": { - PipelineTaskName: "task-2", - Status: nil, - ConditionChecks: prccs2Full, - }, - "pr-task-3-xxyyy": { - PipelineTaskName: "task-3", - Status: &v1beta1.TaskRunStatus{}, - ConditionChecks: prccs3Recovered, - }, - "pr-task-4-xxyyy": { - PipelineTaskName: "task-4", - Status: nil, - ConditionChecks: prccs4Full, - }, - }, - recovered: map[string]*v1beta1.PipelineRunTaskRunStatus{ - "pr-task-1-xxyyy": { - PipelineTaskName: "task-1", - Status: &v1beta1.TaskRunStatus{}, - }, - "orphaned-taskruns-pr-task-2-xxyyy": { - PipelineTaskName: "task-2", - Status: nil, - ConditionChecks: prccs2Recovered, - }, - "pr-task-3-xxyyy": { - PipelineTaskName: "task-3", - Status: &v1beta1.TaskRunStatus{}, - ConditionChecks: prccs3Recovered, - }, - "orphaned-taskruns-pr-task-4-xxyyy": { - PipelineTaskName: "task-4", - Status: nil, - ConditionChecks: prccs4Recovered, - }, - }, - simple: map[string]*v1beta1.PipelineRunTaskRunStatus{ - "pr-task-1-xxyyy": { - PipelineTaskName: "task-1", - Status: &v1beta1.TaskRunStatus{}, - }, - }, + withConditions: withConditions, + missingTaskRun: missingTaskRuns, + foundTaskRun: foundTaskRun, + recovered: recovered, + simple: simple, } } func TestUpdatePipelineRunStatusFromTaskRuns(t *testing.T) { prUID := types.UID("11111111-1111-1111-1111-111111111111") - otherPrUID := types.UID("22222222-2222-2222-2222-222222222222") - taskRunsPRStatusData := getUpdateStatusTaskRunsData() + taskRunsPRStatusData := getUpdateStatusTaskRunsData(t) prRunningStatus := duckv1beta1.Status{ Conditions: []apis.Condition{ @@ -273,82 +227,7 @@ func TestUpdatePipelineRunStatusFromTaskRuns(t *testing.T) { }, } - allTaskRuns := []*v1beta1.TaskRun{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "pr-task-1-xxyyy", - Labels: map[string]string{ - pipeline.PipelineTaskLabelKey: "task-1", - }, - OwnerReferences: []metav1.OwnerReference{{UID: prUID}}, - }, - }, - { - ObjectMeta: metav1.ObjectMeta{ - Name: "pr-task-2-running-condition-check-xxyyy", - Labels: map[string]string{ - pipeline.PipelineTaskLabelKey: "task-2", - pipeline.ConditionCheckKey: "pr-task-2-running-condition-check-xxyyy", - pipeline.ConditionNameKey: "running-condition", - }, - OwnerReferences: []metav1.OwnerReference{{UID: prUID}}, - }, - }, - { - ObjectMeta: metav1.ObjectMeta{ - Name: "pr-task-3-xxyyy", - Labels: map[string]string{ - pipeline.PipelineTaskLabelKey: "task-3", - }, - OwnerReferences: []metav1.OwnerReference{{UID: prUID}}, - }, - }, - { - ObjectMeta: metav1.ObjectMeta{ - Name: "pr-task-3-successful-condition-check-xxyyy", - Labels: map[string]string{ - pipeline.PipelineTaskLabelKey: "task-3", - pipeline.ConditionCheckKey: "pr-task-3-successful-condition-check-xxyyy", - pipeline.ConditionNameKey: "successful-condition", - }, - OwnerReferences: []metav1.OwnerReference{{UID: prUID}}, - }, - }, - { - ObjectMeta: metav1.ObjectMeta{ - Name: "pr-task-4-failed-condition-check-xxyyy", - Labels: map[string]string{ - pipeline.PipelineTaskLabelKey: "task-4", - pipeline.ConditionCheckKey: "pr-task-4-failed-condition-check-xxyyy", - pipeline.ConditionNameKey: "failed-condition", - }, - OwnerReferences: []metav1.OwnerReference{{UID: prUID}}, - }, - }, - } - - taskRunsFromAnotherPR := []*v1beta1.TaskRun{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "pr-task-1-xxyyy", - Labels: map[string]string{ - pipeline.PipelineTaskLabelKey: "task-1", - }, - OwnerReferences: []metav1.OwnerReference{{UID: otherPrUID}}, - }, - }, - } - - taskRunsWithNoOwner := []*v1beta1.TaskRun{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "pr-task-1-xxyyy", - Labels: map[string]string{ - pipeline.PipelineTaskLabelKey: "task-1", - }, - }, - }, - } + allTaskRuns, taskRunsFromAnotherPR, taskRunsWithNoOwner, _, _, _ := getTestTaskRunsAndRuns(t) tcs := []struct { prName string @@ -369,42 +248,37 @@ func TestUpdatePipelineRunStatusFromTaskRuns(t *testing.T) { }, { prName: "status-nil-taskruns", prStatus: prStatusWithEmptyTaskRuns, - trs: []*v1beta1.TaskRun{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "pr-task-1-xxyyy", - Labels: map[string]string{ - pipeline.PipelineTaskLabelKey: "task-1", - }, - OwnerReferences: []metav1.OwnerReference{{UID: prUID}}, - }, - }, - }, + trs: []*v1beta1.TaskRun{parse.MustParseTaskRun(t, ` +metadata: + labels: + tekton.dev/pipelineTask: task-1 + name: pr-task-1-xxyyy + ownerReferences: + - uid: 11111111-1111-1111-1111-111111111111 +`)}, expectedPrStatus: prStatusRecoveredSimple, }, { prName: "status-missing-taskruns", prStatus: prStatusMissingTaskRun, trs: []*v1beta1.TaskRun{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "pr-task-3-xxyyy", - Labels: map[string]string{ - pipeline.PipelineTaskLabelKey: "task-3", - }, - OwnerReferences: []metav1.OwnerReference{{UID: prUID}}, - }, - }, - { - ObjectMeta: metav1.ObjectMeta{ - Name: "pr-task-3-successful-condition-check-xxyyy", - Labels: map[string]string{ - pipeline.PipelineTaskLabelKey: "task-3", - pipeline.ConditionCheckKey: "pr-task-3-successful-condition-check-xxyyy", - pipeline.ConditionNameKey: "successful-condition", - }, - OwnerReferences: []metav1.OwnerReference{{UID: prUID}}, - }, - }, + parse.MustParseTaskRun(t, ` +metadata: + labels: + tekton.dev/pipelineTask: task-3 + name: pr-task-3-xxyyy + ownerReferences: + - uid: 11111111-1111-1111-1111-111111111111 +`), + parse.MustParseTaskRun(t, ` +metadata: + labels: + tekton.dev/conditionCheck: pr-task-3-successful-condition-check-xxyyy + tekton.dev/conditionName: successful-condition + tekton.dev/pipelineTask: task-3 + name: pr-task-3-successful-condition-check-xxyyy + ownerReferences: + - uid: 11111111-1111-1111-1111-111111111111 +`), }, expectedPrStatus: prStatusFoundTaskRun, }, { @@ -439,7 +313,6 @@ func TestUpdatePipelineRunStatusFromTaskRuns(t *testing.T) { Status: tc.prStatus, } - // TODO(abayer): Change function call when TEP-0100 impl is done. updatePipelineRunStatusFromTaskRuns(logger, pr, tc.trs) actualPrStatus := pr.Status @@ -467,7 +340,6 @@ func TestUpdatePipelineRunStatusFromTaskRuns(t *testing.T) { func TestUpdatePipelineRunStatusFromRuns(t *testing.T) { prUID := types.UID("11111111-1111-1111-1111-111111111111") - otherPrUID := types.UID("22222222-2222-2222-2222-222222222222") prRunningStatus := duckv1beta1.Status{ Conditions: []apis.Condition{ @@ -535,58 +407,7 @@ func TestUpdatePipelineRunStatusFromRuns(t *testing.T) { }, } - allRuns := []*v1alpha1.Run{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "pr-run-1-xxyyy", - Labels: map[string]string{ - pipeline.PipelineTaskLabelKey: "run-1", - }, - OwnerReferences: []metav1.OwnerReference{{UID: prUID}}, - }, - }, - { - ObjectMeta: metav1.ObjectMeta{ - Name: "pr-run-2-xxyyy", - Labels: map[string]string{ - pipeline.PipelineTaskLabelKey: "run-2", - }, - OwnerReferences: []metav1.OwnerReference{{UID: prUID}}, - }, - }, - { - ObjectMeta: metav1.ObjectMeta{ - Name: "pr-run-3-xxyyy", - Labels: map[string]string{ - pipeline.PipelineTaskLabelKey: "run-3", - }, - OwnerReferences: []metav1.OwnerReference{{UID: prUID}}, - }, - }, - } - - runsFromAnotherPR := []*v1alpha1.Run{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "pr-run-1-xxyyy", - Labels: map[string]string{ - pipeline.PipelineTaskLabelKey: "run-1", - }, - OwnerReferences: []metav1.OwnerReference{{UID: otherPrUID}}, - }, - }, - } - - runsWithNoOwner := []*v1alpha1.Run{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "pr-run-1-xxyyy", - Labels: map[string]string{ - pipeline.PipelineTaskLabelKey: "run-1", - }, - }, - }, - } + _, _, _, allRuns, runsFromAnotherPR, runsWithNoOwner := getTestTaskRunsAndRuns(t) tcs := []struct { prName string @@ -607,30 +428,26 @@ func TestUpdatePipelineRunStatusFromRuns(t *testing.T) { }, { prName: "status-nil-runs", prStatus: prStatusWithEmptyRuns, - runs: []*v1alpha1.Run{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "pr-run-1-xxyyy", - Labels: map[string]string{ - pipeline.PipelineTaskLabelKey: "run-1", - }, - OwnerReferences: []metav1.OwnerReference{{UID: prUID}}, - }, - }, - }, + runs: []*v1alpha1.Run{parse.MustParseRun(t, ` +metadata: + labels: + tekton.dev/pipelineTask: run-1 + name: pr-run-1-xxyyy + ownerReferences: + - uid: 11111111-1111-1111-1111-111111111111 +`)}, expectedPrStatus: prStatusRecoveredSimple, }, { prName: "status-missing-runs", prStatus: prStatusWithSomeRuns, - runs: []*v1alpha1.Run{{ - ObjectMeta: metav1.ObjectMeta{ - Name: "pr-run-3-xxyyy", - Labels: map[string]string{ - pipeline.PipelineTaskLabelKey: "run-3", - }, - OwnerReferences: []metav1.OwnerReference{{UID: prUID}}, - }, - }}, + runs: []*v1alpha1.Run{parse.MustParseRun(t, ` +metadata: + labels: + tekton.dev/pipelineTask: run-3 + name: pr-run-3-xxyyy + ownerReferences: + - uid: 11111111-1111-1111-1111-111111111111 +`)}, expectedPrStatus: prStatusWithAllRuns, }, { prName: "status-matching-runs-pr", @@ -668,3 +485,518 @@ func TestUpdatePipelineRunStatusFromRuns(t *testing.T) { }) } } + +type updateStatusChildRefsData struct { + withConditions []v1beta1.ChildStatusReference + missingTaskRun []v1beta1.ChildStatusReference + foundTaskRun []v1beta1.ChildStatusReference + missingRun []v1beta1.ChildStatusReference + recovered []v1beta1.ChildStatusReference + simple []v1beta1.ChildStatusReference + simpleRun []v1beta1.ChildStatusReference +} + +func getUpdateStatusChildRefsData(t *testing.T) updateStatusChildRefsData { + prTask1Yaml := ` +apiVersion: tekton.dev/v1beta1 +kind: TaskRun +name: pr-task-1-xxyyy +pipelineTaskName: task-1 +` + + prTask2Yaml := ` +apiVersion: tekton.dev/v1beta1 +conditionChecks: +- conditionCheckName: pr-task-2-running-condition-check-xxyyy + conditionName: running-condition-0 + status: + check: + running: {} + conditions: + - status: Unknown + type: Succeeded +kind: TaskRun +name: pr-task-2-xxyyy +pipelineTaskName: task-2 +` + + prTask3Yaml := ` +apiVersion: tekton.dev/v1beta1 +conditionChecks: +- conditionCheckName: pr-task-3-successful-condition-check-xxyyy + conditionName: successful-condition-0 + status: + check: + terminated: + exitCode: 0 + conditions: + - status: "True" + type: Succeeded +kind: TaskRun +name: pr-task-3-xxyyy +pipelineTaskName: task-3 +` + + prTask4Yaml := ` +apiVersion: tekton.dev/v1beta1 +conditionChecks: +- conditionCheckName: pr-task-4-failed-condition-check-xxyyy + conditionName: failed-condition-0 + status: + check: + terminated: + exitCode: 127 + conditions: + - status: "False" + type: Succeeded +kind: TaskRun +name: pr-task-4-xxyyy +pipelineTaskName: task-4 +` + + prTask6Yaml := ` +apiVersion: tekton.dev/v1alpha1 +kind: Run +name: pr-run-6-xxyyy +pipelineTaskName: task-6 +` + + prTask3NoStatusYaml := ` +apiVersion: tekton.dev/v1beta1 +conditionChecks: +- conditionCheckName: pr-task-3-successful-condition-check-xxyyy + conditionName: successful-condition-0 +kind: TaskRun +name: pr-task-3-xxyyy +pipelineTaskName: task-3 +` + + orphanedPRTask2Yaml := ` +apiVersion: tekton.dev/v1beta1 +conditionChecks: +- conditionCheckName: pr-task-2-running-condition-check-xxyyy + conditionName: running-condition-0 +kind: TaskRun +name: orphaned-taskruns-pr-task-2-xxyyy +pipelineTaskName: task-2 +` + + orphanedPRTask4Yaml := ` +apiVersion: tekton.dev/v1beta1 +conditionChecks: +- conditionCheckName: pr-task-4-failed-condition-check-xxyyy + conditionName: failed-condition-0 +kind: TaskRun +name: orphaned-taskruns-pr-task-4-xxyyy +pipelineTaskName: task-4 +` + + withConditions := []v1beta1.ChildStatusReference{ + mustParseChildStatusReference(t, prTask1Yaml), + mustParseChildStatusReference(t, prTask2Yaml), + mustParseChildStatusReference(t, prTask3Yaml), + mustParseChildStatusReference(t, prTask4Yaml), + mustParseChildStatusReference(t, prTask6Yaml), + } + + missingTaskRun := []v1beta1.ChildStatusReference{ + mustParseChildStatusReference(t, prTask1Yaml), + mustParseChildStatusReference(t, prTask2Yaml), + mustParseChildStatusReference(t, prTask4Yaml), + mustParseChildStatusReference(t, prTask6Yaml), + } + + foundTaskRun := []v1beta1.ChildStatusReference{ + mustParseChildStatusReference(t, prTask1Yaml), + mustParseChildStatusReference(t, prTask2Yaml), + mustParseChildStatusReference(t, prTask3NoStatusYaml), + mustParseChildStatusReference(t, prTask4Yaml), + mustParseChildStatusReference(t, prTask6Yaml), + } + + missingRun := []v1beta1.ChildStatusReference{ + mustParseChildStatusReference(t, prTask1Yaml), + mustParseChildStatusReference(t, prTask2Yaml), + mustParseChildStatusReference(t, prTask3Yaml), + mustParseChildStatusReference(t, prTask4Yaml), + } + + recovered := []v1beta1.ChildStatusReference{ + mustParseChildStatusReference(t, prTask1Yaml), + mustParseChildStatusReference(t, orphanedPRTask2Yaml), + mustParseChildStatusReference(t, prTask3NoStatusYaml), + mustParseChildStatusReference(t, orphanedPRTask4Yaml), + mustParseChildStatusReference(t, prTask6Yaml), + } + + simple := []v1beta1.ChildStatusReference{mustParseChildStatusReference(t, prTask1Yaml)} + + simpleRun := []v1beta1.ChildStatusReference{mustParseChildStatusReference(t, prTask6Yaml)} + + return updateStatusChildRefsData{ + withConditions: withConditions, + missingTaskRun: missingTaskRun, + foundTaskRun: foundTaskRun, + missingRun: missingRun, + recovered: recovered, + simple: simple, + simpleRun: simpleRun, + } +} + +func TestUpdatePipelineRunStatusFromChildRefs(t *testing.T) { + prUID := types.UID("11111111-1111-1111-1111-111111111111") + + childRefsPRStatusData := getUpdateStatusChildRefsData(t) + + prRunningStatus := duckv1beta1.Status{ + Conditions: []apis.Condition{ + { + Type: "Succeeded", + Status: "Unknown", + Reason: "Running", + Message: "Not all Tasks in the Pipeline have finished executing", + }, + }, + } + + prStatusWithCondition := v1beta1.PipelineRunStatus{ + Status: prRunningStatus, + PipelineRunStatusFields: v1beta1.PipelineRunStatusFields{ + ChildReferences: childRefsPRStatusData.withConditions, + }, + } + + prStatusMissingTaskRun := v1beta1.PipelineRunStatus{ + Status: prRunningStatus, + PipelineRunStatusFields: v1beta1.PipelineRunStatusFields{ + ChildReferences: childRefsPRStatusData.missingTaskRun, + }, + } + + prStatusFoundTaskRun := v1beta1.PipelineRunStatus{ + Status: prRunningStatus, + PipelineRunStatusFields: v1beta1.PipelineRunStatusFields{ + ChildReferences: childRefsPRStatusData.foundTaskRun, + }, + } + + prStatusMissingRun := v1beta1.PipelineRunStatus{ + Status: prRunningStatus, + PipelineRunStatusFields: v1beta1.PipelineRunStatusFields{ + ChildReferences: childRefsPRStatusData.missingRun, + }, + } + + prStatusWithEmptyChildRefs := v1beta1.PipelineRunStatus{ + Status: prRunningStatus, + PipelineRunStatusFields: v1beta1.PipelineRunStatusFields{}, + } + + prStatusWithOrphans := v1beta1.PipelineRunStatus{ + Status: duckv1beta1.Status{ + Conditions: []apis.Condition{ + { + Type: "Succeeded", + Status: "Unknown", + Reason: "Running", + Message: "Not all Tasks in the Pipeline have finished executing", + }, + }, + }, + PipelineRunStatusFields: v1beta1.PipelineRunStatusFields{}, + } + + prStatusRecovered := v1beta1.PipelineRunStatus{ + Status: prRunningStatus, + PipelineRunStatusFields: v1beta1.PipelineRunStatusFields{ + ChildReferences: childRefsPRStatusData.recovered, + }, + } + + prStatusRecoveredSimple := v1beta1.PipelineRunStatus{ + Status: prRunningStatus, + PipelineRunStatusFields: v1beta1.PipelineRunStatusFields{ + ChildReferences: childRefsPRStatusData.simple, + }, + } + + prStatusRecoveredSimpleWithRun := v1beta1.PipelineRunStatus{ + Status: prRunningStatus, + PipelineRunStatusFields: v1beta1.PipelineRunStatusFields{ + ChildReferences: []v1beta1.ChildStatusReference{{ + TypeMeta: runtime.TypeMeta{ + APIVersion: "tekton.dev/v1alpha1", + Kind: "Run", + }, + Name: "pr-run-6-xxyyy", + PipelineTaskName: "task-6", + }}, + }, + } + + allTaskRuns, taskRunsFromAnotherPR, taskRunsWithNoOwner, _, runsFromAnotherPR, runsWithNoOwner := getTestTaskRunsAndRuns(t) + + singleRun := []*v1alpha1.Run{parse.MustParseRun(t, ` +metadata: + labels: + tekton.dev/pipelineTask: task-6 + name: pr-run-6-xxyyy + ownerReferences: + - uid: 11111111-1111-1111-1111-111111111111 +`)} + + tcs := []struct { + prName string + prStatus v1beta1.PipelineRunStatus + trs []*v1beta1.TaskRun + runs []*v1alpha1.Run + expectedPrStatus v1beta1.PipelineRunStatus + }{ + { + prName: "no-status-no-taskruns-or-runs", + prStatus: v1beta1.PipelineRunStatus{}, + trs: nil, + runs: nil, + expectedPrStatus: v1beta1.PipelineRunStatus{}, + }, { + prName: "status-no-taskruns-or-runs", + prStatus: prStatusWithCondition, + trs: nil, + runs: nil, + expectedPrStatus: prStatusWithCondition, + }, { + prName: "status-nil-taskruns", + prStatus: prStatusWithEmptyChildRefs, + trs: []*v1beta1.TaskRun{parse.MustParseTaskRun(t, ` +metadata: + labels: + tekton.dev/pipelineTask: task-1 + name: pr-task-1-xxyyy + ownerReferences: + - uid: 11111111-1111-1111-1111-111111111111 +`)}, + expectedPrStatus: prStatusRecoveredSimple, + }, { + prName: "status-nil-runs", + prStatus: prStatusWithEmptyChildRefs, + runs: singleRun, + expectedPrStatus: prStatusRecoveredSimpleWithRun, + }, { + prName: "status-missing-taskruns", + prStatus: prStatusMissingTaskRun, + trs: []*v1beta1.TaskRun{ + parse.MustParseTaskRun(t, ` +metadata: + labels: + tekton.dev/pipelineTask: task-3 + name: pr-task-3-xxyyy + ownerReferences: + - uid: 11111111-1111-1111-1111-111111111111 +`), + parse.MustParseTaskRun(t, ` +metadata: + labels: + tekton.dev/conditionCheck: pr-task-3-successful-condition-check-xxyyy + tekton.dev/conditionName: successful-condition + tekton.dev/pipelineTask: task-3 + name: pr-task-3-successful-condition-check-xxyyy + ownerReferences: + - uid: 11111111-1111-1111-1111-111111111111 +`), + }, + expectedPrStatus: prStatusFoundTaskRun, + }, { + prName: "status-missing-runs", + prStatus: prStatusMissingRun, + runs: singleRun, + expectedPrStatus: prStatusWithCondition, + }, { + prName: "status-matching-taskruns-pr", + prStatus: prStatusWithCondition, + trs: allTaskRuns, + expectedPrStatus: prStatusWithCondition, + }, { + prName: "orphaned-taskruns-pr", + prStatus: prStatusWithOrphans, + trs: allTaskRuns, + runs: singleRun, + expectedPrStatus: prStatusRecovered, + }, { + prName: "tr-and-run-from-another-pr", + prStatus: prStatusWithEmptyChildRefs, + trs: taskRunsFromAnotherPR, + runs: runsFromAnotherPR, + expectedPrStatus: prStatusWithEmptyChildRefs, + }, { + prName: "tr-and-run-with-no-owner", + prStatus: prStatusWithEmptyChildRefs, + trs: taskRunsWithNoOwner, + runs: runsWithNoOwner, + expectedPrStatus: prStatusWithEmptyChildRefs, + }, + } + + for _, tc := range tcs { + t.Run(tc.prName, func(t *testing.T) { + logger := logtesting.TestLogger(t) + + pr := &v1beta1.PipelineRun{ + ObjectMeta: metav1.ObjectMeta{Name: tc.prName, UID: prUID}, + Status: tc.prStatus, + } + + updatePipelineRunStatusFromChildRefs(logger, pr, tc.trs, tc.runs) + + actualPrStatus := pr.Status + + actualChildRefs := actualPrStatus.ChildReferences + if len(actualChildRefs) != 0 { + var fixedChildRefs []v1beta1.ChildStatusReference + re := regexp.MustCompile(`^[a-z\-]*?-(task|run)-[0-9]`) + for _, cr := range actualChildRefs { + cr.Name = fmt.Sprintf("%s-xxyyy", re.FindString(cr.Name)) + fixedChildRefs = append(fixedChildRefs, cr) + } + actualPrStatus.ChildReferences = fixedChildRefs + } + + // Sort the ChildReferences to deal with annoying ordering issues. + sort.Slice(actualPrStatus.ChildReferences, func(i, j int) bool { + return actualPrStatus.ChildReferences[i].PipelineTaskName < actualPrStatus.ChildReferences[j].PipelineTaskName + }) + + if d := cmp.Diff(tc.expectedPrStatus, actualPrStatus); d != "" { + t.Errorf("expected the PipelineRun status to match %#v. Diff %s", tc.expectedPrStatus, diff.PrintWantGot(d)) + } + }) + } +} + +func getTestTaskRunsAndRuns(t *testing.T) ([]*v1beta1.TaskRun, []*v1beta1.TaskRun, []*v1beta1.TaskRun, []*v1alpha1.Run, []*v1alpha1.Run, []*v1alpha1.Run) { + allTaskRuns := []*v1beta1.TaskRun{ + parse.MustParseTaskRun(t, ` +metadata: + labels: + tekton.dev/pipelineTask: task-1 + name: pr-task-1-xxyyy + ownerReferences: + - uid: 11111111-1111-1111-1111-111111111111 +`), + parse.MustParseTaskRun(t, ` +metadata: + labels: + tekton.dev/conditionCheck: pr-task-2-running-condition-check-xxyyy + tekton.dev/conditionName: running-condition + tekton.dev/pipelineTask: task-2 + name: pr-task-2-running-condition-check-xxyyy + ownerReferences: + - uid: 11111111-1111-1111-1111-111111111111 +`), + parse.MustParseTaskRun(t, ` +metadata: + labels: + tekton.dev/pipelineTask: task-3 + name: pr-task-3-xxyyy + ownerReferences: + - uid: 11111111-1111-1111-1111-111111111111 +`), + parse.MustParseTaskRun(t, ` +metadata: + labels: + tekton.dev/conditionCheck: pr-task-3-successful-condition-check-xxyyy + tekton.dev/conditionName: successful-condition + tekton.dev/pipelineTask: task-3 + name: pr-task-3-successful-condition-check-xxyyy + ownerReferences: + - uid: 11111111-1111-1111-1111-111111111111 +`), + parse.MustParseTaskRun(t, ` +metadata: + labels: + tekton.dev/conditionCheck: pr-task-4-failed-condition-check-xxyyy + tekton.dev/conditionName: failed-condition + tekton.dev/pipelineTask: task-4 + name: pr-task-4-failed-condition-check-xxyyy + ownerReferences: + - uid: 11111111-1111-1111-1111-111111111111 +`), + } + + taskRunsFromAnotherPR := []*v1beta1.TaskRun{parse.MustParseTaskRun(t, ` +metadata: + labels: + tekton.dev/pipelineTask: task-1 + name: pr-task-1-xxyyy + ownerReferences: + - uid: 22222222-2222-2222-2222-222222222222 +`)} + + taskRunsWithNoOwner := []*v1beta1.TaskRun{parse.MustParseTaskRun(t, ` +metadata: + labels: + tekton.dev/pipelineTask: task-1 + name: pr-task-1-xxyyy +`)} + + allRuns := []*v1alpha1.Run{ + parse.MustParseRun(t, ` +metadata: + labels: + tekton.dev/pipelineTask: run-1 + name: pr-run-1-xxyyy + ownerReferences: + - uid: 11111111-1111-1111-1111-111111111111 +`), + parse.MustParseRun(t, ` +metadata: + labels: + tekton.dev/pipelineTask: run-2 + name: pr-run-2-xxyyy + ownerReferences: + - uid: 11111111-1111-1111-1111-111111111111 +`), + parse.MustParseRun(t, ` +metadata: + labels: + tekton.dev/pipelineTask: run-3 + name: pr-run-3-xxyyy + ownerReferences: + - uid: 11111111-1111-1111-1111-111111111111 +`), + } + + runsFromAnotherPR := []*v1alpha1.Run{parse.MustParseRun(t, ` +metadata: + labels: + tekton.dev/pipelineTask: run-1 + name: pr-run-1-xxyyy + ownerReferences: + - uid: 22222222-2222-2222-2222-222222222222 +`)} + + runsWithNoOwner := []*v1alpha1.Run{parse.MustParseRun(t, ` +metadata: + labels: + tekton.dev/pipelineTask: run-1 + name: pr-run-1-xxyyy +`)} + + return allTaskRuns, taskRunsFromAnotherPR, taskRunsWithNoOwner, allRuns, runsFromAnotherPR, runsWithNoOwner +} + +func mustParsePipelineRunTaskRunStatus(t *testing.T, yamlStr string) *v1beta1.PipelineRunTaskRunStatus { + var output v1beta1.PipelineRunTaskRunStatus + if err := yaml.Unmarshal([]byte(yamlStr), &output); err != nil { + t.Fatalf("parsing task run status %s: %v", yamlStr, err) + } + return &output +} + +func mustParseChildStatusReference(t *testing.T, yamlStr string) v1beta1.ChildStatusReference { + var output v1beta1.ChildStatusReference + if err := yaml.Unmarshal([]byte(yamlStr), &output); err != nil { + t.Fatalf("parsing task run status %s: %v", yamlStr, err) + } + return output +}