Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 9 additions & 10 deletions executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import (
"github.com/samsarahq/go/oops"
"go.uber.org/multierr"
"golang.org/x/sync/errgroup"
"mvdan.cc/sh/interp"
)

// Executor constructs and executes a DAG for the tasks specified and
Expand Down Expand Up @@ -301,19 +300,19 @@ func (e *Executor) Run(ctx context.Context, taskNames []string, runtime *Runtime
// Commands run in a consistent environment (configurable on a taskrunner level).
// Commands run in taskrunner's working directory.
func (e *Executor) ShellRun(ctx context.Context, command string, opts ...shell.RunOption) error {
options := []shell.RunOption{
func(r *interp.Runner) {
logger := LoggerFromContext(ctx)
if logger == nil {
return
}
var options []shell.RunOption

r.Stdout = logger.Stdout
r.Stderr = logger.Stderr
},
// Default: forward stdout/stderr to executor's logger if available
if logger := LoggerFromContext(ctx); logger != nil {
options = append(options, shell.Stdout(logger.Stdout), shell.Stderr(logger.Stderr))
}

// Executor-level default options (if any)
options = append(options, e.shellRunOptions...)

// Call-site options
options = append(options, opts...)

return shell.Run(ctx, command, options...)
}

Expand Down
13 changes: 7 additions & 6 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
module github.com/pylon-labs/taskrunner

go 1.21
go 1.23

toolchain go1.23.10

require (
github.com/fatih/color v1.16.0
Expand All @@ -9,25 +11,24 @@ require (
github.com/samsarahq/go v0.0.0-20230622164605-46203ca3a6d8
github.com/stretchr/testify v1.8.4
go.uber.org/multierr v1.11.0
golang.org/x/sync v0.6.0
mvdan.cc/sh v2.5.1-0.20180917103936-65d8e2a4b156+incompatible
golang.org/x/sync v0.8.0
mvdan.cc/sh/v3 v3.11.0
)

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/gdamore/encoding v0.0.0-20151215212835-b23993cbb635 // indirect
github.com/gdamore/tcell v1.1.1-0.20181029231221-017915a4d77d // indirect
github.com/jtolds/gls v4.20.0+incompatible // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/kylelemons/godebug v1.1.0 // indirect
github.com/lucasb-eyer/go-colorful v0.0.0-20181028223441-12d3b2882a08 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.4-0.20181117163326-c88d7e5f2e24 // indirect
github.com/mitchellh/go-wordwrap v1.0.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 // indirect
golang.org/x/sys v0.14.0 // indirect
golang.org/x/sys v0.30.0 // indirect
golang.org/x/term v0.29.0 // indirect
golang.org/x/text v0.3.1-0.20181030141323-6f44c5a2ea40 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
30 changes: 16 additions & 14 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s=
github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
Expand All @@ -8,8 +9,11 @@ github.com/gdamore/encoding v0.0.0-20151215212835-b23993cbb635/go.mod h1:yrQYJKK
github.com/gdamore/tcell v1.1.0/go.mod h1:tqyG50u7+Ctv1w5VX67kLzKcj9YXR/JSBZQq/+mLl1A=
github.com/gdamore/tcell v1.1.1-0.20181029231221-017915a4d77d h1:nttfWmFD1ftiDfSTqy7j2709495bojgulJc7KyepcZI=
github.com/gdamore/tcell v1.1.1-0.20181029231221-017915a4d77d/go.mod h1:tqyG50u7+Ctv1w5VX67kLzKcj9YXR/JSBZQq/+mLl1A=
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI=
github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e h1:JKmoR8x90Iww1ks85zJ1lfDGgIiMDuIptTOhJq+zKyg=
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
Expand Down Expand Up @@ -38,11 +42,10 @@ github.com/mattn/go-zglob v0.0.1 h1:xsEx/XUoVlI6yXjqBK062zYhRTZltCNmYPx6v+8DNaY=
github.com/mattn/go-zglob v0.0.1/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo=
github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4=
github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
github.com/samsarahq/go v0.0.0-20230622164605-46203ca3a6d8 h1:3k6siUM/qYdvMe7oMO/VOfD3Hv4oMDSd7YwdZn16o4s=
github.com/samsarahq/go v0.0.0-20230622164605-46203ca3a6d8/go.mod h1:3sbyY5uD6qrfO+gLTor5Fny8qozzWm1m8Kk6KY04M0o=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
Expand All @@ -53,15 +56,14 @@ github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcU
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU=
golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20181030141323-6f44c5a2ea40 h1:BtUFROTRzj9Y8jXjyUJ4NogzXn+sSbruLbjIbdkd7VE=
golang.org/x/text v0.3.1-0.20181030141323-6f44c5a2ea40/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
Expand All @@ -72,5 +74,5 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
mvdan.cc/sh v2.5.1-0.20180917103936-65d8e2a4b156+incompatible h1:YLmgyUXMWLcF6Bk3uCn6V2APFmu0tUnuaiJ14mmkSHs=
mvdan.cc/sh v2.5.1-0.20180917103936-65d8e2a4b156+incompatible/go.mod h1:IeeQbZq+x2SUGBensq/jge5lLQbS3XT2ktyp3wrt4x8=
mvdan.cc/sh/v3 v3.11.0 h1:q5h+XMDRfUGUedCqFFsjoFjrhwf2Mvtt1rkMvVz0blw=
mvdan.cc/sh/v3 v3.11.0/go.mod h1:LRM+1NjoYCzuq/WZ6y44x14YNAI0NK7FLPeQSaFagGg=
15 changes: 2 additions & 13 deletions goextensions/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import (
"github.com/pylon-labs/taskrunner"
"github.com/pylon-labs/taskrunner/clireporter"
"github.com/pylon-labs/taskrunner/shell"
"mvdan.cc/sh/interp"
)

var (
Expand Down Expand Up @@ -116,13 +115,7 @@ func (b *GoBuilder) build() {
}

fmt.Fprintf(stdout, "building packages: %s", pkgList)
b.err = shell.Run(b.ctx, fmt.Sprintf("go install -v %s", pkgList), func(r *interp.Runner) {
r.Stdout = stdout
r.Stderr = stderr
if b.ModuleRoot != "" {
r.Dir = b.ModuleRoot
}
})
b.err = shell.Run(b.ctx, fmt.Sprintf("go install -v %s", pkgList), shell.Stdout(stdout), shell.Stderr(stderr), shell.Dir(b.ModuleRoot))
fmt.Fprintln(stdout, "done building packages")

close(b.doneCh)
Expand Down Expand Up @@ -168,11 +161,7 @@ func newBuildBinder(pkg string) *buildBinder {

func (b *buildBinder) saveDependencies(ctx context.Context, root string, shellRun shell.ShellRun) error {
var buffer bytes.Buffer
if err := shellRun(ctx, fmt.Sprintf("go list -f '{{ .Deps }}' %s", b.pkg), shell.Stdout(&buffer), func(r *interp.Runner) {
if root != "" {
r.Dir = root
}
}); err != nil {
if err := shellRun(ctx, fmt.Sprintf("go list -f '{{ .Deps }}' %s", b.pkg), shell.Stdout(&buffer), shell.Dir(root)); err != nil {
return err
}

Expand Down
87 changes: 70 additions & 17 deletions shell/shell.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,61 +4,114 @@ import (
"context"
"fmt"
"io"
"os"
"strings"

"mvdan.cc/sh/interp"
"mvdan.cc/sh/syntax"
"mvdan.cc/sh/v3/expand"
"mvdan.cc/sh/v3/interp"
"mvdan.cc/sh/v3/syntax"
)

type RunOption func(*interp.Runner)
// runConfig collects options prior to constructing the sh Runner.
type runConfig struct {
stdin io.Reader
stdout io.Writer
stderr io.Writer
env map[string]string
dir string
}

// RunOption configures execution of a shell command.
type RunOption func(*runConfig)

type ShellRun func(ctx context.Context, command string, options ...RunOption) error

// Stdout sets the output location for the stdout of a command.
func Stdout(writer io.Writer) RunOption {
return func(r *interp.Runner) {
r.Stdout = writer
return func(c *runConfig) {
c.stdout = writer
}
}

// Stderr sets the output location for the stderr of a command.
func Stderr(writer io.Writer) RunOption {
return func(r *interp.Runner) {
r.Stderr = writer
return func(c *runConfig) {
c.stderr = writer
}
}

// Stdin pipes in the contents provided by the reader to the command.
func Stdin(reader io.Reader) RunOption {
return func(r *interp.Runner) {
r.Stdin = reader
return func(c *runConfig) {
c.stdin = reader
}
}

// Env sets the environment variables for the command.
func Env(vars map[string]string) RunOption {
return func(r *interp.Runner) {
return func(c *runConfig) {
if c.env == nil {
c.env = make(map[string]string)
}
for k, v := range vars {
r.Env.Set(k, v)
c.env[k] = v
}
}
}

// Run executes a shell command.
// Dir sets the working directory for the command.
func Dir(path string) RunOption {
return func(c *runConfig) {
c.dir = path
}
}

// Run executes a shell command using mvdan.cc/sh's interpreter.
func Run(ctx context.Context, command string, opts ...RunOption) error {
// Parse the program
p, err := syntax.NewParser().Parse(strings.NewReader(command), "")
if err != nil {
return err
}

r, err := interp.New()
if err != nil {
panic(fmt.Errorf("failed to set up interpreter: %s", err.Error()))
// Build configuration from provided options
cfg := &runConfig{}
for _, opt := range opts {
opt(cfg)
}

for _, opt := range opts {
opt(r)
// Default std streams
if cfg.stdin == nil {
cfg.stdin = os.Stdin
}
if cfg.stdout == nil {
cfg.stdout = os.Stdout
}
if cfg.stderr == nil {
cfg.stderr = os.Stderr
}

runnerOpts := []interp.RunnerOption{
interp.StdIO(cfg.stdin, cfg.stdout, cfg.stderr),
}

// Build environment pairs
envPairs := os.Environ()
for k, v := range cfg.env {
envPairs = append(envPairs, fmt.Sprintf("%s=%s", k, v))
}
runnerOpts = append(runnerOpts, interp.Env(expand.ListEnviron(envPairs...)))

if cfg.dir != "" {
runnerOpts = append(runnerOpts, interp.Dir(cfg.dir))
}

// Construct the runner
r, err := interp.New(runnerOpts...)
if err != nil {
return fmt.Errorf("failed to set up interpreter: %w", err)
}

// Execute the parsed program
return r.Run(ctx, p)
}
3 changes: 0 additions & 3 deletions vendor/golang.org/x/crypto/AUTHORS

This file was deleted.

3 changes: 0 additions & 3 deletions vendor/golang.org/x/crypto/CONTRIBUTORS

This file was deleted.

10 changes: 0 additions & 10 deletions vendor/golang.org/x/crypto/ssh/terminal/util_linux.go

This file was deleted.

58 changes: 0 additions & 58 deletions vendor/golang.org/x/crypto/ssh/terminal/util_plan9.go

This file was deleted.

Loading