diff --git a/pkg/model/workflow.go b/pkg/model/workflow.go index 273789b..7ab6139 100644 --- a/pkg/model/workflow.go +++ b/pkg/model/workflow.go @@ -13,10 +13,11 @@ import ( // Workflow is the structure of the files in .github/workflows type Workflow struct { - Name string `yaml:"name"` - RawOn yaml.Node `yaml:"on"` - Env map[string]string `yaml:"env"` - Jobs map[string]*Job `yaml:"jobs"` + Name string `yaml:"name"` + RawOn yaml.Node `yaml:"on"` + Env map[string]string `yaml:"env"` + Jobs map[string]*Job `yaml:"jobs"` + Defaults Defaults `yaml:"defaults"` } // On events for the workflow @@ -64,6 +65,7 @@ type Job struct { Services map[string]*ContainerSpec `yaml:"services"` Strategy *Strategy `yaml:"strategy"` RawContainer yaml.Node `yaml:"container"` + Defaults Defaults `yaml:"defaults"` } // Strategy for the job @@ -73,6 +75,17 @@ type Strategy struct { Matrix map[string][]interface{} `yaml:"matrix"` } +// Default settings that will apply to all steps in the job or workflow +type Defaults struct { + Run RunDefaults `yaml:"run"` +} + +// Defaults for all run steps in the job or workflow +type RunDefaults struct { + Shell string `yaml:"shell"` + WorkingDirectory string `yaml:"working-directory"` +} + // Container details for the job func (j *Job) Container() *ContainerSpec { var val *ContainerSpec diff --git a/pkg/runner/runner_test.go b/pkg/runner/runner_test.go index 441a5f8..c31fe1c 100644 --- a/pkg/runner/runner_test.go +++ b/pkg/runner/runner_test.go @@ -55,6 +55,7 @@ func TestRunEvent(t *testing.T) { {"commands", "push", ""}, {"workdir", "push", ""}, {"issue-228", "push", ""}, // TODO [igni]: Remove this once everything passes + {"defaults-run", "push", ""}, } log.SetLevel(log.DebugLevel) diff --git a/pkg/runner/step_context.go b/pkg/runner/step_context.go index 6e6197a..5cb8952 100644 --- a/pkg/runner/step_context.go +++ b/pkg/runner/step_context.go @@ -111,6 +111,12 @@ func (sc *StepContext) setupShellCommand() common.Executor { return err } + if step.WorkingDirectory == "" { + step.WorkingDirectory = rc.Run.Job().Defaults.Run.WorkingDirectory + } + if step.WorkingDirectory == "" { + step.WorkingDirectory = rc.Run.Workflow.Defaults.Run.WorkingDirectory + } if step.WorkingDirectory != "" { _, err = script.WriteString(fmt.Sprintf("cd %s\n", step.WorkingDirectory)) if err != nil { @@ -126,6 +132,13 @@ func (sc *StepContext) setupShellCommand() common.Executor { scriptName := fmt.Sprintf("workflow/%s", step.ID) log.Debugf("Wrote command '%s' to '%s'", run, scriptName) containerPath := fmt.Sprintf("/github/%s", scriptName) + + if step.Shell == "" { + step.Shell = rc.Run.Job().Defaults.Run.Shell + } + if step.Shell == "" { + step.Shell = rc.Run.Workflow.Defaults.Run.Shell + } sc.Cmd = strings.Fields(strings.Replace(step.ShellCommand(), "{0}", containerPath, 1)) return rc.JobContainer.Copy("/github/", &container.FileEntry{ Name: scriptName, diff --git a/pkg/runner/testdata/defaults-run/main.yaml b/pkg/runner/testdata/defaults-run/main.yaml new file mode 100644 index 0000000..0b1fa0a --- /dev/null +++ b/pkg/runner/testdata/defaults-run/main.yaml @@ -0,0 +1,29 @@ +name: defaults-run +on: + - push +defaults: + run: + shell: sh +jobs: + without-defaults: + runs-on: ubuntu-latest + steps: + - run: echo $SHELL | grep -v bash || exit 1 + with-defaults: + runs-on: ubuntu-latest + defaults: + run: + shell: bash + working-directory: /tmp + steps: + - run: | + echo $SHELL | grep bash || exit 1 + [ $(pwd) = /tmp ] || exit 2 + override-in-step: + runs-on: ubuntu-latest + defaults: + run: + shell: bash + steps: + - run: echo $SHELL | grep -v bash || exit 1 + shell: sh