diff --git a/pkg/reconciler/pipelinerun/resources/pipelinerunstate.go b/pkg/reconciler/pipelinerun/resources/pipelinerunstate.go index cc2b22730da..ba8c0bb2542 100644 --- a/pkg/reconciler/pipelinerun/resources/pipelinerunstate.go +++ b/pkg/reconciler/pipelinerun/resources/pipelinerunstate.go @@ -415,6 +415,15 @@ func (facts *PipelineRunFacts) GetPipelineConditionStatus(ctx context.Context, p } } + if pr.HaveTasksTimedOut(ctx, c) { + return &apis.Condition{ + Type: apis.ConditionSucceeded, + Status: corev1.ConditionFalse, + Reason: v1.PipelineRunReasonTimedOut.String(), + Message: fmt.Sprintf("PipelineRun %q failed to finish within %q", pr.Name, pr.TasksTimeout().Duration.String()), + } + } + // report the count in PipelineRun Status // get the count of successful tasks, failed tasks, cancelled tasks, skipped task, and incomplete tasks s := facts.getPipelineTasksCount() diff --git a/pkg/reconciler/pipelinerun/resources/pipelinerunstate_test.go b/pkg/reconciler/pipelinerun/resources/pipelinerunstate_test.go index c709a6ae218..86f64f47e52 100644 --- a/pkg/reconciler/pipelinerun/resources/pipelinerunstate_test.go +++ b/pkg/reconciler/pipelinerun/resources/pipelinerunstate_test.go @@ -2141,6 +2141,39 @@ func TestGetPipelineConditionStatus_PipelineTimeouts(t *testing.T) { } } +// pipeline should result in timeout if its runtime exceeds its spec.Timeouts.Tasks based on its status.Timeout +func TestGetPipelineConditionStatus_PipelineTasksTimeouts(t *testing.T) { + d, err := dagFromState(oneFinishedState) + if err != nil { + t.Fatalf("Unexpected error while building DAG for state %v: %v", oneFinishedState, err) + } + pr := &v1.PipelineRun{ + ObjectMeta: metav1.ObjectMeta{Name: "pipelinerun-no-tasks-started"}, + Spec: v1.PipelineRunSpec{ + Timeouts: &v1.TimeoutFields{ + Tasks: &metav1.Duration{Duration: 1 * time.Minute}, + }, + }, + Status: v1.PipelineRunStatus{ + PipelineRunStatusFields: v1.PipelineRunStatusFields{ + StartTime: &metav1.Time{Time: now.Add(-2 * time.Minute)}, + }, + }, + } + facts := PipelineRunFacts{ + State: oneFinishedState, + TasksGraph: d, + FinalTasksGraph: &dag.Graph{}, + TimeoutsState: PipelineRunTimeoutsState{ + Clock: testClock, + }, + } + c := facts.GetPipelineConditionStatus(context.Background(), pr, zap.NewNop().Sugar(), testClock) + if c.Status != corev1.ConditionFalse && c.Reason != v1.PipelineRunReasonTimedOut.String() { + t.Fatalf("Expected to get status %s but got %s for state %v", corev1.ConditionFalse, c.Status, oneFinishedState) + } +} + func TestGetPipelineConditionStatus_OnError(t *testing.T) { var oneFailedStateOnError = PipelineRunState{{ PipelineTask: &v1.PipelineTask{