Allow specifying executable in artifact section and skip bash from WSL (#1169)

## Changes
Allow specifying executable in artifact section

```
artifacts:
  test:
    type: whl
    executable: bash
    ...
```

We also skip bash found on Windows if it's from WSL because it won't be
correctly executed, see the issue above

Fixes #1159
This commit is contained in:
Andrew Nester 2024-02-01 14:10:04 +00:00 committed by GitHub
parent 6beda4405e
commit 0b3eeb8e54
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 62 additions and 1 deletions

View File

@ -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
}

View File

@ -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()
}

View File

@ -8,6 +8,7 @@ import (
type shell interface {
prepare(string) (*execContext, error)
getType() ExecutableType
}
type execContext struct {

View File

@ -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
}

View File

@ -36,3 +36,7 @@ func newCmdShell() (shell, error) {
return &cmdShell{executable: out}, nil
}
func (s cmdShell) getType() ExecutableType {
return CmdExecutable
}

View File

@ -35,3 +35,7 @@ func newShShell() (shell, error) {
return &shShell{executable: out}, nil
}
func (s shShell) getType() ExecutableType {
return ShExecutable
}