Skip to content

Commit

Permalink
Merge pull request [#23](#23)
Browse files Browse the repository at this point in the history
Feat/run if
  • Loading branch information
nxtcoder17 authored Nov 17, 2024
2 parents 83fb82a + c03703f commit 232520d
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 35 deletions.
2 changes: 2 additions & 0 deletions examples/run1/Runfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ tasks:
echo:
cmd:
- echo "hello from run1"
- if: gt 1 0
cmd: echo "hello after condition check"

node:shell:
interactive: true
Expand Down
13 changes: 8 additions & 5 deletions pkg/runfile/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ func processOutput(writer io.Writer, reader io.Reader, prefix *string) {
if err != nil {
// logger.Info("stdout", "msg", string(msg[:n]), "err", err)
if errors.Is(err, io.EOF) {
os.Stdout.Write(msg[:n])
writer.Write(msg[:n])
return
}
}
Expand All @@ -80,7 +80,7 @@ func processOutput(writer io.Writer, reader io.Reader, prefix *string) {

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

writer.Write(msg[:n])
Expand Down Expand Up @@ -124,16 +124,19 @@ func runTask(ctx Context, rf *Runfile, args runTaskArgs) *Error {
logger.Debug("debugging env", "pt.environ", pt.Env, "overrides", args.envOverrides)
for _, command := range pt.Commands {
logger.Debug("running command task", "command.run", command.Run, "parent.task", args.taskName)

if command.If != nil && !*command.If {
logger.Debug("skipping execution for failed `if`", "command", command.Run)
continue
}

if command.Run != "" {
if err := runTask(ctx, rf, runTaskArgs{
taskTrail: trail,
taskName: command.Run,
envOverrides: pt.Env,
}); err != nil {
return err
// return NewError("", "").WithTask(fmt.Sprintf("%s/%s", err.TaskName, command.Run)).WithRunfile(rf.attrs.RunfilePath).WithErr(err.WithMetadata())
// e := formatErr(err).WithTask(fmt.Sprintf("%s/%s", err.TaskName, command.Run))
// return e
}
continue
}
Expand Down
75 changes: 47 additions & 28 deletions pkg/runfile/task-parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,31 @@ import (
)

type ParsedTask struct {
Shell []string `json:"shell"`
WorkingDir string `json:"workingDir"`
Env map[string]string `json:"environ"`
Interactive bool `json:"interactive,omitempty"`
Commands []CommandJson `json:"commands"`
Shell []string `json:"shell"`
WorkingDir string `json:"workingDir"`
Env map[string]string `json:"environ"`
Interactive bool `json:"interactive,omitempty"`
Commands []ParsedCommandJson `json:"commands"`
}

func evalGoTemplateCondition(tpl string) (bool, *Error) {
t := template.New("requirement")
t = t.Funcs(sprig.FuncMap())
templateExpr := fmt.Sprintf(`{{ %s }}`, tpl)
t, err := t.Parse(templateExpr)
if err != nil {
return false, TaskRequirementIncorrect.WithErr(err).WithMetadata("requirement", tpl)
}
b := new(bytes.Buffer)
if err := t.ExecuteTemplate(b, "requirement", map[string]string{}); err != nil {
return false, TaskRequirementIncorrect.WithErr(err).WithMetadata("requirement", tpl)
}

if b.String() != "true" {
return false, TaskRequirementFailed.WithErr(fmt.Errorf("template must have evaluated to true")).WithMetadata("requirement", tpl)
}

return true, nil
}

func ParseTask(ctx Context, rf *Runfile, task Task) (*ParsedTask, *Error) {
Expand Down Expand Up @@ -71,22 +91,9 @@ func ParseTask(ctx Context, rf *Runfile, task Task) (*ParsedTask, *Error) {
}

if requirement.GoTmpl != nil {
t := template.New("requirement")
t = t.Funcs(sprig.FuncMap())
templateExpr := fmt.Sprintf(`{{ %s }}`, *requirement.GoTmpl)
t, err := t.Parse(templateExpr)
if err != nil {
return nil, TaskRequirementIncorrect.WithErr(err).WithMetadata("requirement", *requirement.GoTmpl)
}
b := new(bytes.Buffer)
if err := t.ExecuteTemplate(b, "requirement", map[string]string{}); err != nil {
return nil, TaskRequirementIncorrect.WithErr(err).WithMetadata("requirement", *requirement.GoTmpl)
}

if b.String() != "true" {
return nil, TaskRequirementFailed.WithErr(fmt.Errorf("template must have evaluated to true")).WithMetadata("requirement", *requirement.GoTmpl)
if _, err := evalGoTemplateCondition(*requirement.GoTmpl); err != nil {
return nil, err
}

continue
}
}
Expand Down Expand Up @@ -127,7 +134,7 @@ func ParseTask(ctx Context, rf *Runfile, task Task) (*ParsedTask, *Error) {
return nil, err
}

commands := make([]CommandJson, 0, len(task.Commands))
commands := make([]ParsedCommandJson, 0, len(task.Commands))
for i := range task.Commands {
c2, err := parseCommand(rf, task.Commands[i])
if err != nil {
Expand Down Expand Up @@ -169,11 +176,11 @@ func resolveDotEnvFiles(pwd string, dotEnvFiles ...string) ([]string, *Error) {
return paths, nil
}

func parseCommand(rf *Runfile, command any) (*CommandJson, *Error) {
func parseCommand(rf *Runfile, command any) (*ParsedCommandJson, *Error) {
switch c := command.(type) {
case string:
{
return &CommandJson{Command: c}, nil
return &ParsedCommandJson{Command: c}, nil
}
case map[string]any:
{
Expand All @@ -187,15 +194,27 @@ func parseCommand(rf *Runfile, command any) (*CommandJson, *Error) {
return nil, CommandInvalid.WithErr(err).WithMetadata("command", command)
}

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

if _, ok := rf.Tasks[cj.Run]; !ok {
return nil, CommandInvalid.WithErr(fmt.Errorf("run target, not found")).WithMetadata("command", command, "run-target", cj.Run)
var pcj ParsedCommandJson
pcj.Run = cj.Run
pcj.Command = cj.Command

if cj.If != nil {
ok, _ := evalGoTemplateCondition(*cj.If)
// if err != nil {
// return nil, err
// }
pcj.If = &ok
}

return &cj, nil
// if _, ok := rf.Tasks[cj.Run]; !ok {
// return nil, CommandInvalid.WithErr(fmt.Errorf("run target, not found")).WithMetadata("command", command, "run-target", cj.Run)
// }

return &pcj, nil
}
default:
{
Expand Down
19 changes: 17 additions & 2 deletions pkg/runfile/task.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,26 @@ type Task struct {
// List of commands to be executed in given shell (default: sh)
// can take multiple forms
// - simple string
// - a json object with key `run`, signifying other tasks to run
// - a json object with key
// `run`, signifying other tasks to run
// `if`, condition when to run this server
Commands []any `json:"cmd"`
}

type CommandJson struct {
Command string
Command string `json:"cmd"`
Run string `json:"run"`
Env string `json:"env"`

// If is a go template expression, which must evaluate to true, for task to run
If *string `json:"if,omitempty"`
}

type ParsedCommandJson struct {
Command string `json:"cmd"`
Run string `json:"run"`
Env string `json:"env"`

// If is a go template expression, which must evaluate to true, for task to run
If *bool `json:"if"`
}

0 comments on commit 232520d

Please sign in to comment.