Skip to content

Commit 232520d

Browse files
authored
Merge pull request [#23](#23)
Feat/run if
2 parents 83fb82a + c03703f commit 232520d

File tree

4 files changed

+74
-35
lines changed

4 files changed

+74
-35
lines changed

examples/run1/Runfile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ tasks:
44
echo:
55
cmd:
66
- echo "hello from run1"
7+
- if: gt 1 0
8+
cmd: echo "hello after condition check"
79

810
node:shell:
911
interactive: true

pkg/runfile/run.go

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ func processOutput(writer io.Writer, reader io.Reader, prefix *string) {
6969
if err != nil {
7070
// logger.Info("stdout", "msg", string(msg[:n]), "err", err)
7171
if errors.Is(err, io.EOF) {
72-
os.Stdout.Write(msg[:n])
72+
writer.Write(msg[:n])
7373
return
7474
}
7575
}
@@ -80,7 +80,7 @@ func processOutput(writer io.Writer, reader io.Reader, prefix *string) {
8080

8181
if prevByte == '\n' && prefix != nil {
8282
// os.Stdout.WriteString(fmt.Sprintf("HERE... msg: '%s'", msg[:n]))
83-
os.Stdout.WriteString(*prefix)
83+
writer.Write([]byte(*prefix))
8484
}
8585

8686
writer.Write(msg[:n])
@@ -124,16 +124,19 @@ func runTask(ctx Context, rf *Runfile, args runTaskArgs) *Error {
124124
logger.Debug("debugging env", "pt.environ", pt.Env, "overrides", args.envOverrides)
125125
for _, command := range pt.Commands {
126126
logger.Debug("running command task", "command.run", command.Run, "parent.task", args.taskName)
127+
128+
if command.If != nil && !*command.If {
129+
logger.Debug("skipping execution for failed `if`", "command", command.Run)
130+
continue
131+
}
132+
127133
if command.Run != "" {
128134
if err := runTask(ctx, rf, runTaskArgs{
129135
taskTrail: trail,
130136
taskName: command.Run,
131137
envOverrides: pt.Env,
132138
}); err != nil {
133139
return err
134-
// return NewError("", "").WithTask(fmt.Sprintf("%s/%s", err.TaskName, command.Run)).WithRunfile(rf.attrs.RunfilePath).WithErr(err.WithMetadata())
135-
// e := formatErr(err).WithTask(fmt.Sprintf("%s/%s", err.TaskName, command.Run))
136-
// return e
137140
}
138141
continue
139142
}

pkg/runfile/task-parser.go

Lines changed: 47 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,31 @@ import (
1313
)
1414

1515
type ParsedTask struct {
16-
Shell []string `json:"shell"`
17-
WorkingDir string `json:"workingDir"`
18-
Env map[string]string `json:"environ"`
19-
Interactive bool `json:"interactive,omitempty"`
20-
Commands []CommandJson `json:"commands"`
16+
Shell []string `json:"shell"`
17+
WorkingDir string `json:"workingDir"`
18+
Env map[string]string `json:"environ"`
19+
Interactive bool `json:"interactive,omitempty"`
20+
Commands []ParsedCommandJson `json:"commands"`
21+
}
22+
23+
func evalGoTemplateCondition(tpl string) (bool, *Error) {
24+
t := template.New("requirement")
25+
t = t.Funcs(sprig.FuncMap())
26+
templateExpr := fmt.Sprintf(`{{ %s }}`, tpl)
27+
t, err := t.Parse(templateExpr)
28+
if err != nil {
29+
return false, TaskRequirementIncorrect.WithErr(err).WithMetadata("requirement", tpl)
30+
}
31+
b := new(bytes.Buffer)
32+
if err := t.ExecuteTemplate(b, "requirement", map[string]string{}); err != nil {
33+
return false, TaskRequirementIncorrect.WithErr(err).WithMetadata("requirement", tpl)
34+
}
35+
36+
if b.String() != "true" {
37+
return false, TaskRequirementFailed.WithErr(fmt.Errorf("template must have evaluated to true")).WithMetadata("requirement", tpl)
38+
}
39+
40+
return true, nil
2141
}
2242

2343
func ParseTask(ctx Context, rf *Runfile, task Task) (*ParsedTask, *Error) {
@@ -71,22 +91,9 @@ func ParseTask(ctx Context, rf *Runfile, task Task) (*ParsedTask, *Error) {
7191
}
7292

7393
if requirement.GoTmpl != nil {
74-
t := template.New("requirement")
75-
t = t.Funcs(sprig.FuncMap())
76-
templateExpr := fmt.Sprintf(`{{ %s }}`, *requirement.GoTmpl)
77-
t, err := t.Parse(templateExpr)
78-
if err != nil {
79-
return nil, TaskRequirementIncorrect.WithErr(err).WithMetadata("requirement", *requirement.GoTmpl)
80-
}
81-
b := new(bytes.Buffer)
82-
if err := t.ExecuteTemplate(b, "requirement", map[string]string{}); err != nil {
83-
return nil, TaskRequirementIncorrect.WithErr(err).WithMetadata("requirement", *requirement.GoTmpl)
84-
}
85-
86-
if b.String() != "true" {
87-
return nil, TaskRequirementFailed.WithErr(fmt.Errorf("template must have evaluated to true")).WithMetadata("requirement", *requirement.GoTmpl)
94+
if _, err := evalGoTemplateCondition(*requirement.GoTmpl); err != nil {
95+
return nil, err
8896
}
89-
9097
continue
9198
}
9299
}
@@ -127,7 +134,7 @@ func ParseTask(ctx Context, rf *Runfile, task Task) (*ParsedTask, *Error) {
127134
return nil, err
128135
}
129136

130-
commands := make([]CommandJson, 0, len(task.Commands))
137+
commands := make([]ParsedCommandJson, 0, len(task.Commands))
131138
for i := range task.Commands {
132139
c2, err := parseCommand(rf, task.Commands[i])
133140
if err != nil {
@@ -169,11 +176,11 @@ func resolveDotEnvFiles(pwd string, dotEnvFiles ...string) ([]string, *Error) {
169176
return paths, nil
170177
}
171178

172-
func parseCommand(rf *Runfile, command any) (*CommandJson, *Error) {
179+
func parseCommand(rf *Runfile, command any) (*ParsedCommandJson, *Error) {
173180
switch c := command.(type) {
174181
case string:
175182
{
176-
return &CommandJson{Command: c}, nil
183+
return &ParsedCommandJson{Command: c}, nil
177184
}
178185
case map[string]any:
179186
{
@@ -187,15 +194,27 @@ func parseCommand(rf *Runfile, command any) (*CommandJson, *Error) {
187194
return nil, CommandInvalid.WithErr(err).WithMetadata("command", command)
188195
}
189196

190-
if cj.Run == "" {
191-
return nil, CommandInvalid.WithErr(fmt.Errorf("key: 'run', must be specified when setting command in json format")).WithMetadata("command", command)
197+
if cj.Run == "" && cj.Command == "" {
198+
return nil, CommandInvalid.WithErr(fmt.Errorf("key: 'run'/'cmd', must be specified when setting command in json format")).WithMetadata("command", cj)
192199
}
193200

194-
if _, ok := rf.Tasks[cj.Run]; !ok {
195-
return nil, CommandInvalid.WithErr(fmt.Errorf("run target, not found")).WithMetadata("command", command, "run-target", cj.Run)
201+
var pcj ParsedCommandJson
202+
pcj.Run = cj.Run
203+
pcj.Command = cj.Command
204+
205+
if cj.If != nil {
206+
ok, _ := evalGoTemplateCondition(*cj.If)
207+
// if err != nil {
208+
// return nil, err
209+
// }
210+
pcj.If = &ok
196211
}
197212

198-
return &cj, nil
213+
// if _, ok := rf.Tasks[cj.Run]; !ok {
214+
// return nil, CommandInvalid.WithErr(fmt.Errorf("run target, not found")).WithMetadata("command", command, "run-target", cj.Run)
215+
// }
216+
217+
return &pcj, nil
199218
}
200219
default:
201220
{

pkg/runfile/task.go

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,26 @@ type Task struct {
4646
// List of commands to be executed in given shell (default: sh)
4747
// can take multiple forms
4848
// - simple string
49-
// - a json object with key `run`, signifying other tasks to run
49+
// - a json object with key
50+
// `run`, signifying other tasks to run
51+
// `if`, condition when to run this server
5052
Commands []any `json:"cmd"`
5153
}
5254

5355
type CommandJson struct {
54-
Command string
56+
Command string `json:"cmd"`
5557
Run string `json:"run"`
58+
Env string `json:"env"`
59+
60+
// If is a go template expression, which must evaluate to true, for task to run
61+
If *string `json:"if,omitempty"`
62+
}
63+
64+
type ParsedCommandJson struct {
65+
Command string `json:"cmd"`
66+
Run string `json:"run"`
67+
Env string `json:"env"`
68+
69+
// If is a go template expression, which must evaluate to true, for task to run
70+
If *bool `json:"if"`
5671
}

0 commit comments

Comments
 (0)