diff --git a/compiler.go b/compiler.go index 2c2e56f632..ace04bb351 100644 --- a/compiler.go +++ b/compiler.go @@ -90,20 +90,8 @@ func (c *Compiler) getVariables(t *ast.Task, call *Call, evaluateShVars bool) (* return nil } } - rangeFunc := getRangeFunc(c.Dir) - var taskRangeFunc func(k string, v ast.Var) error - if t != nil { - // NOTE(@andreynering): We're manually joining these paths here because - // this is the raw task, not the compiled one. - cache := &templater.Cache{Vars: result} - dir := templater.Replace(t.Dir, cache) - if err := cache.Err(); err != nil { - return nil, err - } - dir = filepathext.SmartJoin(c.Dir, dir) - taskRangeFunc = getRangeFunc(dir) - } + rangeFunc := getRangeFunc(c.Dir) for k, v := range c.TaskfileEnv.All() { if err := rangeFunc(k, v); err != nil { @@ -115,20 +103,39 @@ func (c *Compiler) getVariables(t *ast.Task, call *Call, evaluateShVars bool) (* return nil, err } } - if t != nil { - for k, v := range t.IncludeVars.All() { - if err := rangeFunc(k, v); err != nil { - return nil, err - } + + if t == nil { + return result, nil + } + + for k, v := range t.IncludeVars.All() { + if err := rangeFunc(k, v); err != nil { + return nil, err } - for k, v := range t.IncludedTaskfileVars.All() { - if err := taskRangeFunc(k, v); err != nil { - return nil, err - } + } + + // The task dir may reference variables, so it can only be resolved once the + // Taskfile variables above have been added to the result. Resolving it any + // earlier makes those references expand to an empty string, which silently + // runs the dynamic variables below in the Taskfile dir instead of the task + // one. + // NOTE(@andreynering): We're manually joining these paths here because + // this is the raw task, not the compiled one. + cache := &templater.Cache{Vars: result} + dir := templater.Replace(t.Dir, cache) + if err := cache.Err(); err != nil { + return nil, err + } + dir = filepathext.SmartJoin(c.Dir, dir) + taskRangeFunc := getRangeFunc(dir) + + for k, v := range t.IncludedTaskfileVars.All() { + if err := taskRangeFunc(k, v); err != nil { + return nil, err } } - if t == nil || call == nil { + if call == nil { return result, nil } diff --git a/task_test.go b/task_test.go index b56930e77e..75326b3118 100644 --- a/task_test.go +++ b/task_test.go @@ -1936,6 +1936,23 @@ func TestDynamicVariablesShouldRunOnTheTaskDir(t *testing.T) { }) } +func TestDynamicVariablesShouldRunOnTheTemplatedTaskDir(t *testing.T) { + t.Parallel() + + tt := fileContentTest{ + Dir: "testdata/dir/templated_dir", + Target: "default", + TrimSpace: false, + Files: map[string]string{ + "subdirectory/from_templated_dir.txt": "subdirectory\n", + }, + } + t.Run("", func(t *testing.T) { + t.Parallel() + tt.Run(t) + }) +} + func TestDisplaysErrorOnVersion1Schema(t *testing.T) { t.Parallel() diff --git a/testdata/dir/templated_dir/Taskfile.yml b/testdata/dir/templated_dir/Taskfile.yml new file mode 100644 index 0000000000..d49c8a62d2 --- /dev/null +++ b/testdata/dir/templated_dir/Taskfile.yml @@ -0,0 +1,14 @@ +version: '3' + +vars: + DIRECTORY: subdirectory + +tasks: + default: + cmds: + - echo '{{.TASK_DIR}}' > from_templated_dir.txt + dir: '{{.DIRECTORY}}' + vars: + TASK_DIR: + sh: basename "$(pwd)" + silent: true diff --git a/testdata/dir/templated_dir/subdirectory/.gitignore b/testdata/dir/templated_dir/subdirectory/.gitignore new file mode 100644 index 0000000000..2211df63dd --- /dev/null +++ b/testdata/dir/templated_dir/subdirectory/.gitignore @@ -0,0 +1 @@ +*.txt