Repository: go-task/task
Pull request #677 (2022-02-23 22:56:28)

Add vars to included taskfiles
When including task files allow for specifying variables that should be global variables in the included files.

I was looking for a way to do this so that I can have a template Taskfile repo and include those in my projects.
The included file will have a set of tasks that are our standard tasks for the type of project (terraform, docker image, etc).  These tasks will all need to know which environment they are in.  Included taskfiles already account for directory, but there isn't a way to pass variables to the included taskfile.

The taskfile in the root of the project repo will have this for the includes:
```yaml
includes:
  <account-profile>-tf:
    taskfile: Taskfiles/Taskfile-tf.yml
    dir: terraform/<account-profile>
    vars: { AWS_PROFILE: <account-profile> }
```


Patch:
diff --git a/taskfile/included_taskfile.go b/taskfile/included_taskfile.go
index a0dd8866..332f986e 100644
--- a/taskfile/included_taskfile.go
+++ b/taskfile/included_taskfile.go
@@ -12,6 +12,7 @@ type IncludedTaskfile struct {
 	Dir            string
 	Optional       bool
 	AdvancedImport bool
+	Vars           *Vars
 }
 
 // IncludedTaskfiles represents information about included tasksfiles
@@ -94,6 +95,7 @@ func (it *IncludedTaskfile) UnmarshalYAML(unmarshal func(interface{}) error) err
 		Taskfile string
 		Dir      string
 		Optional bool
+		Vars     *Vars
 	}
 	if err := unmarshal(&includedTaskfile); err != nil {
 		return err
@@ -102,5 +104,6 @@ func (it *IncludedTaskfile) UnmarshalYAML(unmarshal func(interface{}) error) err
 	it.Dir = includedTaskfile.Dir
 	it.Optional = includedTaskfile.Optional
 	it.AdvancedImport = true
+	it.Vars = includedTaskfile.Vars
 	return nil
 }
diff --git a/taskfile/read/taskfile.go b/taskfile/read/taskfile.go
index 6d54f356..ce103d51 100644
--- a/taskfile/read/taskfile.go
+++ b/taskfile/read/taskfile.go
@@ -62,6 +62,7 @@ func Taskfile(dir string, entrypoint string) (*taskfile.Taskfile, error) {
 				Dir:            tr.Replace(includedTask.Dir),
 				Optional:       includedTask.Optional,
 				AdvancedImport: includedTask.AdvancedImport,
+				Vars:           includedTask.Vars,
 			}
 			if err := tr.Err(); err != nil {
 				return err
@@ -109,6 +110,12 @@ func Taskfile(dir string, entrypoint string) (*taskfile.Taskfile, error) {
 			}
 
 			for _, task := range includedTaskfile.Tasks {
+				if includedTask.Vars != nil {
+					if task.Vars == nil {
+						task.Vars = &taskfile.Vars{}
+					}
+					task.Vars.Merge(includedTask.Vars)
+				}
 				if !filepath.IsAbs(task.Dir) {
 					task.Dir = filepath.Join(includedTask.Dir, task.Dir)
 				}


Test patch:
diff --git a/task_test.go b/task_test.go
index 40cf95c3..d4f820b1 100644
--- a/task_test.go
+++ b/task_test.go
@@ -1218,3 +1218,32 @@ Bye!
 	t.Log(buff.String())
 	assert.Equal(t, strings.TrimSpace(buff.String()), expectedOutputOrder)
 }
+
+func TestIncludedVars(t *testing.T) {
+	const dir = "testdata/include_with_vars"
+	var buff bytes.Buffer
+	e := task.Executor{
+		Dir:    dir,
+		Stdout: &buff,
+		Stderr: &buff,
+	}
+	assert.NoError(t, e.Setup())
+
+	expectedOutputOrder := strings.TrimSpace(`
+task: [included1:task1] echo "VAR_1 is included1-var1"
+VAR_1 is included1-var1
+task: [included1:task1] echo "VAR_2 is incldued-default-var2"
+VAR_2 is incldued-default-var2
+task: [included2:task1] echo "VAR_1 is included2-var1"
+VAR_1 is included2-var1
+task: [included2:task1] echo "VAR_2 is incldued-default-var2"
+VAR_2 is incldued-default-var2
+task: [included3:task1] echo "VAR_1 is included-default-var1"
+VAR_1 is included-default-var1
+task: [included3:task1] echo "VAR_2 is incldued-default-var2"
+VAR_2 is incldued-default-var2
+`)
+	assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: "task1"}))
+	t.Log(buff.String())
+	assert.Equal(t, strings.TrimSpace(buff.String()), expectedOutputOrder)
+}
diff --git a/testdata/include_with_vars/Taskfile.yml b/testdata/include_with_vars/Taskfile.yml
new file mode 100644
index 00000000..aee8f515
--- /dev/null
+++ b/testdata/include_with_vars/Taskfile.yml
@@ -0,0 +1,20 @@
+version: "3"
+
+includes:
+  included1:
+    taskfile: include/Taskfile.include.yml
+    vars:
+      VAR_1: included1-var1
+  included2:
+    taskfile: include/Taskfile.include.yml
+    vars:
+      VAR_1: included2-var1
+  included3:
+    taskfile: include/Taskfile.include.yml
+
+tasks:
+  task1:
+    cmds:
+      - task: included1:task1
+      - task: included2:task1
+      - task: included3:task1
diff --git a/testdata/include_with_vars/include/Taskfile.include.yml b/testdata/include_with_vars/include/Taskfile.include.yml
new file mode 100644
index 00000000..dd2a4e65
--- /dev/null
+++ b/testdata/include_with_vars/include/Taskfile.include.yml
@@ -0,0 +1,11 @@
+version: "3"
+
+vars:
+  VAR_1: included-default-var1
+  VAR_2: incldued-default-var2
+
+tasks:
+  task1:
+    cmds:
+      - echo "VAR_1 is {{.VAR_1}}"
+      - echo "VAR_2 is {{.VAR_2}}"