@@ -20,6 +20,7 @@ import (
2020 "context"
2121 "encoding/json"
2222 "fmt"
23+ "github.com/tektoncd/pipeline/pkg/reconciler/pipeline/dag"
2324 "log"
2425 "strings"
2526 "time"
@@ -59,11 +60,51 @@ func init() {
5960
6061// cancelPipelineRun marks the PipelineRun as cancelled and any resolved TaskRun(s) too.
6162func cancelPipelineRun (ctx context.Context , logger * zap.SugaredLogger , pr * v1beta1.PipelineRun , clientSet clientset.Interface ) error {
63+ errs := cancelPipelineTaskRuns (ctx , logger , pr , nil , clientSet )
64+
65+ // If we successfully cancelled all the TaskRuns and Runs, we can consider the PipelineRun cancelled.
66+ if len (errs ) == 0 {
67+ pr .Status .SetCondition (& apis.Condition {
68+ Type : apis .ConditionSucceeded ,
69+ Status : corev1 .ConditionFalse ,
70+ Reason : ReasonCancelled ,
71+ Message : fmt .Sprintf ("PipelineRun %q was cancelled" , pr .Name ),
72+ })
73+ // update pr completed time
74+ pr .Status .CompletionTime = & metav1.Time {Time : time .Now ()}
75+ } else {
76+ e := strings .Join (errs , "\n " )
77+ // Indicate that we failed to cancel the PipelineRun
78+ pr .Status .SetCondition (& apis.Condition {
79+ Type : apis .ConditionSucceeded ,
80+ Status : corev1 .ConditionUnknown ,
81+ Reason : ReasonCouldntCancel ,
82+ Message : fmt .Sprintf ("PipelineRun %q was cancelled but had errors trying to cancel TaskRuns and/or Runs: %s" , pr .Name , e ),
83+ })
84+ return fmt .Errorf ("error(s) from cancelling TaskRun(s) from PipelineRun %s: %s" , pr .Name , e )
85+ }
86+ return nil
87+ }
88+
89+ // cancelPipelineTaskRuns patches `TaskRun` and `Run` with canceled status
90+ func cancelPipelineTaskRuns (ctx context.Context , logger * zap.SugaredLogger , pr * v1beta1.PipelineRun , omitTaskGraph * dag.Graph , clientSet clientset.Interface ) []string {
6291 errs := []string {}
6392
93+ isTaskOmittedFromCancel := func (taskName string ) bool {
94+ if omitTaskGraph == nil {
95+ return false
96+ }
97+ _ , ok := omitTaskGraph .Nodes [taskName ]
98+ return ok
99+ }
100+
64101 // Loop over the TaskRuns in the PipelineRun status.
65102 // If a TaskRun is not in the status yet we should not cancel it anyways.
66- for taskRunName := range pr .Status .TaskRuns {
103+ for taskRunName , taskRun := range pr .Status .TaskRuns {
104+ if isTaskOmittedFromCancel (taskRun .PipelineTaskName ) {
105+ continue
106+ }
107+
67108 logger .Infof ("cancelling TaskRun %s" , taskRunName )
68109
69110 if _ , err := clientSet .TektonV1beta1 ().TaskRuns (pr .Namespace ).Patch (ctx , taskRunName , types .JSONPatchType , cancelTaskRunPatchBytes , metav1.PatchOptions {}, "" ); err != nil {
@@ -72,25 +113,28 @@ func cancelPipelineRun(ctx context.Context, logger *zap.SugaredLogger, pr *v1bet
72113 }
73114 }
74115 // Loop over the Runs in the PipelineRun status.
75- for runName := range pr .Status .Runs {
116+ for runName , run := range pr .Status .Runs {
117+ if isTaskOmittedFromCancel (run .PipelineTaskName ) {
118+ continue
119+ }
120+
76121 logger .Infof ("cancelling Run %s" , runName )
77122
78123 if _ , err := clientSet .TektonV1alpha1 ().Runs (pr .Namespace ).Patch (ctx , runName , types .JSONPatchType , cancelRunPatchBytes , metav1.PatchOptions {}, "" ); err != nil {
79124 errs = append (errs , fmt .Errorf ("Failed to patch Run `%s` with cancellation: %s" , runName , err ).Error ())
80125 continue
81126 }
82127 }
83- // If we successfully cancelled all the TaskRuns and Runs, we can consider the PipelineRun cancelled.
84- if len (errs ) == 0 {
85- pr .Status .SetCondition (& apis.Condition {
86- Type : apis .ConditionSucceeded ,
87- Status : corev1 .ConditionFalse ,
88- Reason : ReasonCancelled ,
89- Message : fmt .Sprintf ("PipelineRun %q was cancelled" , pr .Name ),
90- })
91- // update pr completed time
92- pr .Status .CompletionTime = & metav1.Time {Time : time .Now ()}
93- } else {
128+
129+ return errs
130+ }
131+
132+ // stopPipelineRun marks the PipelineRun as stopping, any resolved TaskRun(s) as cancelled and runs finally.
133+ func stopPipelineRun (ctx context.Context , logger * zap.SugaredLogger , pr * v1beta1.PipelineRun , finalTaskGraph * dag.Graph , clientSet clientset.Interface ) error {
134+ errs := cancelPipelineTaskRuns (ctx , logger , pr , finalTaskGraph , clientSet )
135+
136+ // If we successfully cancelled all the TaskRuns and Runs, we can proceed with the PipelineRun reconciliation to trigger finally.
137+ if len (errs ) > 0 {
94138 e := strings .Join (errs , "\n " )
95139 // Indicate that we failed to cancel the PipelineRun
96140 pr .Status .SetCondition (& apis.Condition {
0 commit comments