github.com/pf-qiu/concourse/v6@v6.7.3-0.20201207032516-1f455d73275f/atc/exec/on_error.go (about) 1 package exec 2 3 import ( 4 "context" 5 "errors" 6 7 "github.com/hashicorp/go-multierror" 8 ) 9 10 // OnErrorStep will run one step, and then a second step if the first step 11 // errors. 12 type OnErrorStep struct { 13 step Step 14 hook Step 15 } 16 17 // OnError constructs an OnErrorStep factory. 18 func OnError(step Step, hook Step) OnErrorStep { 19 return OnErrorStep{ 20 step: step, 21 hook: hook, 22 } 23 } 24 25 // Run will call Run on the first step and wait for it to complete. If the 26 // first step errors, Run returns the error. OnErrorStep is ready as soon as 27 // the first step is ready. 28 // 29 // If the first step errors, the second 30 // step is executed. If the second step errors, nothing is returned. 31 func (o OnErrorStep) Run(ctx context.Context, state RunState) (bool, error) { 32 var errs error 33 stepRunOk, stepRunErr := o.step.Run(ctx, state) 34 // with no error, we just want to return right away 35 if stepRunErr == nil { 36 return stepRunOk, nil 37 } 38 errs = multierror.Append(errs, stepRunErr) 39 40 // for all errors that aren't caused by an Abort, run the hook 41 if !errors.Is(stepRunErr, context.Canceled) { 42 _, err := o.hook.Run(context.Background(), state) 43 if err != nil { 44 // This causes to return both the errors as expected. 45 errs = multierror.Append(errs, err) 46 } 47 } 48 49 return stepRunOk, errs 50 }