From 8b72c86ba5b81075ba120284066df9d736ebd94f Mon Sep 17 00:00:00 2001 From: Pete Davison Date: Wed, 8 Feb 2023 10:21:43 +0000 Subject: [PATCH] feat: use semver package for taskfile schema version --- cmd/task/task.go | 7 +---- go.mod | 1 + go.sum | 2 ++ setup.go | 66 +++++++++++++++++++-------------------- task_test.go | 5 +-- taskfile/merge.go | 2 +- taskfile/read/taskfile.go | 11 ++----- taskfile/taskfile.go | 20 +++++------- variables.go | 7 +---- 9 files changed, 53 insertions(+), 68 deletions(-) diff --git a/cmd/task/task.go b/cmd/task/task.go index 31cef8248c..34da2c9d2c 100644 --- a/cmd/task/task.go +++ b/cmd/task/task.go @@ -178,11 +178,6 @@ func main() { if err := e.Setup(); err != nil { log.Fatal(err) } - v, err := e.Taskfile.ParsedVersion() - if err != nil { - log.Fatal(err) - return - } if listOptions.ShouldListTasks() { if foundTasks, err := e.ListTasks(listOptions); !foundTasks || err != nil { @@ -201,7 +196,7 @@ func main() { log.Fatal(err) } - if v >= 3.0 { + if e.Taskfile.Version.Compare(taskfile.V3) >= 0 { calls, globals = args.ParseV3(tasksAndVars...) } else { calls, globals = args.ParseV2(tasksAndVars...) diff --git a/go.mod b/go.mod index b0da9b6a45..bd1509aabe 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,7 @@ module github.com/go-task/task/v3 require ( + github.com/Masterminds/semver/v3 v3.2.0 github.com/fatih/color v1.14.1 github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 github.com/joho/godotenv v1.5.1 diff --git a/go.sum b/go.sum index 832ba9b1a7..21452dd95a 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g= +github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= diff --git a/setup.go b/setup.go index 65615431d5..fed7608109 100644 --- a/setup.go +++ b/setup.go @@ -9,6 +9,9 @@ import ( "strings" "sync" + "github.com/Masterminds/semver/v3" + "github.com/sajari/fuzzy" + compilerv2 "github.com/go-task/task/v3/internal/compiler/v2" compilerv3 "github.com/go-task/task/v3/internal/compiler/v3" "github.com/go-task/task/v3/internal/execext" @@ -17,8 +20,6 @@ import ( "github.com/go-task/task/v3/internal/output" "github.com/go-task/task/v3/taskfile" "github.com/go-task/task/v3/taskfile/read" - - "github.com/sajari/fuzzy" ) func (e *Executor) Setup() error { @@ -32,11 +33,6 @@ func (e *Executor) Setup() error { e.setupFuzzyModel() - v, err := e.Taskfile.ParsedVersion() - if err != nil { - return err - } - if err := e.setupTempDir(); err != nil { return err } @@ -45,17 +41,17 @@ func (e *Executor) Setup() error { if err := e.setupOutput(); err != nil { return err } - if err := e.setupCompiler(v); err != nil { + if err := e.setupCompiler(); err != nil { return err } - if err := e.readDotEnvFiles(v); err != nil { + if err := e.readDotEnvFiles(); err != nil { return err } - if err := e.doVersionChecks(v); err != nil { + if err := e.doVersionChecks(); err != nil { return err } - e.setupDefaults(v) + e.setupDefaults() e.setupConcurrencyState() return nil @@ -163,8 +159,8 @@ func (e *Executor) setupOutput() error { return err } -func (e *Executor) setupCompiler(v float64) error { - if v < 3 { +func (e *Executor) setupCompiler() error { + if e.Taskfile.Version.LessThan(taskfile.V3) { var err error e.taskvars, err = read.Taskvars(e.Dir) if err != nil { @@ -195,8 +191,8 @@ func (e *Executor) setupCompiler(v float64) error { return nil } -func (e *Executor) readDotEnvFiles(v float64) error { - if v < 3.0 { +func (e *Executor) readDotEnvFiles() error { + if e.Taskfile.Version.LessThan(taskfile.V3) { return nil } @@ -214,14 +210,14 @@ func (e *Executor) readDotEnvFiles(v float64) error { return err } -func (e *Executor) setupDefaults(v float64) { +func (e *Executor) setupDefaults() { // Color available only on v3 - if v < 3 { + if e.Taskfile.Version.LessThan(taskfile.V3) { e.Logger.Color = false } if e.Taskfile.Method == "" { - if v >= 3 { + if e.Taskfile.Version.Compare(taskfile.V3) >= 0 { e.Taskfile.Method = "checksum" } else { e.Taskfile.Method = "timestamp" @@ -248,37 +244,41 @@ func (e *Executor) setupConcurrencyState() { } } -func (e *Executor) doVersionChecks(v float64) error { - if v < 2 { +func (e *Executor) doVersionChecks() error { + // Copy the version to avoid modifying the original + v := &semver.Version{} + *v = *e.Taskfile.Version + + if v.LessThan(taskfile.V2) { return fmt.Errorf(`task: Taskfile versions 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.Equal(taskfile.V2) { + v = semver.MustParse("2.6") } - if v == 3.0 { - v = 3.8 + if v.Equal(taskfile.V3) { + v = semver.MustParse("3.8") } - if v > 3.8 { + if v.GreaterThan(semver.MustParse("3.8")) { return fmt.Errorf(`task: Taskfile versions greater than v3.8 not implemented in the version of Task`) } - if v < 2.1 && !e.Taskfile.Output.IsSet() { + if v.LessThan(semver.MustParse("2.1")) && !e.Taskfile.Output.IsSet() { return fmt.Errorf(`task: Taskfile option "output" is only available starting on Taskfile version v2.1`) } - if v < 2.2 && e.Taskfile.Includes.Len() > 0 { + if v.LessThan(semver.MustParse("2.2")) && e.Taskfile.Includes.Len() > 0 { return fmt.Errorf(`task: Including Taskfiles is only available starting on Taskfile version v2.2`) } - if v >= 3.0 && e.Taskfile.Expansions > 2 { + if v.Compare(taskfile.V3) >= 0 && e.Taskfile.Expansions > 2 { return fmt.Errorf(`task: The "expansions" setting is not available anymore on v3.0`) } - if v < 3.8 && e.Taskfile.Output.Group.IsSet() { + if v.LessThan(semver.MustParse("3.8")) && e.Taskfile.Output.Group.IsSet() { return fmt.Errorf(`task: Taskfile option "output.group" is only available starting on Taskfile version v3.8`) } - if v <= 2.1 { + if v.Compare(semver.MustParse("2.1")) <= 0 { err := errors.New(`task: Taskfile option "ignore_error" is only available starting on Taskfile version v2.1`) for _, task := range e.Taskfile.Tasks { @@ -293,7 +293,7 @@ func (e *Executor) doVersionChecks(v float64) error { } } - if v < 2.6 { + if v.LessThan(semver.MustParse("2.6")) { for _, task := range e.Taskfile.Tasks { if len(task.Preconditions) > 0 { return errors.New(`task: Task option "preconditions" is only available starting on Taskfile version v2.6`) @@ -301,7 +301,7 @@ func (e *Executor) doVersionChecks(v float64) error { } } - if v < 3 { + if v.LessThan(taskfile.V3) { err := e.Taskfile.Includes.Range(func(_ string, taskfile taskfile.IncludedTaskfile) error { if taskfile.AdvancedImport { return errors.New(`task: Import with additional parameters is only available starting on Taskfile version v3`) @@ -313,7 +313,7 @@ func (e *Executor) doVersionChecks(v float64) error { } } - if v < 3.7 { + if v.LessThan(semver.MustParse("3.7")) { if e.Taskfile.Run != "" { return errors.New(`task: Setting the "run" type is only available starting on Taskfile version v3.7`) } diff --git a/task_test.go b/task_test.go index 9ba87e0a0b..8eaaf0e79f 100644 --- a/task_test.go +++ b/task_test.go @@ -11,6 +11,7 @@ import ( "strings" "testing" + "github.com/Masterminds/semver/v3" "github.com/stretchr/testify/assert" "github.com/go-task/task/v3" @@ -726,9 +727,9 @@ func TestCyclicDep(t *testing.T) { func TestTaskVersion(t *testing.T) { tests := []struct { Dir string - Version string + Version *semver.Version }{ - {"testdata/version/v2", "2"}, + {"testdata/version/v2", semver.MustParse("2")}, } for _, test := range tests { diff --git a/taskfile/merge.go b/taskfile/merge.go index 6c805ea986..e74d9da4a5 100644 --- a/taskfile/merge.go +++ b/taskfile/merge.go @@ -10,7 +10,7 @@ const NamespaceSeparator = ":" // Merge merges the second Taskfile into the first func Merge(t1, t2 *Taskfile, includedTaskfile *IncludedTaskfile, namespaces ...string) error { - if t1.Version != t2.Version { + if !t1.Version.Equal(t2.Version) { return fmt.Errorf(`task: Taskfiles versions should match. First is "%s" but second is "%s"`, t1.Version, t2.Version) } diff --git a/taskfile/read/taskfile.go b/taskfile/read/taskfile.go index 0db409e718..0f58f41a94 100644 --- a/taskfile/read/taskfile.go +++ b/taskfile/read/taskfile.go @@ -58,11 +58,6 @@ func Taskfile(readerNode *ReaderNode) (*taskfile.Taskfile, string, error) { return nil, "", err } - v, err := t.ParsedVersion() - if err != nil { - return nil, "", err - } - // Annotate any included Taskfile reference with a base directory for resolving relative paths _ = t.Includes.Range(func(key string, includedFile taskfile.IncludedTaskfile) error { // Set the base directory for resolving relative paths, but only if not already set @@ -74,7 +69,7 @@ func Taskfile(readerNode *ReaderNode) (*taskfile.Taskfile, string, error) { }) err = t.Includes.Range(func(namespace string, includedTask taskfile.IncludedTaskfile) error { - if v >= 3.0 { + if t.Version.Compare(taskfile.V3) >= 0 { tr := templater.Templater{Vars: t.Vars, RemoveNoValue: true} includedTask = taskfile.IncludedTaskfile{ Taskfile: tr.Replace(includedTask.Taskfile), @@ -123,7 +118,7 @@ func Taskfile(readerNode *ReaderNode) (*taskfile.Taskfile, string, error) { return err } - if v >= 3.0 && len(includedTaskfile.Dotenv) > 0 { + if t.Version.Compare(taskfile.V3) >= 0 && len(includedTaskfile.Dotenv) > 0 { return ErrIncludedTaskfilesCantHaveDotenvs } @@ -168,7 +163,7 @@ func Taskfile(readerNode *ReaderNode) (*taskfile.Taskfile, string, error) { return nil, "", err } - if v < 3.0 { + if t.Version.Compare(taskfile.V3) < 0 { path = filepathext.SmartJoin(readerNode.Dir, fmt.Sprintf("Taskfile_%s.yml", runtime.GOOS)) if _, err = os.Stat(path); err == nil { osTaskfile, err := readTaskfile(path) diff --git a/taskfile/taskfile.go b/taskfile/taskfile.go index 583677309e..9f2c177700 100644 --- a/taskfile/taskfile.go +++ b/taskfile/taskfile.go @@ -2,15 +2,20 @@ package taskfile import ( "fmt" - "strconv" "time" + "github.com/Masterminds/semver/v3" "gopkg.in/yaml.v3" ) +var ( + V3 = semver.MustParse("3") + V2 = semver.MustParse("2") +) + // Taskfile represents a Taskfile.yml type Taskfile struct { - Version string + Version *semver.Version Expansions int Output Output Method string @@ -31,7 +36,7 @@ func (tf *Taskfile) UnmarshalYAML(node *yaml.Node) error { case yaml.MappingNode: var taskfile struct { - Version string + Version *semver.Version Expansions int Output Output Method string @@ -77,12 +82,3 @@ func (tf *Taskfile) UnmarshalYAML(node *yaml.Node) error { return fmt.Errorf("yaml: line %d: cannot unmarshal %s into taskfile", node.Line, node.ShortTag()) } - -// ParsedVersion returns the version as a float64 -func (tf *Taskfile) ParsedVersion() (float64, error) { - v, err := strconv.ParseFloat(tf.Version, 64) - if err != nil { - return 0, fmt.Errorf(`task: Could not parse taskfile version "%s": %v`, tf.Version, err) - } - return v, nil -} diff --git a/variables.go b/variables.go index a1fa917aa2..4bb3492713 100644 --- a/variables.go +++ b/variables.go @@ -40,12 +40,7 @@ func (e *Executor) compiledTask(call taskfile.Call, evaluateShVars bool) (*taskf return nil, err } - v, err := e.Taskfile.ParsedVersion() - if err != nil { - return nil, err - } - - r := templater.Templater{Vars: vars, RemoveNoValue: v >= 3.0} + r := templater.Templater{Vars: vars, RemoveNoValue: e.Taskfile.Version.Compare(taskfile.V3) >= 0} new := taskfile.Task{ Task: origTask.Task,