diff --git a/task.go b/task.go index 54cda92762..ab33a95077 100644 --- a/task.go +++ b/task.go @@ -156,6 +156,14 @@ func (e *Executor) RunTask(ctx context.Context, call *Call) error { } } + // Attempt to create the task dir before compiling the task so that ShVars can run/access + // the configured task dir. If the directory can't be created (e.g. contains unresolved + // template values), continue as if nothing happened (the directory is created again later). + if t.Dir != "" && !strings.Contains(t.Dir, "{") { + if err := e.mkdir(t); err != nil { + e.Logger.Warnf("task: cannot make directory %q: %v\n", t.Dir, err) + } + } t, err = e.CompiledTask(call) if err != nil { return err @@ -205,6 +213,10 @@ func (e *Executor) RunTask(ctx context.Context, call *Call) error { defer release() if err = e.startExecution(ctx, t, func(ctx context.Context) error { + if err := e.mkdir(t); err != nil { + e.Logger.Errf(logger.Red, "task: cannot make directory %q: %v\n", t.Dir, err) + } + e.Logger.VerboseErrf(logger.Magenta, "task: %q started\n", call.Task) if err := e.runDeps(ctx, t); err != nil { return err @@ -260,10 +272,6 @@ func (e *Executor) RunTask(ctx context.Context, call *Call) error { } } - if err := e.mkdir(t); err != nil { - e.Logger.Errf(logger.Red, "task: cannot make directory %q: %v\n", t.Dir, err) - } - var deferredExitCode uint8 for i := range t.Cmds { diff --git a/task_test.go b/task_test.go index 80915c2c47..bec7a88723 100644 --- a/task_test.go +++ b/task_test.go @@ -1752,6 +1752,37 @@ func TestDynamicVariablesShouldRunOnTheTaskDir(t *testing.T) { }) } +func TestDynamicVariablesRunOnParentDir(t *testing.T) { + t.Parallel() + + const expected = "fubar" + const dir = "testdata/dir/dynamic_var_on_parent_dir/" + const toBeCreated = dir + "somefolder" + const target = "default" + var out bytes.Buffer + e := task.NewExecutor( + task.WithDir(dir), + task.WithStdout(&out), + task.WithStderr(&out), + task.WithSilent(true), + ) + + // Ensure that the directory to be created doesn't actually exist. + _ = os.RemoveAll(toBeCreated) + if _, err := os.Stat(toBeCreated); err == nil { + t.Errorf("Directory should not exist: %v", err) + } + require.NoError(t, e.Setup()) + require.NoError(t, e.Run(t.Context(), &task.Call{Task: target})) + + normalized := normalizePathSeparators(out.String()) + got := strings.TrimSuffix(filepath.Base(normalized), "\n") + assert.Equal(t, expected, got, "Mismatch message from parent dir") + + // Clean-up after ourselves only if no error. + _ = os.RemoveAll(toBeCreated) +} + func TestDisplaysErrorOnVersion1Schema(t *testing.T) { t.Parallel() diff --git a/testdata/dir/dynamic_var_on_parent_dir/Taskfile.yml b/testdata/dir/dynamic_var_on_parent_dir/Taskfile.yml new file mode 100644 index 0000000000..756511ed62 --- /dev/null +++ b/testdata/dir/dynamic_var_on_parent_dir/Taskfile.yml @@ -0,0 +1,10 @@ +version: '3' + +tasks: + default: + dir: somefolder + cmds: + - echo {{.MSG}} + vars: + MSG: + sh: cat ../foo.txt diff --git a/testdata/dir/dynamic_var_on_parent_dir/foo.txt b/testdata/dir/dynamic_var_on_parent_dir/foo.txt new file mode 100644 index 0000000000..570de9c7c2 --- /dev/null +++ b/testdata/dir/dynamic_var_on_parent_dir/foo.txt @@ -0,0 +1 @@ +fubar \ No newline at end of file