1package exec
2
3import (
4	"context"
5)
6
7// OnFailureStep will run one step, and then a second step if the first step
8// fails (but not errors).
9type OnFailureStep struct {
10	step Step
11	hook Step
12}
13
14// OnFailure constructs an OnFailureStep factory.
15func OnFailure(firstStep Step, secondStep Step) OnFailureStep {
16	return OnFailureStep{
17		step: firstStep,
18		hook: secondStep,
19	}
20}
21
22// Run will call Run on the first step and wait for it to complete. If the
23// first step errors, Run returns the error. OnFailureStep is ready as soon as
24// the first step is ready.
25//
26// If the first step fails (that is, its Success result is false), the second
27// step is executed. If the second step errors, its error is returned.
28func (o OnFailureStep) Run(ctx context.Context, state RunState) error {
29	err := o.step.Run(ctx, state)
30	if err != nil {
31		return err
32	}
33
34	if !o.step.Succeeded() {
35		return o.hook.Run(ctx, state)
36	}
37
38	return nil
39}
40
41// Succeeded is true if the first step doesn't exist, or if it
42// completed successfully.
43func (o OnFailureStep) Succeeded() bool {
44	return o.step.Succeeded()
45}
46