@@ -18,7 +18,6 @@ package resources
18
18
19
19
import (
20
20
"fmt"
21
- "reflect"
22
21
23
22
"github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1"
24
23
"github.com/tektoncd/pipeline/pkg/reconciler/pipeline/dag"
@@ -193,53 +192,30 @@ func (facts *PipelineRunFacts) GetPipelineConditionStatus(pr *v1beta1.PipelineRu
193
192
}
194
193
}
195
194
196
- allTasks := []string {}
197
- withStatusTasks := []string {}
198
- skipTasks := []v1beta1.SkippedTask {}
199
- failedTasks := int (0 )
200
- cancelledTasks := int (0 )
201
- reason := v1beta1 .PipelineRunReasonSuccessful .String ()
202
-
203
- // Check to see if all tasks are success or skipped
204
- //
205
- // The completion reason is also calculated here, but it will only be used
206
- // if all tasks are completed.
207
- //
208
- // The pipeline run completion reason is set from the taskrun completion reason
209
- // according to the following logic:
210
- //
211
- // - All successful: ReasonSucceeded
212
- // - Some successful, some skipped: ReasonCompleted
213
- // - Some cancelled, none failed: ReasonCancelled
214
- // - At least one failed: ReasonFailed
215
- for _ , rprt := range facts .State {
216
- allTasks = append (allTasks , rprt .PipelineTask .Name )
217
- switch {
218
- case rprt .IsSuccessful ():
219
- withStatusTasks = append (withStatusTasks , rprt .PipelineTask .Name )
220
- case rprt .Skip (facts ):
221
- withStatusTasks = append (withStatusTasks , rprt .PipelineTask .Name )
222
- skipTasks = append (skipTasks , v1beta1.SkippedTask {Name : rprt .PipelineTask .Name })
223
- // At least one is skipped and no failure yet, mark as completed
224
- if reason == v1beta1 .PipelineRunReasonSuccessful .String () {
225
- reason = v1beta1 .PipelineRunReasonCompleted .String ()
226
- }
227
- case rprt .IsCancelled ():
228
- cancelledTasks ++
229
- withStatusTasks = append (withStatusTasks , rprt .PipelineTask .Name )
230
- if reason != v1beta1 .PipelineRunReasonFailed .String () {
231
- reason = v1beta1 .PipelineRunReasonCancelled .String ()
232
- }
233
- case rprt .IsFailure ():
234
- withStatusTasks = append (withStatusTasks , rprt .PipelineTask .Name )
235
- failedTasks ++
236
- reason = v1beta1 .PipelineRunReasonFailed .String ()
237
- }
238
- }
195
+ // report the count in PipelineRun Status
196
+ // get the count of successful tasks, failed tasks, cancelled tasks, skipped task, and incomplete tasks
197
+ sTasks , fTasks , cTasks , skTasks , iTasks := facts .getPipelineTasksCount ()
198
+ // completed task is a collection of successful, failed, cancelled tasks (skipped tasks are reported separately)
199
+ cmTasks := sTasks + fTasks + cTasks
239
200
240
- if reflect .DeepEqual (allTasks , withStatusTasks ) {
201
+ // The completion reason is set from the TaskRun completion reason
202
+ // by default, set it to ReasonRunning
203
+ reason := v1beta1 .PipelineRunReasonRunning .String ()
204
+
205
+ if facts .checkAllTasksDone () {
241
206
status := corev1 .ConditionTrue
242
- if failedTasks > 0 || cancelledTasks > 0 {
207
+ reason := v1beta1 .PipelineRunReasonSuccessful .String ()
208
+ // Set reason to ReasonCompleted - At least one is skipped
209
+ if skTasks > 0 {
210
+ reason = v1beta1 .PipelineRunReasonCompleted .String ()
211
+ }
212
+ // Set reason to ReasonFailed - At least one failed
213
+ if fTasks > 0 {
214
+ reason = v1beta1 .PipelineRunReasonFailed .String ()
215
+ status = corev1 .ConditionFalse
216
+ // Set reason to ReasonCancelled - At least one is cancelled and no failure yet
217
+ } else if cTasks > 0 {
218
+ reason = v1beta1 .PipelineRunReasonCancelled .String ()
243
219
status = corev1 .ConditionFalse
244
220
}
245
221
logger .Infof ("All TaskRuns have finished for PipelineRun %s so it has finished" , pr .Name )
@@ -248,28 +224,29 @@ func (facts *PipelineRunFacts) GetPipelineConditionStatus(pr *v1beta1.PipelineRu
248
224
Status : status ,
249
225
Reason : reason ,
250
226
Message : fmt .Sprintf ("Tasks Completed: %d (Failed: %d, Cancelled %d), Skipped: %d" ,
251
- len ( allTasks ) - len ( skipTasks ), failedTasks , cancelledTasks , len ( skipTasks ) ),
227
+ cmTasks , fTasks , cTasks , skTasks ),
252
228
}
253
229
}
254
230
255
231
// Hasn't timed out; not all tasks have finished.... Must keep running then....
256
232
// transition pipeline into stopping state when one of the tasks(dag/final) cancelled or one of the dag tasks failed
257
233
// for a pipeline with final tasks, single dag task failure does not transition to interim stopping state
258
234
// pipeline stays in running state until all final tasks are done before transitioning to failed state
259
- if cancelledTasks > 0 || (failedTasks > 0 && facts .CheckFinalTasksDone ()) {
235
+ if cTasks > 0 || (fTasks > 0 && facts .CheckFinalTasksDone ()) {
260
236
reason = v1beta1 .PipelineRunReasonStopping .String ()
261
- } else {
262
- reason = v1beta1 .PipelineRunReasonRunning .String ()
263
237
}
238
+
239
+ // return the status
264
240
return & apis.Condition {
265
241
Type : apis .ConditionSucceeded ,
266
242
Status : corev1 .ConditionUnknown ,
267
243
Reason : reason ,
268
244
Message : fmt .Sprintf ("Tasks Completed: %d (Failed: %d, Cancelled %d), Incomplete: %d, Skipped: %d" ,
269
- len ( withStatusTasks ) - len ( skipTasks ), failedTasks , cancelledTasks , len ( allTasks ) - len ( withStatusTasks ), len ( skipTasks ) ),
245
+ cmTasks , fTasks , cTasks , iTasks , skTasks ),
270
246
}
271
247
}
272
248
249
+ // GetSkippedTasks constructs a list of SkippedTask struct to be included in the PipelineRun Status
273
250
func (facts * PipelineRunFacts ) GetSkippedTasks () []v1beta1.SkippedTask {
274
251
skipped := []v1beta1.SkippedTask {}
275
252
for _ , rprt := range facts .State {
@@ -329,6 +306,48 @@ func (state PipelineRunState) GetTaskRunsStatus(pr *v1beta1.PipelineRun) map[str
329
306
return status
330
307
}
331
308
309
+ // checkAllTasksDone returns true if all DAG and finally tasks have been visited and executed
310
+ // tasks could have either executed successfully or failed or cancelled or skipped
311
+ func (facts * PipelineRunFacts ) checkAllTasksDone () bool {
312
+ for _ , t := range facts .State {
313
+ if t .TaskRun == nil {
314
+ if t .Skip (facts ) {
315
+ continue
316
+ }
317
+ return false
318
+ }
319
+ if ! t .IsDone () && ! t .IsCancelled () {
320
+ return false
321
+ }
322
+ }
323
+ return true
324
+ }
325
+
326
+ // getPipelineTasksCount returns the count of successful tasks, failed tasks, cancelled tasks, skipped task, and incomplete tasks
327
+ func (facts * PipelineRunFacts ) getPipelineTasksCount () (int , int , int , int , int ) {
328
+ s , f , c , sk , i := 0 , 0 , 0 , 0 , 0
329
+ for _ , t := range facts .State {
330
+ switch {
331
+ // increment success counter since the task is successful
332
+ case t .IsSuccessful ():
333
+ s ++
334
+ // increment failure counter since the task has failed
335
+ case t .IsFailure ():
336
+ f ++
337
+ // increment cancelled counter since the task is cancelled
338
+ case t .IsCancelled ():
339
+ c ++
340
+ // increment skip counter since the task is skipped
341
+ case t .Skip (facts ):
342
+ sk ++
343
+ // increment incomplete counter since the task is pending and not executed yet
344
+ default :
345
+ i ++
346
+ }
347
+ }
348
+ return s , f , c , sk , i
349
+ }
350
+
332
351
func (facts * PipelineRunFacts ) isDAGTask (pipelineTaskName string ) bool {
333
352
if _ , ok := facts .TasksGraph .Nodes [pipelineTaskName ]; ok {
334
353
return true
0 commit comments