diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index c9acea3b..d7361f60 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -13,7 +13,7 @@ jobs: name: Lint strategy: matrix: - go-version: [1.21.x, 1.22.x] + go-version: [1.22.x, 1.23.x] runs-on: ubuntu-latest steps: - uses: actions/setup-go@v5 @@ -25,7 +25,7 @@ jobs: - name: golangci-lint uses: golangci/golangci-lint-action@v6 with: - version: v1.55.2 + version: v1.60.1 lint-jsonschema: runs-on: ubuntu-latest diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index fa1c98ab..ff8ab1a2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -15,7 +15,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v5 with: - go-version: 1.21.x + go-version: 1.22.x - name: Run GoReleaser uses: goreleaser/goreleaser-action@v2 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index af5f33c2..f9d2ccfd 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -13,7 +13,7 @@ jobs: name: Test strategy: matrix: - go-version: [1.21.x, 1.22.x] + go-version: [1.22.x, 1.23.x] platform: [ubuntu-latest, macos-latest, windows-latest] runs-on: ${{matrix.platform}} steps: diff --git a/go.mod b/go.mod index 6d60bc1a..4483844b 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/go-task/task/v3 -go 1.21.0 +go 1.22.0 require ( github.com/Ladicle/tabwriter v1.0.0 diff --git a/hash.go b/hash.go index 2a0632c2..af49a804 100644 --- a/hash.go +++ b/hash.go @@ -1,15 +1,15 @@ package task import ( + "cmp" "fmt" "github.com/go-task/task/v3/internal/hash" - "github.com/go-task/task/v3/internal/slicesext" "github.com/go-task/task/v3/taskfile/ast" ) func (e *Executor) GetHash(t *ast.Task) (string, error) { - r := slicesext.FirstNonZero(t.Run, e.Taskfile.Run) + r := cmp.Or(t.Run, e.Taskfile.Run) var h hash.HashFunc switch r { case "always": diff --git a/help.go b/help.go index f1bb339d..622ef17b 100644 --- a/help.go +++ b/help.go @@ -160,23 +160,21 @@ func (e *Executor) ToEditorOutput(tasks []*ast.Task, noStatus bool) (*editors.Ta } var g errgroup.Group for i := range tasks { - task := tasks[i] - j := i aliases := []string{} - if len(task.Aliases) > 0 { - aliases = task.Aliases + if len(tasks[i].Aliases) > 0 { + aliases = tasks[i].Aliases } g.Go(func() error { - o.Tasks[j] = editors.Task{ - Name: task.Name(), - Desc: task.Desc, - Summary: task.Summary, + o.Tasks[i] = editors.Task{ + Name: tasks[i].Name(), + Desc: tasks[i].Desc, + Summary: tasks[i].Summary, Aliases: aliases, UpToDate: false, Location: &editors.Location{ - Line: task.Location.Line, - Column: task.Location.Column, - Taskfile: task.Location.Taskfile, + Line: tasks[i].Location.Line, + Column: tasks[i].Location.Column, + Taskfile: tasks[i].Location.Taskfile, }, } @@ -186,10 +184,10 @@ func (e *Executor) ToEditorOutput(tasks []*ast.Task, noStatus bool) (*editors.Ta // Get the fingerprinting method to use method := e.Taskfile.Method - if task.Method != "" { - method = task.Method + if tasks[i].Method != "" { + method = tasks[i].Method } - upToDate, err := fingerprint.IsTaskUpToDate(context.Background(), task, + upToDate, err := fingerprint.IsTaskUpToDate(context.Background(), tasks[i], fingerprint.WithMethod(method), fingerprint.WithTempDir(e.TempDir.Fingerprint), fingerprint.WithDry(e.Dry), @@ -199,7 +197,7 @@ func (e *Executor) ToEditorOutput(tasks []*ast.Task, noStatus bool) (*editors.Ta return err } - o.Tasks[j].UpToDate = upToDate + o.Tasks[i].UpToDate = upToDate return nil }) diff --git a/internal/deepcopy/deepcopy.go b/internal/deepcopy/deepcopy.go index 261d443e..8305755b 100644 --- a/internal/deepcopy/deepcopy.go +++ b/internal/deepcopy/deepcopy.go @@ -85,7 +85,7 @@ func TraverseStringsFunc[T any](v T, fn func(v string) (string, error)) (T, erro case reflect.Struct: // Loop over each field and call traverseFunc recursively - for i := 0; i < v.NumField(); i += 1 { + for i := range v.NumField() { if err := traverseFunc(copy.Field(i), v.Field(i)); err != nil { return err } @@ -95,7 +95,7 @@ func TraverseStringsFunc[T any](v T, fn func(v string) (string, error)) (T, erro // Create an empty copy from the original value's type copy.Set(reflect.MakeSlice(v.Type(), v.Len(), v.Cap())) // Loop over each element and call traverseFunc recursively - for i := 0; i < v.Len(); i += 1 { + for i := range v.Len() { if err := traverseFunc(copy.Index(i), v.Index(i)); err != nil { return err } diff --git a/internal/logger/logger.go b/internal/logger/logger.go index e5155b2a..0a276b00 100644 --- a/internal/logger/logger.go +++ b/internal/logger/logger.go @@ -89,7 +89,7 @@ func envColor(env string, defaultColor color.Attribute) []color.Attribute { // Otherwise, split by semicolons (ANSI color codes) and use them as is. attributeStrs := strings.Split(override, ",") if len(attributeStrs) == 3 { - attributeStrs = append([]string{"38", "2"}, attributeStrs...) + attributeStrs = slices.Concat([]string{"38", "2"}, attributeStrs) } else { attributeStrs = strings.Split(override, ";") } diff --git a/internal/slicesext/slicesext.go b/internal/slicesext/slicesext.go index b3149a23..8b539bc8 100644 --- a/internal/slicesext/slicesext.go +++ b/internal/slicesext/slicesext.go @@ -18,13 +18,3 @@ func UniqueJoin[T cmp.Ordered](ss ...[]T) []T { slices.Sort(r) return slices.Compact(r) } - -func FirstNonZero[T comparable](values ...T) T { - var zero T - for _, v := range values { - if v != zero { - return v - } - } - return zero -} diff --git a/requires.go b/requires.go index 5462f900..b07f7f66 100644 --- a/requires.go +++ b/requires.go @@ -1,13 +1,11 @@ package task import ( - "context" - "github.com/go-task/task/v3/errors" "github.com/go-task/task/v3/taskfile/ast" ) -func (e *Executor) areTaskRequiredVarsSet(ctx context.Context, t *ast.Task, call *ast.Call) error { +func (e *Executor) areTaskRequiredVarsSet(t *ast.Task, call *ast.Call) error { if t.Requires == nil || len(t.Requires.Vars) == 0 { return nil } diff --git a/setup.go b/setup.go index a6eb772d..c745ebfb 100644 --- a/setup.go +++ b/setup.go @@ -5,6 +5,7 @@ import ( "fmt" "os" "path/filepath" + "slices" "strings" "sync" @@ -95,7 +96,7 @@ func (e *Executor) setupFuzzyModel() { words = append(words, taskName) for _, task := range e.Taskfile.Tasks.Values() { - words = append(words, task.Aliases...) + words = slices.Concat(words, task.Aliases) } } diff --git a/signals.go b/signals.go index 8d2e55b2..6f908472 100644 --- a/signals.go +++ b/signals.go @@ -8,24 +8,25 @@ import ( "github.com/go-task/task/v3/internal/logger" ) +const interruptSignalsCount = 3 + // NOTE(@andreynering): This function intercepts SIGINT and SIGTERM signals // so the Task process is not killed immediately and processes running have // time to do cleanup work. func (e *Executor) InterceptInterruptSignals() { - ch := make(chan os.Signal, 3) + ch := make(chan os.Signal, interruptSignalsCount) signal.Notify(ch, os.Interrupt, syscall.SIGTERM) go func() { - for i := 1; i <= 3; i++ { + for i := range interruptSignalsCount { sig := <-ch - if i < 3 { - e.Logger.Outf(logger.Yellow, "task: Signal received: %q\n", sig) - continue + if i+1 >= interruptSignalsCount { + e.Logger.Errf(logger.Red, "task: Signal received for the third time: %q. Forcing shutdown\n", sig) + os.Exit(1) } - e.Logger.Errf(logger.Red, "task: Signal received for the third time: %q. Forcing shutdown\n", sig) - os.Exit(1) + e.Logger.Outf(logger.Yellow, "task: Signal received: %q\n", sig) } }() } diff --git a/signals_test.go b/signals_test.go index acfacb51..6faa8aef 100644 --- a/signals_test.go +++ b/signals_test.go @@ -20,9 +20,7 @@ import ( "time" ) -var ( - SLEEPIT, _ = filepath.Abs("./bin/sleepit") -) +var SLEEPIT, _ = filepath.Abs("./bin/sleepit") func TestSignalSentToProcessGroup(t *testing.T) { task, err := getTaskPath() @@ -147,7 +145,7 @@ func TestSignalSentToProcessGroup(t *testing.T) { // where the negative PID means the corresponding process group. Note that // this negative PID works only as long as the caller of the kill(2) system // call has a different PID, which is the case for this test. - for i := 1; i <= tc.sendSigs; i++ { + for range tc.sendSigs - 1 { if err := syscall.Kill(-sut.Process.Pid, syscall.SIGINT); err != nil { t.Fatalf("sending INT signal to the process group: %v", err) } diff --git a/task.go b/task.go index 516ee204..0f03ba0d 100644 --- a/task.go +++ b/task.go @@ -200,7 +200,7 @@ func (e *Executor) RunTask(ctx context.Context, call *ast.Call) error { return err } - if err := e.areTaskRequiredVarsSet(ctx, t, call); err != nil { + if err := e.areTaskRequiredVarsSet(t, call); err != nil { return err } @@ -494,14 +494,12 @@ func (e *Executor) GetTaskList(filters ...FilterFunc) ([]*ast.Task, error) { // Compile the list of tasks for i := range tasks { - idx := i - task := tasks[idx] g.Go(func() error { - compiledTask, err := e.FastCompiledTask(&ast.Call{Task: task.Task}) + compiledTask, err := e.FastCompiledTask(&ast.Call{Task: tasks[i].Task}) if err != nil { return err } - tasks[idx] = compiledTask + tasks[i] = compiledTask return nil }) } diff --git a/task_test.go b/task_test.go index 90a2ac14..751c87bd 100644 --- a/task_test.go +++ b/task_test.go @@ -825,7 +825,8 @@ func TestListDescInterpolation(t *testing.T) { t.Error(err) } - assert.Contains(t, buff.String(), "bar") + assert.Contains(t, buff.String(), "foo-var") + assert.Contains(t, buff.String(), "bar-var") } func TestStatusVariables(t *testing.T) { diff --git a/taskfile/ast/tasks.go b/taskfile/ast/tasks.go index b4c3951a..b49a9a09 100644 --- a/taskfile/ast/tasks.go +++ b/taskfile/ast/tasks.go @@ -2,6 +2,7 @@ package ast import ( "fmt" + "slices" "strings" "gopkg.in/yaml.v3" @@ -111,7 +112,7 @@ func (t1 *Tasks) Merge(t2 Tasks, include *Include, includedTaskfileVars *Vars) { if t2.Get("default") != nil && t1.Get(include.Namespace) == nil { defaultTaskName := fmt.Sprintf("%s:default", include.Namespace) t1.Get(defaultTaskName).Aliases = append(t1.Get(defaultTaskName).Aliases, include.Namespace) - t1.Get(defaultTaskName).Aliases = append(t1.Get(defaultTaskName).Aliases, include.Aliases...) + t1.Get(defaultTaskName).Aliases = slices.Concat(t1.Get(defaultTaskName).Aliases, include.Aliases) } } diff --git a/testdata/list_desc_interpolation/Taskfile.yml b/testdata/list_desc_interpolation/Taskfile.yml index 63c0bd10..48bf44db 100644 --- a/testdata/list_desc_interpolation/Taskfile.yml +++ b/testdata/list_desc_interpolation/Taskfile.yml @@ -1,8 +1,12 @@ version: '3' vars: - FOO: bar + FOO: foo + BAR: bar tasks: foo: - desc: "task has desc with {{.FOO}} var" + desc: "task has desc with {{.FOO}}-var" + + bar: + desc: "task has desc with {{.BAR}}-var" diff --git a/variables.go b/variables.go index d69764c7..22b9d9d0 100644 --- a/variables.go +++ b/variables.go @@ -266,7 +266,7 @@ func itemsFromFor( var keys []string // The list of keys to loop over (only if looping over a map) var values []any // The list of values to loop over // Get the list from the explicit for list - if f.List != nil && len(f.List) > 0 { + if len(f.List) > 0 { values = f.List } // Get the list from the task sources