diff --git a/CHANGELOG.md b/CHANGELOG.md index 8648a432..4a8f0871 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ # v3.0.0 - Unreleased +- On `v3`, all CLI variables will be considered global variables + ([#336](https://github.com/go-task/task/issues/336), [#341](https://github.com/go-task/task/pull/341)) - Add support to `.env` like files ([#324](https://github.com/go-task/task/issues/324), [#356](https://github.com/go-task/task/pull/356)). - Add `label:` to task so you can override the task name in the logs diff --git a/cmd/task/task.go b/cmd/task/task.go index d80c972c..9d0e2555 100644 --- a/cmd/task/task.go +++ b/cmd/task/task.go @@ -12,6 +12,7 @@ import ( "github.com/go-task/task/v3" "github.com/go-task/task/v3/internal/args" "github.com/go-task/task/v3/internal/logger" + "github.com/go-task/task/v3/internal/taskfile" "github.com/spf13/pflag" ) @@ -141,13 +142,26 @@ func main() { if err := e.Setup(); err != nil { log.Fatal(err) } + v, err := e.Taskfile.ParsedVersion() + if err != nil { + log.Fatal(err) + return + } if list { e.PrintTasksHelp() return } - calls, globals := args.Parse(pflag.Args()...) + var ( + calls []taskfile.Call + globals *taskfile.Vars + ) + if v >= 3.0 { + calls, globals = args.ParseV3(pflag.Args()...) + } else { + calls, globals = args.ParseV2(pflag.Args()...) + } e.Taskfile.Vars.Merge(globals) ctx := context.Background() diff --git a/docs/usage.md b/docs/usage.md index 7691f1c1..9e1051db 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -488,19 +488,11 @@ $ TASK_VARIABLE=a-value task do-something Since some shells don't support above syntax to set environment variables (Windows) tasks also accepts a similar style when not in the beginning of -the command. Variables given in this form are only visible to the task called -right before. - +the command. ```bash $ task write-file FILE=file.txt "CONTENT=Hello, World!" print "MESSAGE=All done!" ``` -If you want to set global variables using this syntax, give it before any task: - -```bash -$ task OUTPUT=file.txt generate-file -``` - Example of locally declared vars: ```yaml diff --git a/internal/args/args.go b/internal/args/args.go index 6d99b323..e152b8f0 100644 --- a/internal/args/args.go +++ b/internal/args/args.go @@ -6,8 +6,33 @@ import ( "github.com/go-task/task/v3/internal/taskfile" ) -// Parse parses command line argument: tasks and vars of each task -func Parse(args ...string) ([]taskfile.Call, *taskfile.Vars) { +// ParseV3 parses command line argument: tasks and global variables +func ParseV3(args ...string) ([]taskfile.Call, *taskfile.Vars) { + var calls []taskfile.Call + var globals *taskfile.Vars + + for _, arg := range args { + if !strings.Contains(arg, "=") { + calls = append(calls, taskfile.Call{Task: arg}) + continue + } + + if globals == nil { + globals = &taskfile.Vars{} + } + name, value := splitVar(arg) + globals.Set(name, taskfile.Var{Static: value}) + } + + if len(calls) == 0 { + calls = append(calls, taskfile.Call{Task: "default"}) + } + + return calls, globals +} + +// ParseV2 parses command line argument: tasks and vars of each task +func ParseV2(args ...string) ([]taskfile.Call, *taskfile.Vars) { var calls []taskfile.Call var globals *taskfile.Vars diff --git a/internal/args/args_test.go b/internal/args/args_test.go index 69d23495..086a9d2a 100644 --- a/internal/args/args_test.go +++ b/internal/args/args_test.go @@ -10,7 +10,98 @@ import ( "github.com/stretchr/testify/assert" ) -func TestArgs(t *testing.T) { +func TestArgsV3(t *testing.T) { + tests := []struct { + Args []string + ExpectedCalls []taskfile.Call + ExpectedGlobals *taskfile.Vars + }{ + { + Args: []string{"task-a", "task-b", "task-c"}, + ExpectedCalls: []taskfile.Call{ + {Task: "task-a"}, + {Task: "task-b"}, + {Task: "task-c"}, + }, + }, + { + Args: []string{"task-a", "FOO=bar", "task-b", "task-c", "BAR=baz", "BAZ=foo"}, + ExpectedCalls: []taskfile.Call{ + {Task: "task-a"}, + {Task: "task-b"}, + {Task: "task-c"}, + }, + ExpectedGlobals: &taskfile.Vars{ + Keys: []string{"FOO", "BAR", "BAZ"}, + Mapping: map[string]taskfile.Var{ + "FOO": taskfile.Var{Static: "bar"}, + "BAR": taskfile.Var{Static: "baz"}, + "BAZ": taskfile.Var{Static: "foo"}, + }, + }, + }, + { + Args: []string{"task-a", "CONTENT=with some spaces"}, + ExpectedCalls: []taskfile.Call{ + {Task: "task-a"}, + }, + ExpectedGlobals: &taskfile.Vars{ + Keys: []string{"CONTENT"}, + Mapping: map[string]taskfile.Var{ + "CONTENT": taskfile.Var{Static: "with some spaces"}, + }, + }, + }, + { + Args: []string{"FOO=bar", "task-a", "task-b"}, + ExpectedCalls: []taskfile.Call{ + {Task: "task-a"}, + {Task: "task-b"}, + }, + ExpectedGlobals: &taskfile.Vars{ + Keys: []string{"FOO"}, + Mapping: map[string]taskfile.Var{ + "FOO": {Static: "bar"}, + }, + }, + }, + { + Args: nil, + ExpectedCalls: []taskfile.Call{ + {Task: "default"}, + }, + }, + { + Args: []string{}, + ExpectedCalls: []taskfile.Call{ + {Task: "default"}, + }, + }, + { + Args: []string{"FOO=bar", "BAR=baz"}, + ExpectedCalls: []taskfile.Call{ + {Task: "default"}, + }, + ExpectedGlobals: &taskfile.Vars{ + Keys: []string{"FOO", "BAR"}, + Mapping: map[string]taskfile.Var{ + "FOO": {Static: "bar"}, + "BAR": {Static: "baz"}, + }, + }, + }, + } + + for i, test := range tests { + t.Run(fmt.Sprintf("TestArgs%d", i+1), func(t *testing.T) { + calls, globals := args.ParseV3(test.Args...) + assert.Equal(t, test.ExpectedCalls, calls) + assert.Equal(t, test.ExpectedGlobals, globals) + }) + } +} + +func TestArgsV2(t *testing.T) { tests := []struct { Args []string ExpectedCalls []taskfile.Call @@ -105,7 +196,7 @@ func TestArgs(t *testing.T) { for i, test := range tests { t.Run(fmt.Sprintf("TestArgs%d", i+1), func(t *testing.T) { - calls, globals := args.Parse(test.Args...) + calls, globals := args.ParseV2(test.Args...) assert.Equal(t, test.ExpectedCalls, calls) assert.Equal(t, test.ExpectedGlobals, globals) })