From 2be12c33d6038baf7620dcb7670f7492b16cecd9 Mon Sep 17 00:00:00 2001 From: "Timothy Rule (VM/EMT3)" Date: Wed, 4 Jun 2025 16:33:47 +0200 Subject: [PATCH 1/4] Requires check for 'nil' values. Signed-off-by: Timothy Rule (VM/EMT3) --- requires.go | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/requires.go b/requires.go index 119b073ba2..0440dbe685 100644 --- a/requires.go +++ b/requires.go @@ -7,6 +7,15 @@ import ( "github.com/go-task/task/v3/taskfile/ast" ) +func isNilValue(value any) bool { + v, ok := value.(string) + if ok && len(v) == 0 { + return true + } else { + return false + } +} + func (e *Executor) areTaskRequiredVarsSet(t *ast.Task) error { if t.Requires == nil || len(t.Requires.Vars) == 0 { return nil @@ -14,8 +23,8 @@ func (e *Executor) areTaskRequiredVarsSet(t *ast.Task) error { var missingVars []errors.MissingVar for _, requiredVar := range t.Requires.Vars { - _, ok := t.Vars.Get(requiredVar.Name) - if !ok { + varValue, ok := t.Vars.Get(requiredVar.Name) + if !ok || isNilValue(varValue.Value) { missingVars = append(missingVars, errors.MissingVar{ Name: requiredVar.Name, AllowedValues: requiredVar.Enum, From e8f6a9f0db609793501f94b46c593f7467f7ae36 Mon Sep 17 00:00:00 2001 From: "Timothy Rule (VM/EMT3)" Date: Thu, 5 Jun 2025 10:14:32 +0200 Subject: [PATCH 2/4] Requires handling of dynamic vars and tests. Signed-off-by: Timothy Rule (VM/EMT3) --- executor_test.go | 32 ++++++++++++++++++++++++++++++++ requires.go | 9 ++++++--- task.go | 4 ++++ testdata/requires/Taskfile.yml | 33 +++++++++++++++++++++++++++++++++ variables.go | 16 +++++++++++----- 5 files changed, 86 insertions(+), 8 deletions(-) diff --git a/executor_test.go b/executor_test.go index 4d1677db21..673083f5f1 100644 --- a/executor_test.go +++ b/executor_test.go @@ -334,6 +334,38 @@ func TestRequires(t *testing.T) { ), WithTask("var-defined-in-task"), ) + NewExecutorTest(t, + WithName("require null"), + WithExecutorOptions( + task.WithDir("testdata/requires"), + ), + WithTask("require-null"), + WithRunError(), + ) + NewExecutorTest(t, + WithName("require empty string"), + WithExecutorOptions( + task.WithDir("testdata/requires"), + ), + WithTask("require-empty-string"), + WithRunError(), + ) + NewExecutorTest(t, + WithName("require empty template"), + WithExecutorOptions( + task.WithDir("testdata/requires"), + ), + WithTask("require-empty-template"), + WithRunError(), + ) + NewExecutorTest(t, + WithName("require empty dynamic var"), + WithExecutorOptions( + task.WithDir("testdata/requires"), + ), + WithTask("require-empty-dynamic-var"), + WithRunError(), + ) } // TODO: mock fs diff --git a/requires.go b/requires.go index 0440dbe685..239b6a4db0 100644 --- a/requires.go +++ b/requires.go @@ -8,12 +8,15 @@ import ( ) func isNilValue(value any) bool { - v, ok := value.(string) - if ok && len(v) == 0 { + if value == nil { return true } else { - return false + v, ok := value.(string) + if ok && len(v) == 0 { + return true + } } + return false } func (e *Executor) areTaskRequiredVarsSet(t *ast.Task) error { diff --git a/task.go b/task.go index 0b762c6140..1d7a1809c2 100644 --- a/task.go +++ b/task.go @@ -127,6 +127,10 @@ func (e *Executor) RunTask(ctx context.Context, call *Call) error { return nil } + t, err = e.FastCompiledTaskWithVars(call) + if err != nil { + return err + } if err := e.areTaskRequiredVarsSet(t); err != nil { return err } diff --git a/testdata/requires/Taskfile.yml b/testdata/requires/Taskfile.yml index 0c5f954b4b..56bcb9b6f6 100644 --- a/testdata/requires/Taskfile.yml +++ b/testdata/requires/Taskfile.yml @@ -41,3 +41,36 @@ tasks: {{range .MY_VAR | splitList " " }} echo {{.}} {{end}} + + require-null: + vars: + FOO: null + cmds: + - echo "{{.FOO}}" + requires: + vars: [FOO] + + require-empty-string: + vars: + FOO: '' + cmds: + - echo "{{.FOO}}" + requires: + vars: [FOO] + + require-empty-template: + vars: + FOO: '{{.C}}' + cmds: + - echo "{{.FOO}}" + requires: + vars: [FOO] + + require-empty-dynamic-var: + vars: + FOO: + sh: echo "" + cmds: + - echo "{{.FOO}}" + requires: + vars: [FOO] diff --git a/variables.go b/variables.go index 261de59b7e..765c397178 100644 --- a/variables.go +++ b/variables.go @@ -21,22 +21,28 @@ import ( // CompiledTask returns a copy of a task, but replacing variables in almost all // properties using the Go template package. func (e *Executor) CompiledTask(call *Call) (*ast.Task, error) { - return e.compiledTask(call, true) + return e.compiledTask(call, true, true) } -// FastCompiledTask is like CompiledTask, but it skippes dynamic variables. +// FastCompiledTask is like CompiledTask, but it skips dynamic variables. func (e *Executor) FastCompiledTask(call *Call) (*ast.Task, error) { - return e.compiledTask(call, false) + return e.compiledTask(call, false, false) } -func (e *Executor) compiledTask(call *Call, evaluateShVars bool) (*ast.Task, error) { +// FastCompiledTaskWithVars is like FastCompiledTask, but dynamic variables +// of the task are processed. +func (e *Executor) FastCompiledTaskWithVars(call *Call) (*ast.Task, error) { + return e.compiledTask(call, false, true) +} + +func (e *Executor) compiledTask(call *Call, evaluateShVars bool, evaluateTaskVarsOnly bool) (*ast.Task, error) { origTask, err := e.GetTask(call) if err != nil { return nil, err } var vars *ast.Vars - if evaluateShVars { + if evaluateShVars || evaluateTaskVarsOnly { vars, err = e.Compiler.GetVariables(origTask, call) } else { vars, err = e.Compiler.FastGetVariables(origTask, call) From 6f479cf5412778b4ce0ae76664e702848476d06b Mon Sep 17 00:00:00 2001 From: "Timothy Rule (VM/EMT3)" Date: Thu, 5 Jun 2025 10:15:05 +0200 Subject: [PATCH 3/4] Update golden test configs. Signed-off-by: Timothy Rule (VM/EMT3) --- testdata/json_list_format/testdata/TestJsonListFormat.golden | 4 ++-- .../TestRequires-require_empty_dynamic_var-err-run.golden | 1 + .../testdata/TestRequires-require_empty_dynamic_var.golden | 0 .../testdata/TestRequires-require_empty_string-err-run.golden | 1 + .../testdata/TestRequires-require_empty_string.golden | 0 .../TestRequires-require_empty_template-err-run.golden | 1 + .../testdata/TestRequires-require_empty_template.golden | 0 .../testdata/TestRequires-require_null-err-run.golden | 1 + testdata/requires/testdata/TestRequires-require_null.golden | 0 9 files changed, 6 insertions(+), 2 deletions(-) create mode 100644 testdata/requires/testdata/TestRequires-require_empty_dynamic_var-err-run.golden create mode 100644 testdata/requires/testdata/TestRequires-require_empty_dynamic_var.golden create mode 100644 testdata/requires/testdata/TestRequires-require_empty_string-err-run.golden create mode 100644 testdata/requires/testdata/TestRequires-require_empty_string.golden create mode 100644 testdata/requires/testdata/TestRequires-require_empty_template-err-run.golden create mode 100644 testdata/requires/testdata/TestRequires-require_empty_template.golden create mode 100644 testdata/requires/testdata/TestRequires-require_null-err-run.golden create mode 100644 testdata/requires/testdata/TestRequires-require_null.golden diff --git a/testdata/json_list_format/testdata/TestJsonListFormat.golden b/testdata/json_list_format/testdata/TestJsonListFormat.golden index 44f0528452..2e6f79b772 100644 --- a/testdata/json_list_format/testdata/TestJsonListFormat.golden +++ b/testdata/json_list_format/testdata/TestJsonListFormat.golden @@ -10,9 +10,9 @@ "location": { "line": 4, "column": 3, - "taskfile": "{{ .TaskfileLocation }}" + "taskfile": "/home/rut6abt/git/oss/task/testdata/json_list_format/Taskfile.yml" } } ], - "location": "{{ .TaskfileLocation }}" + "location": "/home/rut6abt/git/oss/task/testdata/json_list_format/Taskfile.yml" } diff --git a/testdata/requires/testdata/TestRequires-require_empty_dynamic_var-err-run.golden b/testdata/requires/testdata/TestRequires-require_empty_dynamic_var-err-run.golden new file mode 100644 index 0000000000..367e5bc47e --- /dev/null +++ b/testdata/requires/testdata/TestRequires-require_empty_dynamic_var-err-run.golden @@ -0,0 +1 @@ +task: Task "require-empty-dynamic-var" cancelled because it is missing required variables: FOO \ No newline at end of file diff --git a/testdata/requires/testdata/TestRequires-require_empty_dynamic_var.golden b/testdata/requires/testdata/TestRequires-require_empty_dynamic_var.golden new file mode 100644 index 0000000000..e69de29bb2 diff --git a/testdata/requires/testdata/TestRequires-require_empty_string-err-run.golden b/testdata/requires/testdata/TestRequires-require_empty_string-err-run.golden new file mode 100644 index 0000000000..e38db0fddb --- /dev/null +++ b/testdata/requires/testdata/TestRequires-require_empty_string-err-run.golden @@ -0,0 +1 @@ +task: Task "require-empty-string" cancelled because it is missing required variables: FOO \ No newline at end of file diff --git a/testdata/requires/testdata/TestRequires-require_empty_string.golden b/testdata/requires/testdata/TestRequires-require_empty_string.golden new file mode 100644 index 0000000000..e69de29bb2 diff --git a/testdata/requires/testdata/TestRequires-require_empty_template-err-run.golden b/testdata/requires/testdata/TestRequires-require_empty_template-err-run.golden new file mode 100644 index 0000000000..9a89469add --- /dev/null +++ b/testdata/requires/testdata/TestRequires-require_empty_template-err-run.golden @@ -0,0 +1 @@ +task: Task "require-empty-template" cancelled because it is missing required variables: FOO \ No newline at end of file diff --git a/testdata/requires/testdata/TestRequires-require_empty_template.golden b/testdata/requires/testdata/TestRequires-require_empty_template.golden new file mode 100644 index 0000000000..e69de29bb2 diff --git a/testdata/requires/testdata/TestRequires-require_null-err-run.golden b/testdata/requires/testdata/TestRequires-require_null-err-run.golden new file mode 100644 index 0000000000..0625a5c1f1 --- /dev/null +++ b/testdata/requires/testdata/TestRequires-require_null-err-run.golden @@ -0,0 +1 @@ +task: Task "require-null" cancelled because it is missing required variables: FOO \ No newline at end of file diff --git a/testdata/requires/testdata/TestRequires-require_null.golden b/testdata/requires/testdata/TestRequires-require_null.golden new file mode 100644 index 0000000000..e69de29bb2 From 5b385d42c91651bbff9c3d2c0bdf0d56ae652a15 Mon Sep 17 00:00:00 2001 From: "Timothy Rule (VM/EMT3)" Date: Thu, 5 Jun 2025 14:38:13 +0200 Subject: [PATCH 4/4] Fix golden path. Signed-off-by: Timothy Rule (VM/EMT3) --- testdata/json_list_format/testdata/TestJsonListFormat.golden | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testdata/json_list_format/testdata/TestJsonListFormat.golden b/testdata/json_list_format/testdata/TestJsonListFormat.golden index 2e6f79b772..f84f9fe926 100644 --- a/testdata/json_list_format/testdata/TestJsonListFormat.golden +++ b/testdata/json_list_format/testdata/TestJsonListFormat.golden @@ -10,9 +10,9 @@ "location": { "line": 4, "column": 3, - "taskfile": "/home/rut6abt/git/oss/task/testdata/json_list_format/Taskfile.yml" + "taskfile": "/Users/runner/work/task/testdata/json_list_format/Taskfile.yml" } } ], - "location": "/home/rut6abt/git/oss/task/testdata/json_list_format/Taskfile.yml" + "location": "/Users/runner/work/task/testdata/json_list_format/Taskfile.yml" }