diff --git a/pkg/model/workflow.go b/pkg/model/workflow.go index 410bb806..cc519b79 100644 --- a/pkg/model/workflow.go +++ b/pkg/model/workflow.go @@ -257,11 +257,12 @@ func (s *Step) GetEnv() map[string]string { func (s *Step) ShellCommand() string { shellCommand := "" + //Reference: https://github.com/actions/runner/blob/8109c962f09d9acc473d92c595ff43afceddb347/src/Runner.Worker/Handlers/ScriptHandlerHelpers.cs#L9-L17 switch s.Shell { case "", "bash": - shellCommand = "bash --login --norc -e {0}" + shellCommand = "bash --login --noprofile --norc -e -o pipefail {0}" case "pwsh": - shellCommand = "pwsh -login -command \"& '{0}'\"" + shellCommand = "pwsh -login -command . '{0}'" case "python": shellCommand = "python {0}" case "sh": @@ -269,7 +270,7 @@ func (s *Step) ShellCommand() string { case "cmd": shellCommand = "%ComSpec% /D /E:ON /V:OFF /S /C \"CALL \"{0}\"\"" case "powershell": - shellCommand = "powershell -command \"& '{0}'\"" + shellCommand = "powershell -command . '{0}'" default: shellCommand = s.Shell } diff --git a/pkg/runner/runner_test.go b/pkg/runner/runner_test.go index 5cfb34c9..3175de7b 100644 --- a/pkg/runner/runner_test.go +++ b/pkg/runner/runner_test.go @@ -79,6 +79,7 @@ func TestRunEvent(t *testing.T) { "ubuntu-latest": "node:12.20.1-buster-slim", } tables := []TestJobFileInfo{ + // {"testdata", "powershell", "push", "", platforms}, // Powershell is not available on default act test runner (yet) but preserving here for posterity {"testdata", "basic", "push", "", platforms, "linux/amd64"}, {"testdata", "fail", "push", "exit with `FAILURE`: 1", platforms, "linux/amd64"}, {"testdata", "runs-on", "push", "", platforms, "linux/amd64"}, diff --git a/pkg/runner/step_context.go b/pkg/runner/step_context.go index 763e5086..4855cda2 100644 --- a/pkg/runner/step_context.go +++ b/pkg/runner/step_context.go @@ -159,6 +159,29 @@ func (sc *StepContext) setupShellCommand() common.Executor { return err } scriptName := fmt.Sprintf("workflow/%s", step.ID) + + //Reference: https://github.com/actions/runner/blob/8109c962f09d9acc473d92c595ff43afceddb347/src/Runner.Worker/Handlers/ScriptHandlerHelpers.cs#L47-L64 + //Reference: https://github.com/actions/runner/blob/8109c962f09d9acc473d92c595ff43afceddb347/src/Runner.Worker/Handlers/ScriptHandlerHelpers.cs#L19-L27 + runPrepend := "" + runAppend := "" + scriptExt := "" + switch step.Shell { + case "bash", "sh": + scriptExt = ".sh" + case "pwsh", "powershell": + scriptExt = ".ps1" + runPrepend = "$ErrorActionPreference = 'stop'" + runAppend = "if ((Test-Path -LiteralPath variable:/LASTEXITCODE)) { exit $LASTEXITCODE }" + case "cmd": + scriptExt = ".cmd" + runPrepend = "@echo off" + case "python": + scriptExt = ".py" + } + + scriptName += scriptExt + run = runPrepend + "\n" + run + "\n" + runAppend + log.Debugf("Wrote command '%s' to '%s'", run, scriptName) containerPath := fmt.Sprintf("%s/%s", filepath.Dir(rc.Config.Workdir), scriptName) @@ -168,7 +191,14 @@ func (sc *StepContext) setupShellCommand() common.Executor { if step.Shell == "" { step.Shell = rc.Run.Workflow.Defaults.Run.Shell } - sc.Cmd = strings.Fields(strings.Replace(step.ShellCommand(), "{0}", containerPath, 1)) + scCmd := step.ShellCommand() + scResolvedCmd := strings.Replace(scCmd, "{0}", containerPath, 1) + if step.Shell == "pwsh" || step.Shell == "powershell" { + sc.Cmd = strings.SplitN(scResolvedCmd, " ", 3) + } else { + sc.Cmd = strings.Fields(scResolvedCmd) + } + return rc.JobContainer.Copy(fmt.Sprintf("%s/", filepath.Dir(rc.Config.Workdir)), &container.FileEntry{ Name: scriptName, Mode: 0755, diff --git a/pkg/runner/testdata/powershell/push.yml b/pkg/runner/testdata/powershell/push.yml new file mode 100644 index 00000000..c514d350 --- /dev/null +++ b/pkg/runner/testdata/powershell/push.yml @@ -0,0 +1,12 @@ +name: powershell +on: push + +env: + TEST: value +jobs: + check: + runs-on: ubuntu-latest + steps: + - shell: pwsh + run: | + echo "hello test" \ No newline at end of file