Repository: kubeflow/kfp-tekton (language: python)

Issue:
Make pipelineloop to break when seeing a pipelineloop break operation task
/kind feature

**Description:**
Currently, pipelineloop can break the loop when it sees a task is getting skipped. However, it would make more sense in the DSL if we can have it to also break the loop when it sees a specific task prefix name. This should be an addition to the current break feature instead of replacing it.


**Additional information:**
[Miscellaneous information that will assist in solving the issue.]



Discussion / hints:
Currently the pipeline loop break only happens when the task is skipped as below. We want to extend this logic to also check whether any task with `pipelineloop-break-operation` prefix in the task name is executed. If so, we should break the loop as below as well. This way, we can have multiple break tasks in the DSL and all of them will have the task prefix `pipelineloop-break-operation`. 
https://github.com/kubeflow/kfp-tekton/blob/c4f52e5f1c360e577187be6c447b5afc1c0505cb/tekton-catalog/pipeline-loops/pkg/reconciler/pipelinelooprun/pipelinelooprun.go#L558-L571
/assign @ScrapCodes 

Fix patch:
diff --git a/tekton-catalog/pipeline-loops/pkg/reconciler/pipelinelooprun/pipelinelooprun.go b/tekton-catalog/pipeline-loops/pkg/reconciler/pipelinelooprun/pipelinelooprun.go
index 0d8a9925cf..8a1a8ef2f9 100644
--- a/tekton-catalog/pipeline-loops/pkg/reconciler/pipelinelooprun/pipelinelooprun.go
+++ b/tekton-catalog/pipeline-loops/pkg/reconciler/pipelinelooprun/pipelinelooprun.go
@@ -569,6 +569,17 @@ func (c *Reconciler) updatePipelineRunStatus(logger *zap.SugaredLogger, run *v1a
 				}
 			}
 		}
+		for _, runStatus := range pr.Status.Runs {
+			if strings.HasPrefix(runStatus.PipelineTaskName, "pipelineloop-break-operation") {
+				// Mark run successful and stop the loop pipelinerun
+				run.Status.MarkRunSucceeded(pipelineloopv1alpha1.PipelineLoopRunReasonSucceeded.String(),
+					"PipelineRuns completed successfully with the conditions are met")
+				run.Status.Results = []runv1alpha1.RunResult{{
+					Name:  "condition",
+					Value: "pass",
+				}}
+			}
+		}
 
 		status.PipelineRuns[pr.Name] = &pipelineloopv1alpha1.PipelineLoopPipelineRunStatus{
 			Iteration: iteration,


Test patch:
diff --git a/.github/workflows/kfp-tekton-unittests.yml b/.github/workflows/kfp-tekton-unittests.yml
index 2ad8656537..f879446e6c 100644
--- a/.github/workflows/kfp-tekton-unittests.yml
+++ b/.github/workflows/kfp-tekton-unittests.yml
@@ -9,6 +9,7 @@ on:
 
 env:
   GITHUB_ACTION: "true"
+  SETUPTOOLS_USE_DISTUTILS: "stdlib"
 
 jobs:
   python-unittest: