diff --git a/cmd/task/task.go b/cmd/task/task.go index 8091e363..5c60a052 100644 --- a/cmd/task/task.go +++ b/cmd/task/task.go @@ -28,12 +28,14 @@ Example: 'task hello' with the following 'Taskfile.yml' file will generate an 'output.txt' file with the content "hello". ''' -hello: - cmds: - - echo "I am going to write a file named 'output.txt' now." - - echo "hello" > output.txt - generates: - - output.txt +version: '2' +tasks: + hello: + cmds: + - echo "I am going to write a file named 'output.txt' now." + - echo "hello" > output.txt + generates: + - output.txt ''' Options: diff --git a/docs/taskfile_versions.md b/docs/taskfile_versions.md index a318f12a..9b76f17d 100644 --- a/docs/taskfile_versions.md +++ b/docs/taskfile_versions.md @@ -15,21 +15,7 @@ available, but not `3.0.0+`. ## Version 1 -In the first version of the `Taskfile`, the `version:` key was not available, -because the tasks was in the root of the YAML document. Like this: - -```yaml -echo: - cmds: - - echo "Hello, World!" -``` - -The variable priority order was also different: - -1. Call variables -2. Environment -3. Task variables -4. `Taskvars.yml` variables +Is deprecated and can not be used anymore. ## Version 2.0 diff --git a/internal/compiler/v1/compiler_v1.go b/internal/compiler/v1/compiler_v1.go deleted file mode 100644 index 295670e6..00000000 --- a/internal/compiler/v1/compiler_v1.go +++ /dev/null @@ -1,137 +0,0 @@ -package v1 - -import ( - "bytes" - "context" - "fmt" - "strings" - "sync" - - "github.com/go-task/task/v2/internal/compiler" - "github.com/go-task/task/v2/internal/execext" - "github.com/go-task/task/v2/internal/logger" - "github.com/go-task/task/v2/internal/taskfile" - "github.com/go-task/task/v2/internal/templater" -) - -var _ compiler.Compiler = &CompilerV1{} - -type CompilerV1 struct { - Dir string - Vars taskfile.Vars - - Logger *logger.Logger - - dynamicCache map[string]string - muDynamicCache sync.Mutex -} - -// GetVariables returns fully resolved variables following the priority order: -// 1. Call variables (should already have been resolved) -// 2. Environment (should not need to be resolved) -// 3. Task variables, resolved with access to: -// - call, taskvars and environment variables -// 4. Taskvars variables, resolved with access to: -// - environment variables -func (c *CompilerV1) GetVariables(t *taskfile.Task, call taskfile.Call) (taskfile.Vars, error) { - merge := func(dest taskfile.Vars, srcs ...taskfile.Vars) { - for _, src := range srcs { - for k, v := range src { - dest[k] = v - } - } - } - varsKeys := func(srcs ...taskfile.Vars) []string { - m := make(map[string]struct{}) - for _, src := range srcs { - for k := range src { - m[k] = struct{}{} - } - } - lst := make([]string, 0, len(m)) - for k := range m { - lst = append(lst, k) - } - return lst - } - replaceVars := func(dest taskfile.Vars, keys []string) error { - r := templater.Templater{Vars: dest} - for _, k := range keys { - v := dest[k] - dest[k] = taskfile.Var{ - Static: r.Replace(v.Static), - Sh: r.Replace(v.Sh), - } - } - return r.Err() - } - resolveShell := func(dest taskfile.Vars, keys []string) error { - for _, k := range keys { - v := dest[k] - static, err := c.HandleDynamicVar(v) - if err != nil { - return err - } - dest[k] = taskfile.Var{Static: static} - } - return nil - } - update := func(dest taskfile.Vars, srcs ...taskfile.Vars) error { - merge(dest, srcs...) - // updatedKeys ensures template evaluation is run only once. - updatedKeys := varsKeys(srcs...) - if err := replaceVars(dest, updatedKeys); err != nil { - return err - } - return resolveShell(dest, updatedKeys) - } - - // Resolve taskvars variables to "result" with environment override variables. - override := compiler.GetEnviron() - result := make(taskfile.Vars, len(c.Vars)+len(t.Vars)+len(override)) - if err := update(result, c.Vars, override); err != nil { - return nil, err - } - // Resolve task variables to "result" with environment and call override variables. - merge(override, call.Vars) - if err := update(result, t.Vars, override); err != nil { - return nil, err - } - return result, nil -} - -func (c *CompilerV1) HandleDynamicVar(v taskfile.Var) (string, error) { - if v.Static != "" || v.Sh == "" { - return v.Static, nil - } - - c.muDynamicCache.Lock() - defer c.muDynamicCache.Unlock() - - if c.dynamicCache == nil { - c.dynamicCache = make(map[string]string, 30) - } - if result, ok := c.dynamicCache[v.Sh]; ok { - return result, nil - } - - var stdout bytes.Buffer - opts := &execext.RunCommandOptions{ - Command: v.Sh, - Dir: c.Dir, - Stdout: &stdout, - Stderr: c.Logger.Stderr, - } - if err := execext.RunCommand(context.Background(), opts); err != nil { - return "", fmt.Errorf(`task: Command "%s" in taskvars file failed: %s`, opts.Command, err) - } - - // Trim a single trailing newline from the result to make most command - // output easier to use in shell commands. - result := strings.TrimSuffix(stdout.String(), "\n") - - c.dynamicCache[v.Sh] = result - c.Logger.VerboseErrf(logger.Magenta, `task: dynamic variable: '%s' result: '%s'`, v.Sh, result) - - return result, nil -} diff --git a/task.go b/task.go index 40b1dc98..8a0ab124 100644 --- a/task.go +++ b/task.go @@ -11,7 +11,6 @@ import ( "sync/atomic" "github.com/go-task/task/v2/internal/compiler" - compilerv1 "github.com/go-task/task/v2/internal/compiler/v1" compilerv2 "github.com/go-task/task/v2/internal/compiler/v2" "github.com/go-task/task/v2/internal/execext" "github.com/go-task/task/v2/internal/logger" @@ -122,14 +121,16 @@ func (e *Executor) Setup() error { if err != nil { return fmt.Errorf(`task: Could not parse taskfile version "%s": %v`, e.Taskfile.Version, err) } + + if v < 2 { + return fmt.Errorf(`task: Taskfile version prior to v2 are not supported anymore`) + } + // consider as equal to the greater version if round if v == 2.0 { v = 2.6 } - if v < 1 { - return fmt.Errorf(`task: Taskfile version should be greater or equal to v1`) - } if v > 3.0 { return fmt.Errorf(`task: Taskfile versions greater than v3.0 not implemented in the version of Task`) } @@ -139,20 +140,12 @@ func (e *Executor) Setup() error { e.Logger.Color = false } - if v < 2 { - e.Compiler = &compilerv1.CompilerV1{ - Dir: e.Dir, - Vars: e.taskvars, - Logger: e.Logger, - } - } else { // v >= 2 - e.Compiler = &compilerv2.CompilerV2{ - Dir: e.Dir, - Taskvars: e.taskvars, - TaskfileVars: e.Taskfile.Vars, - Expansions: e.Taskfile.Expansions, - Logger: e.Logger, - } + e.Compiler = &compilerv2.CompilerV2{ + Dir: e.Dir, + Taskvars: e.taskvars, + TaskfileVars: e.Taskfile.Vars, + Expansions: e.Taskfile.Expansions, + Logger: e.Logger, } if v < 2.1 && e.Taskfile.Output != "" { diff --git a/task_test.go b/task_test.go index b4aa4544..7b512271 100644 --- a/task_test.go +++ b/task_test.go @@ -69,43 +69,6 @@ func TestEnv(t *testing.T) { tt.Run(t) } -func TestVarsV1(t *testing.T) { - tt := fileContentTest{ - Dir: "testdata/vars/v1", - Target: "default", - TrimSpace: true, - Files: map[string]string{ - // hello task: - "foo.txt": "foo", - "bar.txt": "bar", - "baz.txt": "baz", - "tmpl_foo.txt": "foo", - "tmpl_bar.txt": "", - "tmpl_foo2.txt": "foo2", - "tmpl_bar2.txt": "bar2", - "shtmpl_foo.txt": "foo", - "shtmpl_foo2.txt": "foo2", - "nestedtmpl_foo.txt": "{{.FOO}}", - "nestedtmpl_foo2.txt": "foo2", - "foo2.txt": "foo2", - "bar2.txt": "bar2", - "baz2.txt": "baz2", - "tmpl2_foo.txt": "", - "tmpl2_foo2.txt": "foo2", - "tmpl2_bar.txt": "", - "tmpl2_bar2.txt": "", - "shtmpl2_foo.txt": "", - "shtmpl2_foo2.txt": "foo2", - "nestedtmpl2_foo2.txt": "{{.FOO2}}", - "override.txt": "bar", - }, - } - tt.Run(t) - // Ensure identical results when running hello task directly. - tt.Target = "hello" - tt.Run(t) -} - func TestVarsV2(t *testing.T) { tt := fileContentTest{ Dir: "testdata/vars/v2", @@ -144,7 +107,7 @@ func TestVarsV2(t *testing.T) { } func TestMultilineVars(t *testing.T) { - for _, dir := range []string{"testdata/vars/v1/multiline", "testdata/vars/v2/multiline"} { + for _, dir := range []string{"testdata/vars/v2/multiline"} { tt := fileContentTest{ Dir: dir, Target: "default", @@ -168,7 +131,7 @@ func TestMultilineVars(t *testing.T) { func TestVarsInvalidTmpl(t *testing.T) { const ( - dir = "testdata/vars/v1" + dir = "testdata/vars/v2" target = "invalid-var-tmpl" expectError = "template: :1: unexpected EOF" ) @@ -441,7 +404,6 @@ func TestTaskVersion(t *testing.T) { Dir string Version string }{ - {"testdata/version/v1", "1"}, {"testdata/version/v2", "2"}, } @@ -678,3 +640,12 @@ func TestWhenDirAttributeItCreatesMissingAndRunsInThatDir(t *testing.T) { // Clean-up after ourselves only if no error. _ = os.Remove(toBeCreated) } + +func TestDisplaysErrorOnUnsupportedVersion(t *testing.T) { + e := task.Executor{ + Dir: "testdata/version/v1", + Stdout: ioutil.Discard, + Stderr: ioutil.Discard, + } + assert.Error(t, e.Setup()) +} diff --git a/testdata/checksum/Taskfile.yml b/testdata/checksum/Taskfile.yml index 4f4a2362..1c620a71 100644 --- a/testdata/checksum/Taskfile.yml +++ b/testdata/checksum/Taskfile.yml @@ -1,9 +1,12 @@ -build: - cmds: - - cp ./source.txt ./generated.txt - sources: - - ./**/glob-with-inexistent-file.txt - - ./source.txt - generates: - - ./generated.txt - method: checksum +version: '2' + +tasks: + build: + cmds: + - cp ./source.txt ./generated.txt + sources: + - ./**/glob-with-inexistent-file.txt + - ./source.txt + generates: + - ./generated.txt + method: checksum diff --git a/testdata/cyclic/Taskfile.yml b/testdata/cyclic/Taskfile.yml index 65d741cb..0da55536 100644 --- a/testdata/cyclic/Taskfile.yml +++ b/testdata/cyclic/Taskfile.yml @@ -1,7 +1,10 @@ -task-1: - deps: - - task: task-2 +version: '2' -task-2: - deps: - - task: task-1 +tasks: + task-1: + deps: + - task: task-2 + + task-2: + deps: + - task: task-1 diff --git a/testdata/deps/Taskfile.yml b/testdata/deps/Taskfile.yml index dd82345c..411eeb91 100644 --- a/testdata/deps/Taskfile.yml +++ b/testdata/deps/Taskfile.yml @@ -1,53 +1,56 @@ -default: - deps: [d1, d2, d3] +version: '2' -d1: - deps: [d11, d12, d13] - cmds: - - echo 'Text' > d1.txt +tasks: + default: + deps: [d1, d2, d3] -d2: - deps: [d21, d22, d23] - cmds: - - echo 'Text' > d2.txt + d1: + deps: [d11, d12, d13] + cmds: + - echo 'Text' > d1.txt -d3: - deps: [d31, d32, d33] - cmds: - - echo 'Text' > d3.txt + d2: + deps: [d21, d22, d23] + cmds: + - echo 'Text' > d2.txt -d11: - cmds: - - echo 'Text' > d11.txt + d3: + deps: [d31, d32, d33] + cmds: + - echo 'Text' > d3.txt -d12: - cmds: - - echo 'Text' > d12.txt + d11: + cmds: + - echo 'Text' > d11.txt -d13: - cmds: - - echo 'Text' > d13.txt + d12: + cmds: + - echo 'Text' > d12.txt -d21: - cmds: - - echo 'Text' > d21.txt + d13: + cmds: + - echo 'Text' > d13.txt -d22: - cmds: - - echo 'Text' > d22.txt + d21: + cmds: + - echo 'Text' > d21.txt -d23: - cmds: - - echo 'Text' > d23.txt + d22: + cmds: + - echo 'Text' > d22.txt -d31: - cmds: - - echo 'Text' > d31.txt + d23: + cmds: + - echo 'Text' > d23.txt -d32: - cmds: - - echo 'Text' > d32.txt + d31: + cmds: + - echo 'Text' > d31.txt -d33: - cmds: - - echo 'Text' > d33.txt + d32: + cmds: + - echo 'Text' > d32.txt + + d33: + cmds: + - echo 'Text' > d33.txt diff --git a/testdata/generates/Taskfile.yml b/testdata/generates/Taskfile.yml index 26987489..d050aa6b 100644 --- a/testdata/generates/Taskfile.yml +++ b/testdata/generates/Taskfile.yml @@ -1,41 +1,44 @@ -abs.txt: - desc: generates dest file based on absolute paths - deps: - - sub/src.txt - dir: sub - cmds: - - cat src.txt > '{{.BUILD_DIR}}/abs.txt' - sources: - - src.txt - generates: - - "{{.BUILD_DIR}}/abs.txt" +version: '2' -rel.txt: - desc: generates dest file based on relative paths - deps: - - sub/src.txt - dir: sub - cmds: - - cat src.txt > '../rel.txt' - sources: - - src.txt - generates: - - "../rel.txt" +tasks: + abs.txt: + desc: generates dest file based on absolute paths + deps: + - sub/src.txt + dir: sub + cmds: + - cat src.txt > '{{.BUILD_DIR}}/abs.txt' + sources: + - src.txt + generates: + - "{{.BUILD_DIR}}/abs.txt" -sub/src.txt: - desc: generate source file - cmds: - - mkdir -p sub - - echo "hello world" > sub/src.txt - status: - - test -f sub/src.txt + rel.txt: + desc: generates dest file based on relative paths + deps: + - sub/src.txt + dir: sub + cmds: + - cat src.txt > '../rel.txt' + sources: + - src.txt + generates: + - "../rel.txt" -'my text file.txt': - desc: generate file with spaces in the name - deps: [sub/src.txt] - cmds: - - cat sub/src.txt > 'my text file.txt' - sources: - - sub/src.txt - generates: - - 'my text file.txt' + sub/src.txt: + desc: generate source file + cmds: + - mkdir -p sub + - echo "hello world" > sub/src.txt + status: + - test -f sub/src.txt + + 'my text file.txt': + desc: generate file with spaces in the name + deps: [sub/src.txt] + cmds: + - cat sub/src.txt > 'my text file.txt' + sources: + - sub/src.txt + generates: + - 'my text file.txt' diff --git a/testdata/params/Taskfile.yml b/testdata/params/Taskfile.yml index 5090580f..f8d9a91a 100644 --- a/testdata/params/Taskfile.yml +++ b/testdata/params/Taskfile.yml @@ -1,37 +1,40 @@ -default: - vars: - SPANISH: ¡Holla mundo! - PORTUGUESE: "{{.PORTUGUESE_HELLO_WORLD}}" - GERMAN: "Welt!" - deps: - - task: write-file - vars: {CONTENT: Dependence1, FILE: dep1.txt} - - task: write-file - vars: {CONTENT: Dependence2, FILE: dep2.txt} - - task: write-file - vars: {CONTENT: "{{.SPANISH|replace \"mundo\" \"dependencia\"}}", FILE: spanish-dep.txt} - cmds: - - task: write-file - vars: {CONTENT: Hello, FILE: hello.txt} - - task: write-file - vars: {CONTENT: "$echo 'World'", FILE: world.txt} - - task: write-file - vars: {CONTENT: "!", FILE: exclamation.txt} - - task: write-file - vars: {CONTENT: "{{.SPANISH}}", FILE: spanish.txt} - - task: write-file - vars: {CONTENT: "{{.PORTUGUESE}}", FILE: portuguese.txt} - - task: write-file - vars: {CONTENT: "{{.GERMAN}}", FILE: german.txt} - - task: non-default +version: '2' -write-file: - cmds: - - echo {{.CONTENT}} > {{.FILE}} +tasks: + default: + vars: + SPANISH: ¡Holla mundo! + PORTUGUESE: "{{.PORTUGUESE_HELLO_WORLD}}" + GERMAN: "Welt!" + deps: + - task: write-file + vars: {CONTENT: Dependence1, FILE: dep1.txt} + - task: write-file + vars: {CONTENT: Dependence2, FILE: dep2.txt} + - task: write-file + vars: {CONTENT: "{{.SPANISH|replace \"mundo\" \"dependencia\"}}", FILE: spanish-dep.txt} + cmds: + - task: write-file + vars: {CONTENT: Hello, FILE: hello.txt} + - task: write-file + vars: {CONTENT: "$echo 'World'", FILE: world.txt} + - task: write-file + vars: {CONTENT: "!", FILE: exclamation.txt} + - task: write-file + vars: {CONTENT: "{{.SPANISH}}", FILE: spanish.txt} + - task: write-file + vars: {CONTENT: "{{.PORTUGUESE}}", FILE: portuguese.txt} + - task: write-file + vars: {CONTENT: "{{.GERMAN}}", FILE: german.txt} + - task: non-default -non-default: - vars: - PORTUGUESE: "{{.PORTUGUESE_HELLO_WORLD}}" - cmds: - - task: write-file - vars: {CONTENT: "{{.PORTUGUESE}}", FILE: portuguese2.txt} + write-file: + cmds: + - echo {{.CONTENT}} > {{.FILE}} + + non-default: + vars: + PORTUGUESE: "{{.PORTUGUESE_HELLO_WORLD}}" + cmds: + - task: write-file + vars: {CONTENT: "{{.PORTUGUESE}}", FILE: portuguese2.txt} diff --git a/testdata/status/Taskfile.yml b/testdata/status/Taskfile.yml index e3a69232..57900efc 100644 --- a/testdata/status/Taskfile.yml +++ b/testdata/status/Taskfile.yml @@ -1,5 +1,8 @@ -gen-foo: - cmds: - - touch foo.txt - status: - - test -f foo.txt +version: '2' + +tasks: + gen-foo: + cmds: + - touch foo.txt + status: + - test -f foo.txt diff --git a/testdata/summary/Taskfile.yml b/testdata/summary/Taskfile.yml index 5df3ef01..3e4d4640 100644 --- a/testdata/summary/Taskfile.yml +++ b/testdata/summary/Taskfile.yml @@ -1,4 +1,4 @@ -version: 2 +version: '2' tasks: task-with-summary: diff --git a/testdata/vars/v1/.gitignore b/testdata/vars/v1/.gitignore deleted file mode 100644 index 2211df63..00000000 --- a/testdata/vars/v1/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*.txt diff --git a/testdata/vars/v1/Taskfile.yml b/testdata/vars/v1/Taskfile.yml deleted file mode 100644 index f0868921..00000000 --- a/testdata/vars/v1/Taskfile.yml +++ /dev/null @@ -1,48 +0,0 @@ -default: - deps: [hello] - -hello: - cmds: - - echo {{.FOO}} > foo.txt - - echo {{.BAR}} > bar.txt - - echo {{.BAZ}} > baz.txt - - echo '{{.TMPL_FOO}}' > tmpl_foo.txt - - echo '{{.TMPL_BAR}}' > tmpl_bar.txt - - echo '{{.TMPL_FOO2}}' > tmpl_foo2.txt - - echo '{{.TMPL_BAR2}}' > tmpl_bar2.txt - - echo '{{.SHTMPL_FOO}}' > shtmpl_foo.txt - - echo '{{.SHTMPL_FOO2}}' > shtmpl_foo2.txt - - echo '{{.NESTEDTMPL_FOO}}' > nestedtmpl_foo.txt - - echo '{{.NESTEDTMPL_FOO2}}' > nestedtmpl_foo2.txt - - echo {{.FOO2}} > foo2.txt - - echo {{.BAR2}} > bar2.txt - - echo {{.BAZ2}} > baz2.txt - - echo '{{.TMPL2_FOO}}' > tmpl2_foo.txt - - echo '{{.TMPL2_BAR}}' > tmpl2_bar.txt - - echo '{{.TMPL2_FOO2}}' > tmpl2_foo2.txt - - echo '{{.TMPL2_BAR2}}' > tmpl2_bar2.txt - - echo '{{.SHTMPL2_FOO}}' > shtmpl2_foo.txt - - echo '{{.SHTMPL2_FOO2}}' > shtmpl2_foo2.txt - - echo '{{.NESTEDTMPL2_FOO2}}' > nestedtmpl2_foo2.txt - - echo {{.OVERRIDE}} > override.txt - vars: - FOO: foo - BAR: $echo bar - BAZ: - sh: echo baz - TMPL_FOO: "{{.FOO}}" - TMPL_BAR: "{{.BAR}}" - TMPL_FOO2: "{{.FOO2}}" - TMPL_BAR2: "{{.BAR2}}" - SHTMPL_FOO: - sh: "echo '{{.FOO}}'" - SHTMPL_FOO2: - sh: "echo '{{.FOO2}}'" - NESTEDTMPL_FOO: "{{.TMPL_FOO}}" - NESTEDTMPL_FOO2: "{{.TMPL2_FOO2}}" - OVERRIDE: "bar" - -invalid-var-tmpl: - vars: - CHARS: "abcd" - INVALID: "{{range .CHARS}}no end" diff --git a/testdata/vars/v1/Taskvars.yml b/testdata/vars/v1/Taskvars.yml deleted file mode 100644 index 7b5bfb33..00000000 --- a/testdata/vars/v1/Taskvars.yml +++ /dev/null @@ -1,12 +0,0 @@ -FOO2: foo2 -BAR2: $echo bar2 -BAZ2: - sh: echo baz2 -TMPL2_FOO: "{{.FOO}}" -TMPL2_BAR: "{{.BAR}}" -TMPL2_FOO2: "{{.FOO2}}" -TMPL2_BAR2: "{{.BAR2}}" -SHTMPL2_FOO2: - sh: "echo '{{.FOO2}}'" -NESTEDTMPL2_FOO2: "{{.TMPL2_FOO2}}" -OVERRIDE: "foo" diff --git a/testdata/vars/v1/multiline/Taskfile.yml b/testdata/vars/v1/multiline/Taskfile.yml deleted file mode 100644 index 79ba86d7..00000000 --- a/testdata/vars/v1/multiline/Taskfile.yml +++ /dev/null @@ -1,43 +0,0 @@ -default: - vars: - MULTILINE: "\n\nfoo\n bar\nfoobar\n\nbaz\n\n" - cmds: - - task: file - vars: - CONTENT: - sh: "echo 'foo\nbar'" - FILE: "echo_foobar.txt" - - task: file - vars: - CONTENT: - sh: "echo -n 'foo\nbar'" - FILE: "echo_n_foobar.txt" - - task: file - vars: - CONTENT: - sh: echo -n "{{.MULTILINE}}" - FILE: "echo_n_multiline.txt" - - task: file - vars: - CONTENT: "{{.MULTILINE}}" - FILE: "var_multiline.txt" - - task: file - vars: - CONTENT: "{{.MULTILINE | catLines}}" - FILE: "var_catlines.txt" - - task: enumfile - vars: - LINES: "{{.MULTILINE}}" - FILE: "var_enumfile.txt" -file: - cmds: - - | - cat << EOF > '{{.FILE}}' - {{.CONTENT}} - EOF -enumfile: - cmds: - - | - cat << EOF > '{{.FILE}}' - {{range $i, $line := .LINES| splitLines}}{{$i}}:{{$line}} - {{end}}EOF diff --git a/testdata/version/v2/Taskfile.yml b/testdata/version/v2/Taskfile.yml index 8dbdd900..9f47f2df 100644 --- a/testdata/version/v2/Taskfile.yml +++ b/testdata/version/v2/Taskfile.yml @@ -1,9 +1,9 @@ -version: 2 +version: '2' + tasks: foo: cmds: - echo "Foo" - bar: cmds: - echo "Bar"