fix(compiler): add call.Vars support in scoped mode

When calling a task with vars (e.g., `task: name` with `vars:`),
those vars were not being applied in scoped mode. This fix adds
call.Vars to the variable resolution chain.

Variable priority (lowest to highest):
1. Root Taskfile vars
2. Include Taskfile vars
3. Include passthrough vars
4. Task vars
5. Call vars (NEW)
6. CLI vars
This commit is contained in:
Valentin Maerten
2025-12-29 17:07:48 +01:00
parent 5ef7313e95
commit a57a16efca
5 changed files with 67 additions and 12 deletions

View File

@@ -218,6 +218,12 @@ func (c *Compiler) getVariables(t *ast.Task, call *Call, evaluateShVars bool) (*
return nil, err
}
}
// Apply call vars (vars passed when calling a task)
for k, v := range call.Vars.All() {
if err := taskRangeFunc(k, v); err != nil {
return nil, err
}
}
}
// CLI vars have highest priority - applied last to override everything

View File

@@ -1272,5 +1272,14 @@ func TestScopedTaskfiles(t *testing.T) {
),
WithTask("a:print-env"),
)
// Test call vars: vars passed when calling a task override task vars
NewExecutorTest(t,
WithName("call-vars"),
WithExecutorOptions(
task.WithDir("testdata/scoped_taskfiles"),
task.WithSilent(true),
),
WithTask("call-with-vars"),
)
})
}

View File

@@ -42,3 +42,16 @@ tasks:
LOL: prout_from_root
cmds:
- echo "{{.LOL}}"
call-with-vars:
desc: Test calling a task with vars override
cmds:
- task: print-name
vars:
NAME: from_caller
print-name:
vars:
NAME: default_name
cmds:
- echo "NAME={{.NAME}}"

View File

@@ -0,0 +1 @@
NAME=from_caller

View File

@@ -98,8 +98,9 @@ still inherit variables from their parent.
### Example
```yaml
# Taskfile.yml
::: code-group
```yaml [Taskfile.yml]
version: '3'
vars:
@@ -110,8 +111,7 @@ includes:
web: ./web
```
```yaml
# api/Taskfile.yml
```yaml [api/Taskfile.yml]
version: '3'
vars:
@@ -130,8 +130,7 @@ tasks:
- echo "WEB_VAR={{.WEB_VAR}}"
```
```yaml
# web/Taskfile.yml
```yaml [web/Taskfile.yml]
version: '3'
vars:
@@ -150,10 +149,23 @@ tasks:
- echo "API_VAR={{.API_VAR}}"
```
## CLI Variables Priority
:::
With this experiment, CLI variables (passed as `task foo VAR=value`) have the
highest priority and will override task-level variables.
## Variable Priority
With this experiment, variables follow a clear priority order (lowest to
highest):
| Priority | Source | Description |
| -------- | ------------------------ | ---------------------------------------- |
| 1 | Root Taskfile vars | `vars:` in the root Taskfile |
| 2 | Include Taskfile vars | `vars:` in the included Taskfile |
| 3 | Include passthrough vars | `includes: name: vars:` from parent |
| 4 | Task vars | `tasks: name: vars:` in the task |
| 5 | Call vars | `task: name` with `vars:` when calling |
| 6 | CLI vars | `task foo VAR=value` on command line |
### Example: Call vars override task vars
```yaml
version: '3'
@@ -161,14 +173,28 @@ version: '3'
tasks:
greet:
vars:
NAME: from_task
NAME: default
cmds:
- echo "Hello {{.NAME}}"
caller:
cmds:
- task: greet
vars:
NAME: from_caller
```
```bash
# CLI vars now override task vars
TASK_X_SCOPED_TASKFILES=1 task greet NAME=cli
# Direct call uses task default
task greet
# Output: Hello default
# Call vars override task vars
task caller
# Output: Hello from_caller
# CLI vars override everything
task greet NAME=cli
# Output: Hello cli
```