Skip to content

Commit 18ca17f

Browse files
committed
feat: adds task prefix to run target command logs
1 parent 9c750e2 commit 18ca17f

File tree

6 files changed

+107
-8
lines changed

6 files changed

+107
-8
lines changed

parser/parse-task.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,12 +123,13 @@ func ParseTask(ctx context.Context, prf *types.ParsedRunfile, task types.Task) (
123123
}
124124

125125
return &types.ParsedTask{
126+
Name: task.Name,
126127
Shell: task.Shell,
127128
WorkingDir: *task.Dir,
128129
Interactive: task.Interactive,
129130
Env: taskEnv,
130131
Commands: commands,
131132
Watch: watch,
132-
Parallel: task.Parallel,
133+
Parallel: task.Parallel,
133134
}, nil
134135
}

parser/parser-runfile.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,10 @@ func parseRunfile(runfile *types.Runfile) (*types.ParsedRunfile, error) {
1818
Tasks: make(map[string]types.Task),
1919
}
2020

21-
prf.Tasks = runfile.Tasks
21+
for k, task := range runfile.Tasks {
22+
task.Name = k
23+
prf.Tasks[k] = task
24+
}
2225

2326
m, err := parseIncludes(runfile.Includes)
2427
if err != nil {
@@ -27,6 +30,7 @@ func parseRunfile(runfile *types.Runfile) (*types.ParsedRunfile, error) {
2730

2831
for k, iprf := range m {
2932
for taskName, task := range iprf.Tasks {
33+
task.Name = k
3034
task.Metadata.RunfilePath = &iprf.Metadata.RunfilePath
3135
prf.Tasks[fmt.Sprintf("%s:%s", k, taskName)] = task
3236
}

runner/run-task.go

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
// "bytes"
55
"context"
66
"fmt"
7+
"io"
78
"os"
89
"os/exec"
910
"path/filepath"
@@ -53,7 +54,17 @@ func isTTY() bool {
5354
return ((stdout.Mode() & os.ModeCharDevice) == os.ModeCharDevice) && ((stderr.Mode() & os.ModeCharDevice) == os.ModeCharDevice)
5455
}
5556

56-
func createCommands(ctx Context, prf *types.ParsedRunfile, pt *types.ParsedTask, args runTaskArgs) ([]executor.CommandGroup, error) {
57+
type CreateCommandGroupArgs struct {
58+
Runfile *types.ParsedRunfile
59+
Task *types.ParsedTask
60+
61+
Prefix string
62+
63+
Stdout io.Writer
64+
Stderr io.Writer
65+
}
66+
67+
func createCommandGroups(ctx Context, prf *types.ParsedRunfile, pt *types.ParsedTask, stdout *LogWriter, stderr *LogWriter) ([]executor.CommandGroup, error) {
5768
var cmds []executor.CommandGroup
5869

5970
for _, cmd := range pt.Commands {
@@ -70,7 +81,7 @@ func createCommands(ctx Context, prf *types.ParsedRunfile, pt *types.ParsedTask,
7081
return nil, errors.WithErr(err).KV("env-vars", prf.Env)
7182
}
7283

73-
rtCommands, err := createCommands(ctx, prf, rtp, args)
84+
rtCommands, err := createCommandGroups(ctx, prf, rtp, stdout, stderr)
7485
if err != nil {
7586
return nil, errors.WithErr(err).KV("env-vars", prf.Env)
7687
}
@@ -101,8 +112,8 @@ func createCommands(ctx Context, prf *types.ParsedRunfile, pt *types.ParsedTask,
101112
Cmd: *cmd.Command,
102113
WorkingDir: pt.WorkingDir,
103114
interactive: pt.Interactive,
104-
Stdout: os.Stdout,
105-
Stderr: os.Stderr,
115+
Stdout: stdout.WithPrefix(pt.Name),
116+
Stderr: stdout.WithPrefix(pt.Name),
106117
})
107118
})
108119

@@ -296,7 +307,9 @@ func runTask(ctx Context, prf *types.ParsedRunfile, args runTaskArgs) error {
296307
return errors.WithErr(err)
297308
}
298309

299-
execCommands, err := createCommands(ctx, prf, pt, args)
310+
logStdout := &LogWriter{w: os.Stdout}
311+
312+
execCommands, err := createCommandGroups(ctx, prf, pt, logStdout, logStdout)
300313
if err != nil {
301314
return err
302315
}

runner/run-task_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ func TestCreateCommands(t *testing.T) {
2424
}
2525

2626
for _, tt := range tests {
27-
cg, err := createCommands(Context{Context: context.TODO(), Logger: slog.Default()}, &tt.prf, &tt.pt, tt.rta)
27+
cg, err := createCommandGroups(Context{Context: context.TODO(), Logger: slog.Default()}, &tt.prf, &tt.pt, tt.rta)
2828
if err != nil {
2929
t.Error(err)
3030
}

runner/writer.go

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package runner
2+
3+
import (
4+
"bufio"
5+
"errors"
6+
"fmt"
7+
"io"
8+
"sync"
9+
)
10+
11+
type LineWriter struct {
12+
prefix string
13+
w io.Writer
14+
}
15+
16+
// Write implements io.Writer.
17+
func (lw *LineWriter) Write(p []byte) (n int, err error) {
18+
return lw.w.Write(p)
19+
}
20+
21+
type LogWriter struct {
22+
w io.Writer
23+
mu sync.Mutex
24+
wg sync.WaitGroup
25+
}
26+
27+
// Write implements io.Writer.
28+
func (s *LogWriter) Write(p []byte) (n int, err error) {
29+
s.mu.Lock()
30+
defer s.mu.Unlock()
31+
return s.w.Write(p)
32+
}
33+
34+
var _ io.Writer = (*LogWriter)(nil)
35+
36+
func (s *LogWriter) WithPrefix(prefix string) io.Writer {
37+
pr, pw := io.Pipe()
38+
s.wg.Add(1)
39+
go func() {
40+
defer s.wg.Done()
41+
copyStream(prefix, s.w, pr)
42+
}()
43+
return &LineWriter{prefix: prefix, w: pw}
44+
}
45+
46+
func (s *LogWriter) Wait() {
47+
s.wg.Wait()
48+
}
49+
50+
func copyBytes(prefix string, src []byte) []byte {
51+
dest := make([]byte, 0, len(src))
52+
for i := range src {
53+
if i == 0 || src[i-1] == '\n' {
54+
dest = append(dest, []byte(fmt.Sprintf("[%s] ", prefix))...)
55+
}
56+
dest = append(dest, src[i])
57+
}
58+
return dest
59+
}
60+
61+
func copyStream(prefix string, dest io.Writer, src io.Reader) {
62+
r := bufio.NewReader(src)
63+
for {
64+
b, err := r.ReadBytes('\n')
65+
if err != nil {
66+
// logger.Info("stdout", "msg", string(msg[:n]), "err", err)
67+
fmt.Println("ERR: ", err)
68+
if errors.Is(err, io.EOF) {
69+
dest.Write([]byte(fmt.Sprintf("[%s] ", prefix)))
70+
dest.Write(b)
71+
return
72+
}
73+
}
74+
75+
dest.Write([]byte(fmt.Sprintf("[%s] ", prefix)))
76+
dest.Write(b)
77+
}
78+
}

types/parsed-types.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ type ParsedRunfile struct {
1010
}
1111

1212
type ParsedTask struct {
13+
// Name should be resolved from key itself
14+
Name string `json:"-"`
15+
1316
Shell []string `json:"shell"`
1417
WorkingDir string `json:"workingDir"`
1518
Watch *TaskWatch `json:"watch,omitempty"`

0 commit comments

Comments
 (0)