From a57a16efca2e1f6189a778daee1cb8bfd1b2054f Mon Sep 17 00:00:00 2001 From: Valentin Maerten Date: Mon, 29 Dec 2025 17:07:48 +0100 Subject: [PATCH] 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 --- compiler.go | 6 +++ executor_test.go | 9 ++++ testdata/scoped_taskfiles/Taskfile.yml | 13 +++++ ...estScopedTaskfiles-scoped-call-vars.golden | 1 + .../src/docs/experiments/scoped-taskfiles.md | 50 ++++++++++++++----- 5 files changed, 67 insertions(+), 12 deletions(-) create mode 100644 testdata/scoped_taskfiles/testdata/TestScopedTaskfiles-scoped-call-vars.golden diff --git a/compiler.go b/compiler.go index 1e24b3b3..53d09d78 100644 --- a/compiler.go +++ b/compiler.go @@ -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 diff --git a/executor_test.go b/executor_test.go index dd268330..574ea27a 100644 --- a/executor_test.go +++ b/executor_test.go @@ -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"), + ) }) } diff --git a/testdata/scoped_taskfiles/Taskfile.yml b/testdata/scoped_taskfiles/Taskfile.yml index 77185977..8cff7113 100644 --- a/testdata/scoped_taskfiles/Taskfile.yml +++ b/testdata/scoped_taskfiles/Taskfile.yml @@ -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}}" diff --git a/testdata/scoped_taskfiles/testdata/TestScopedTaskfiles-scoped-call-vars.golden b/testdata/scoped_taskfiles/testdata/TestScopedTaskfiles-scoped-call-vars.golden new file mode 100644 index 00000000..8a11e1d5 --- /dev/null +++ b/testdata/scoped_taskfiles/testdata/TestScopedTaskfiles-scoped-call-vars.golden @@ -0,0 +1 @@ +NAME=from_caller diff --git a/website/src/docs/experiments/scoped-taskfiles.md b/website/src/docs/experiments/scoped-taskfiles.md index 7cee72e8..ad349ac4 100644 --- a/website/src/docs/experiments/scoped-taskfiles.md +++ b/website/src/docs/experiments/scoped-taskfiles.md @@ -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 ```