Skip to content

Commit

Permalink
Pipeline: Allow to capture output of executed program in 'exec' op.
Browse files Browse the repository at this point in the history
Signed-off-by: Richard Kosegi <richard.kosegi@gmail.com>
  • Loading branch information
rkosegi committed Aug 8, 2024
1 parent 6bc8fd7 commit 8bd64e8
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 0 deletions.
37 changes: 37 additions & 0 deletions pipeline/exec_op.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ package pipeline
import (
"errors"
"fmt"
"io"
"os"
osx "os/exec"
"slices"
)
Expand All @@ -30,20 +32,55 @@ type ExecOp struct {
Args *[]string `yaml:"args,omitempty"`
// List of exit codes that are assumed to be valid
ValidExitCodes *[]int `yaml:"validExitCodes,omitempty"`
// Path to file where program's stdout will be written upon completion.
// Any error occurred during write will result in panic.
Stdout *string
// Path to file where program's stderr will be written upon completion
// Any error occurred during write will result in panic.
Stderr *string
}

func (e *ExecOp) String() string {
return fmt.Sprintf("Exec[Program=%s,Args=%d]", e.Program, safeStrListSize(e.Args))
}

func (e *ExecOp) Do(_ ActionContext) error {
var closables []io.Closer
if e.ValidExitCodes == nil {
e.ValidExitCodes = &[]int{}
}
if e.Args == nil {
e.Args = &[]string{}
}
cmd := osx.Command(e.Program, *e.Args...)
defer func() {
for _, closer := range closables {
_ = closer.Close()
}
}()
type streamTgt struct {
output *string
target *io.Writer
}
for _, stream := range []streamTgt{
{
output: e.Stdout,
target: &cmd.Stdout,
},
{
output: e.Stderr,
target: &cmd.Stderr,
},
} {
if stream.output != nil {
out, err := os.OpenFile(*stream.output, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
if err != nil {
return err
}
*stream.target = out
closables = append(closables, out)
}
}
err := cmd.Run()
var exitErr *osx.ExitError
if errors.As(err, &exitErr) {
Expand Down
25 changes: 25 additions & 0 deletions pipeline/exec_op_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package pipeline
import (
"github.com/rkosegi/yaml-toolkit/dom"
"github.com/stretchr/testify/assert"
"os"
"testing"
)

Expand All @@ -31,6 +32,30 @@ func TestExecOpDo(t *testing.T) {
var (
eo *ExecOp
)
fout, err := os.CreateTemp("", "yt.*.txt")
ferr, err := os.CreateTemp("", "yt.*.txt")
defer func() {
t.Logf("removing %s", fout.Name())
_ = os.Remove(fout.Name())
t.Logf("removing %s", ferr.Name())
_ = os.Remove(ferr.Name())
}()
assert.NoError(t, err)
eo = &ExecOp{
Program: "sh",
Args: &[]string{"-c", "echo abcd"},
Stdout: strPointer(fout.Name()),
Stderr: strPointer(ferr.Name()),
}
assert.NoError(t, eo.Do(mockEmptyActCtx()))

eo = &ExecOp{
Program: "sh",
Args: &[]string{"-c", "echo abcd"},
Stdout: strPointer("/"),
}
assert.Error(t, eo.Do(mockEmptyActCtx()))

eo = &ExecOp{
Program: "sh",
Args: &[]string{"-c", "exit 3"},
Expand Down

0 comments on commit 8bd64e8

Please sign in to comment.