Skip to content

Commit

Permalink
Merge pull request [#22] (#22)
Browse files Browse the repository at this point in the history
feat: interactive commands support
  • Loading branch information
nxtcoder17 authored Nov 10, 2024
2 parents 9472489 + 652ecf4 commit 83fb82a
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 38 deletions.
5 changes: 5 additions & 0 deletions examples/run1/Runfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,8 @@ tasks:
echo:
cmd:
- echo "hello from run1"

node:shell:
interactive: true
cmd:
- node
88 changes: 58 additions & 30 deletions pkg/runfile/run.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package runfile

import (
"bufio"
"errors"
"fmt"
"io"
"os"
"os/exec"
"path/filepath"
"strings"
"sync"

fn "github.com/nxtcoder17/runfile/pkg/functions"
"golang.org/x/sync/errgroup"
Expand All @@ -20,8 +21,9 @@ type cmdArgs struct {

cmd string

stdout io.Writer
stderr io.Writer
interactive bool
stdout io.Writer
stderr io.Writer
}

func createCommand(ctx Context, args cmdArgs) *exec.Cmd {
Expand All @@ -46,6 +48,10 @@ func createCommand(ctx Context, args cmdArgs) *exec.Cmd {
c.Stdout = args.stdout
c.Stderr = args.stderr

if args.interactive {
c.Stdin = os.Stdin
}

return c
}

Expand All @@ -55,6 +61,33 @@ type runTaskArgs struct {
envOverrides map[string]string
}

func processOutput(writer io.Writer, reader io.Reader, prefix *string) {
prevByte := byte('\n')
msg := make([]byte, 1)
for {
n, err := reader.Read(msg)
if err != nil {
// logger.Info("stdout", "msg", string(msg[:n]), "err", err)
if errors.Is(err, io.EOF) {
os.Stdout.Write(msg[:n])
return
}
}

if n != 1 {
continue
}

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

writer.Write(msg[:n])
prevByte = msg[0]
}
}

func runTask(ctx Context, rf *Runfile, args runTaskArgs) *Error {
runfilePath := fn.Must(filepath.Rel(rf.attrs.RootRunfilePath, rf.attrs.RunfilePath))

Expand Down Expand Up @@ -108,44 +141,39 @@ func runTask(ctx Context, rf *Runfile, args runTaskArgs) *Error {
stdoutR, stdoutW := io.Pipe()
stderrR, stderrW := io.Pipe()

wg := sync.WaitGroup{}

wg.Add(1)
go func() {
r := bufio.NewReader(stdoutR)
for {
b, err := r.ReadBytes('\n')
if err != nil {
logger.Info("stdout", "msg", string(b), "err", err)
// return
break
}
fmt.Fprintf(os.Stdout, "%s %s", ctx.theme.TaskPrefixStyle.Render(fmt.Sprintf("[%s]", strings.Join(trail, "/"))), b)
}
defer wg.Done()
logPrefix := fmt.Sprintf("%s ", ctx.theme.TaskPrefixStyle.Render(fmt.Sprintf("[%s]", strings.Join(trail, "/"))))
processOutput(os.Stdout, stdoutR, &logPrefix)
}()

wg.Add(1)
go func() {
r := bufio.NewReader(stderrR)
for {
b, err := r.ReadBytes('\n')
if err != nil {
fmt.Printf("hello err: %+v\n", err)
logger.Info("stderr", "err", err)
// return
break
}
fmt.Fprintf(os.Stderr, "%s %s", ctx.theme.TaskPrefixStyle.Render(fmt.Sprintf("[%s]", strings.Join(trail, "/"))), b)
}
defer wg.Done()
logPrefix := fmt.Sprintf("%s ", ctx.theme.TaskPrefixStyle.Render(fmt.Sprintf("[%s]", strings.Join(trail, "/"))))
processOutput(os.Stderr, stderrR, &logPrefix)
}()

cmd := createCommand(ctx, cmdArgs{
shell: pt.Shell,
env: ToEnviron(pt.Env),
cmd: command.Command,
workingDir: pt.WorkingDir,
stdout: stdoutW,
stderr: stderrW,
shell: pt.Shell,
env: ToEnviron(pt.Env),
cmd: command.Command,
workingDir: pt.WorkingDir,
interactive: pt.Interactive,
stdout: stdoutW,
stderr: stderrW,
})
if err := cmd.Run(); err != nil {
return formatErr(CommandFailed).WithErr(err)
}

stdoutW.Close()
stderrW.Close()

wg.Wait()
}

return nil
Expand Down
18 changes: 10 additions & 8 deletions pkg/runfile/task-parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@ import (
)

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

func ParseTask(ctx Context, rf *Runfile, task Task) (*ParsedTask, *Error) {
Expand Down Expand Up @@ -136,10 +137,11 @@ func ParseTask(ctx Context, rf *Runfile, task Task) (*ParsedTask, *Error) {
}

return &ParsedTask{
Shell: task.Shell,
WorkingDir: *task.Dir,
Env: fn.MapMerge(globalEnv, taskDotenvVars, taskEnvVars),
Commands: commands,
Shell: task.Shell,
WorkingDir: *task.Dir,
Interactive: task.Interactive,
Env: fn.MapMerge(globalEnv, taskDotenvVars, taskEnvVars),
Commands: commands,
}, nil
}

Expand Down
43 changes: 43 additions & 0 deletions pkg/runfile/task-parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ func TestParseTask(t *testing.T) {
return false
}

if got.Interactive != want.Interactive {
t.Logf("interactive not equal")
return false
}

if len(got.Env) != len(want.Env) {
t.Logf("environments not equal")
return false
Expand Down Expand Up @@ -629,6 +634,44 @@ echo "hi"
},
wantErr: true,
},

{
name: "[task] interactive task",
args: args{
ctx: nil,
rf: &Runfile{
Tasks: map[string]Task{
"test": {
ignoreSystemEnv: true,
Interactive: true,
Commands: []any{
"echo i will call hello, now",
map[string]any{
"run": "hello",
},
},
},
"hello": {
ignoreSystemEnv: true,
Commands: []any{
"echo hello everyone",
},
},
},
},
taskName: "test",
},
want: &ParsedTask{
Shell: []string{"sh", "-c"},
WorkingDir: fn.Must(os.Getwd()),
Interactive: true,
Commands: []CommandJson{
{Command: "echo i will call hello, now"},
{Run: "hello"},
},
},
wantErr: false,
},
}

testGlobalEnvVars := []test{
Expand Down
2 changes: 2 additions & 0 deletions pkg/runfile/task.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ type Task struct {

Requires []*Requires `json:"requires,omitempty"`

Interactive bool `json:"interactive,omitempty"`

// List of commands to be executed in given shell (default: sh)
// can take multiple forms
// - simple string
Expand Down

0 comments on commit 83fb82a

Please sign in to comment.