From 5a78808caabd58b6953b138433e14cd3b4898d7e Mon Sep 17 00:00:00 2001 From: Valentin Maerten Date: Sun, 25 Jan 2026 19:40:29 +0100 Subject: [PATCH] fix: evaluate task-level if condition after resolving dynamic variables --- executor_test.go | 4 ++++ task.go | 23 ++++++++++--------- testdata/if/Taskfile.yml | 18 +++++++++++++++ .../TestIf-task-if-dynamic-false.golden | 2 ++ .../TestIf-task-if-dynamic-true.golden | 1 + 5 files changed, 37 insertions(+), 11 deletions(-) create mode 100644 testdata/if/testdata/TestIf-task-if-dynamic-false.golden create mode 100644 testdata/if/testdata/TestIf-task-if-dynamic-true.golden diff --git a/executor_test.go b/executor_test.go index d810e652..6e3ff3e1 100644 --- a/executor_test.go +++ b/executor_test.go @@ -1160,6 +1160,10 @@ func TestIf(t *testing.T) { // For loop with if {name: "if-in-for-loop", task: "if-in-for-loop", verbose: true}, + + // Task-level if with dynamic variable + {name: "task-if-dynamic-true", task: "task-if-dynamic-true"}, + {name: "task-if-dynamic-false", task: "task-if-dynamic-false", verbose: true}, } for _, test := range tests { diff --git a/task.go b/task.go index 0184793c..5456115f 100644 --- a/task.go +++ b/task.go @@ -148,17 +148,6 @@ func (e *Executor) RunTask(ctx context.Context, call *Call) error { return nil } - if strings.TrimSpace(t.If) != "" { - if err := execext.RunCommand(ctx, &execext.RunCommandOptions{ - Command: t.If, - Dir: t.Dir, - Env: env.Get(t), - }); err != nil { - e.Logger.VerboseOutf(logger.Yellow, "task: if condition not met - skipped: %q\n", call.Task) - return nil - } - } - // Prompt for missing required vars (just-in-time for sequential task calls) prompted, err := e.promptTaskVars(t, call) if err != nil { @@ -185,6 +174,18 @@ func (e *Executor) RunTask(ctx context.Context, call *Call) error { return err } + // Check if condition after CompiledTask so dynamic variables are resolved + if strings.TrimSpace(t.If) != "" { + if err := execext.RunCommand(ctx, &execext.RunCommandOptions{ + Command: t.If, + Dir: t.Dir, + Env: env.Get(t), + }); err != nil { + e.Logger.VerboseOutf(logger.Yellow, "task: if condition not met - skipped: %q\n", call.Task) + return nil + } + } + if !e.Watch && atomic.AddInt32(e.taskCallCount[t.Task], 1) >= MaximumTaskCall { return &errors.TaskCalledTooManyTimesError{ TaskName: t.Task, diff --git a/testdata/if/Taskfile.yml b/testdata/if/Taskfile.yml index 316b732f..72b72ed9 100644 --- a/testdata/if/Taskfile.yml +++ b/testdata/if/Taskfile.yml @@ -158,3 +158,21 @@ tasks: if: '{{ eq .ENV "dev" }}' cmds: - echo "should not appear" + + # Task-level if with dynamic variable (condition met) + task-if-dynamic-true: + vars: + ENABLE_FEATURE: + sh: 'echo "true"' + if: '{{ eq .ENABLE_FEATURE "true" }}' + cmds: + - echo "dynamic feature enabled" + + # Task-level if with dynamic variable (condition not met) + task-if-dynamic-false: + vars: + ENABLE_FEATURE: + sh: 'echo "false"' + if: '{{ eq .ENABLE_FEATURE "true" }}' + cmds: + - echo "should not appear" diff --git a/testdata/if/testdata/TestIf-task-if-dynamic-false.golden b/testdata/if/testdata/TestIf-task-if-dynamic-false.golden new file mode 100644 index 00000000..f17ef420 --- /dev/null +++ b/testdata/if/testdata/TestIf-task-if-dynamic-false.golden @@ -0,0 +1,2 @@ +task: dynamic variable: "echo \"false\"" result: "false" +task: if condition not met - skipped: "task-if-dynamic-false" diff --git a/testdata/if/testdata/TestIf-task-if-dynamic-true.golden b/testdata/if/testdata/TestIf-task-if-dynamic-true.golden new file mode 100644 index 00000000..4d1ec95b --- /dev/null +++ b/testdata/if/testdata/TestIf-task-if-dynamic-true.golden @@ -0,0 +1 @@ +dynamic feature enabled