github.com/clusterize-io/tusk@v0.6.3-0.20211001020217-cfe8a8cd0d4a/runner/run.go (about)

     1  package runner
     2  
     3  import (
     4  	"errors"
     5  
     6  	"github.com/clusterize-io/tusk/marshal"
     7  )
     8  
     9  // Run defines a a single runnable item within a task.
    10  type Run struct {
    11  	When           WhenList           `yaml:",omitempty"`
    12  	Command        CommandList        `yaml:",omitempty"`
    13  	SubTaskList    SubTaskList        `yaml:"task,omitempty"`
    14  	SetEnvironment map[string]*string `yaml:"set-environment,omitempty"`
    15  
    16  	// Computed members not specified in yaml file
    17  	Tasks []Task `yaml:"-"`
    18  }
    19  
    20  // UnmarshalYAML allows simple commands to represent run structs.
    21  func (r *Run) UnmarshalYAML(unmarshal func(interface{}) error) error {
    22  	var cl CommandList
    23  	commandCandidate := marshal.UnmarshalCandidate{
    24  		Unmarshal: func() error { return unmarshal(&cl) },
    25  		Assign:    func() { *r = Run{Command: cl} },
    26  	}
    27  
    28  	type runType Run // Use new type to avoid recursion
    29  	var runItem runType
    30  	runCandidate := marshal.UnmarshalCandidate{
    31  		Unmarshal: func() error { return unmarshal(&runItem) },
    32  		Assign:    func() { *r = Run(runItem) },
    33  		Validate: func() error {
    34  			actionUsedList := []bool{
    35  				len(runItem.Command) != 0,
    36  				len(runItem.SubTaskList) != 0,
    37  				runItem.SetEnvironment != nil,
    38  			}
    39  
    40  			count := 0
    41  			for _, isUsed := range actionUsedList {
    42  				if isUsed {
    43  					count++
    44  				}
    45  			}
    46  
    47  			if count > 1 {
    48  				return errors.New("only one action can be defined in `run`")
    49  			}
    50  
    51  			return nil
    52  		},
    53  	}
    54  
    55  	return marshal.UnmarshalOneOf(commandCandidate, runCandidate)
    56  }
    57  
    58  func (r *Run) shouldRun(ctx Context, vars map[string]string) (bool, error) {
    59  	if err := r.When.Validate(ctx, vars); err != nil {
    60  		if !IsFailedCondition(err) {
    61  			return false, err
    62  		}
    63  
    64  		for _, command := range r.Command {
    65  			ctx.Logger.PrintSkipped(command.Print, err.Error())
    66  		}
    67  
    68  		for _, subTask := range r.SubTaskList {
    69  			ctx.Logger.PrintSkipped("task: "+subTask.Name, err.Error())
    70  		}
    71  
    72  		return false, nil
    73  	}
    74  
    75  	return true, nil
    76  }
    77  
    78  // RunList is a list of run items with custom yaml unmarshaling.
    79  type RunList []*Run
    80  
    81  // UnmarshalYAML allows single items to be used as lists.
    82  func (rl *RunList) UnmarshalYAML(unmarshal func(interface{}) error) error {
    83  	var runSlice []*Run
    84  	sliceCandidate := marshal.UnmarshalCandidate{
    85  		Unmarshal: func() error { return unmarshal(&runSlice) },
    86  		Assign:    func() { *rl = runSlice },
    87  	}
    88  
    89  	var runItem *Run
    90  	itemCandidate := marshal.UnmarshalCandidate{
    91  		Unmarshal: func() error { return unmarshal(&runItem) },
    92  		Assign:    func() { *rl = RunList{runItem} },
    93  	}
    94  
    95  	return marshal.UnmarshalOneOf(sliceCandidate, itemCandidate)
    96  }