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  }