diff --git a/bundle/config/artifact.go b/bundle/config/artifact.go index 2a1a92a150..279a8f3b7d 100644 --- a/bundle/config/artifact.go +++ b/bundle/config/artifact.go @@ -42,6 +42,8 @@ type Artifact struct { Files []ArtifactFile `json:"files,omitempty"` BuildCommand string `json:"build,omitempty"` + Executable exec.ExecutableType `json:"executable,omitempty"` + paths.Paths } @@ -50,7 +52,14 @@ func (a *Artifact) Build(ctx context.Context) ([]byte, error) { return nil, fmt.Errorf("no build property defined") } - e, err := exec.NewCommandExecutor(a.Path) + var e *exec.Executor + var err error + if a.Executable != "" { + e, err = exec.NewCommandExecutorWithExecutable(a.Path, a.Executable) + } else { + e, err = exec.NewCommandExecutor(a.Path) + a.Executable = e.ShellType() + } if err != nil { return nil, err } diff --git a/libs/exec/exec.go b/libs/exec/exec.go index a85e19ea16..9767c199a2 100644 --- a/libs/exec/exec.go +++ b/libs/exec/exec.go @@ -2,11 +2,24 @@ package exec import ( "context" + "fmt" "io" "os" osexec "os/exec" ) +type ExecutableType string + +const BashExecutable ExecutableType = `bash` +const ShExecutable ExecutableType = `sh` +const CmdExecutable ExecutableType = `cmd` + +var finders map[ExecutableType](func() (shell, error)) = map[ExecutableType](func() (shell, error)){ + BashExecutable: newBashShell, + ShExecutable: newShShell, + CmdExecutable: newCmdShell, +} + type Command interface { // Wait for command to terminate. It must have been previously started. Wait() error @@ -61,6 +74,22 @@ func NewCommandExecutor(dir string) (*Executor, error) { }, nil } +func NewCommandExecutorWithExecutable(dir string, execType ExecutableType) (*Executor, error) { + f, ok := finders[execType] + if !ok { + return nil, fmt.Errorf("%s is not supported as an artifact executable, options are: %s, %s or %s", execType, BashExecutable, ShExecutable, CmdExecutable) + } + shell, err := f() + if err != nil { + return nil, err + } + + return &Executor{ + shell: shell, + dir: dir, + }, nil +} + func (e *Executor) StartCommand(ctx context.Context, command string) (Command, error) { ec, err := e.shell.prepare(command) if err != nil { @@ -99,3 +128,7 @@ func (e *Executor) Exec(ctx context.Context, command string) ([]byte, error) { return res, cmd.Wait() } + +func (e *Executor) ShellType() ExecutableType { + return e.shell.getType() +} diff --git a/libs/exec/shell.go b/libs/exec/shell.go index 8589aed763..f5d1768967 100644 --- a/libs/exec/shell.go +++ b/libs/exec/shell.go @@ -8,6 +8,7 @@ import ( type shell interface { prepare(string) (*execContext, error) + getType() ExecutableType } type execContext struct { diff --git a/libs/exec/shell_bash.go b/libs/exec/shell_bash.go index c8af31b085..bb8c6c514f 100644 --- a/libs/exec/shell_bash.go +++ b/libs/exec/shell_bash.go @@ -3,6 +3,7 @@ package exec import ( "errors" osexec "os/exec" + "strings" ) type bashShell struct { @@ -33,5 +34,14 @@ func newBashShell() (shell, error) { return nil, nil } + // Skipping WSL bash if found one + if strings.Contains(out, `\Windows\System32\bash.exe`) || strings.Contains(out, `\Microsoft\WindowsApps\bash.exe`) { + return nil, nil + } + return &bashShell{executable: out}, nil } + +func (s bashShell) getType() ExecutableType { + return BashExecutable +} diff --git a/libs/exec/shell_cmd.go b/libs/exec/shell_cmd.go index b207c513d7..164d09739f 100644 --- a/libs/exec/shell_cmd.go +++ b/libs/exec/shell_cmd.go @@ -36,3 +36,7 @@ func newCmdShell() (shell, error) { return &cmdShell{executable: out}, nil } + +func (s cmdShell) getType() ExecutableType { + return CmdExecutable +} diff --git a/libs/exec/shell_sh.go b/libs/exec/shell_sh.go index 1181c5e33a..ca42ecfa46 100644 --- a/libs/exec/shell_sh.go +++ b/libs/exec/shell_sh.go @@ -35,3 +35,7 @@ func newShShell() (shell, error) { return &shShell{executable: out}, nil } + +func (s shShell) getType() ExecutableType { + return ShExecutable +}