Skip to content

Commit

Permalink
fix: run once in shared dependencies (#1655)
Browse files Browse the repository at this point in the history
* fix: run once in shared dependencies

* feat: add test
  • Loading branch information
pd93 authored Jun 28, 2024
1 parent a9ff58d commit 3aaa322
Show file tree
Hide file tree
Showing 13 changed files with 128 additions and 37 deletions.
7 changes: 2 additions & 5 deletions hash.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,12 @@ import (
"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 := t.Run
if r == "" {
r = e.Taskfile.Run
}

r := slicesext.FirstNonZero(t.Run, e.Taskfile.Run)
var h hash.HashFunc
switch r {
case "always":
Expand Down
2 changes: 1 addition & 1 deletion internal/hash/hash.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ func Empty(*ast.Task) (string, error) {
}

func Name(t *ast.Task) (string, error) {
return t.Task, nil
return fmt.Sprintf("%s:%s", t.Location.Taskfile, t.LocalName()), nil
}

func Hash(t *ast.Task) (string, error) {
Expand Down
10 changes: 10 additions & 0 deletions internal/slicesext/slicesext.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,13 @@ 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
}
20 changes: 20 additions & 0 deletions task_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1664,6 +1664,26 @@ func TestRunOnlyRunsJobsHashOnce(t *testing.T) {
tt.Run(t)
}

func TestRunOnceSharedDeps(t *testing.T) {
const dir = "testdata/run_once_shared_deps"

var buff bytes.Buffer
e := task.Executor{
Dir: dir,
Stdout: &buff,
Stderr: &buff,
ForceAll: true,
}
require.NoError(t, e.Setup())
require.NoError(t, e.Run(context.Background(), &ast.Call{Task: "build"}))

rx := regexp.MustCompile(`task: \[service-[a,b]:library:build\] echo "build library"`)
matches := rx.FindAllStringSubmatch(buff.String(), -1)
assert.Len(t, matches, 1)
assert.Contains(t, buff.String(), `task: [service-a:build] echo "build a"`)
assert.Contains(t, buff.String(), `task: [service-b:build] echo "build b"`)
}

func TestDeferredCmds(t *testing.T) {
const dir = "testdata/deferred"
var buff bytes.Buffer
Expand Down
68 changes: 39 additions & 29 deletions taskfile/ast/task.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,37 +13,39 @@ import (

// Task represents a task
type Task struct {
Task string
Cmds []*Cmd
Deps []*Dep
Label string
Desc string
Prompt string
Summary string
Requires *Requires
Aliases []string
Sources []*Glob
Generates []*Glob
Status []string
Preconditions []*Precondition
Dir string
Set []string
Shopt []string
Vars *Vars
Env *Vars
Dotenv []string
Silent bool
Interactive bool
Internal bool
Method string
Prefix string
IgnoreError bool
Run string
Task string
Cmds []*Cmd
Deps []*Dep
Label string
Desc string
Prompt string
Summary string
Requires *Requires
Aliases []string
Sources []*Glob
Generates []*Glob
Status []string
Preconditions []*Precondition
Dir string
Set []string
Shopt []string
Vars *Vars
Env *Vars
Dotenv []string
Silent bool
Interactive bool
Internal bool
Method string
Prefix string
IgnoreError bool
Run string
Platforms []*Platform
Watch bool
Location *Location
// Populated during merging
Namespace string
IncludeVars *Vars
IncludedTaskfileVars *Vars
Platforms []*Platform
Location *Location
Watch bool
}

func (t *Task) Name() string {
Expand All @@ -53,6 +55,13 @@ func (t *Task) Name() string {
return t.Task
}

func (t *Task) LocalName() string {
name := t.Task
name = strings.TrimPrefix(name, t.Namespace)
name = strings.TrimPrefix(name, ":")
return name
}

// WildcardMatch will check if the given string matches the name of the Task and returns any wildcard values.
func (t *Task) WildcardMatch(name string) (bool, []string) {
// Convert the name into a regex string
Expand Down Expand Up @@ -210,6 +219,7 @@ func (t *Task) DeepCopy() *Task {
Platforms: deepcopy.Slice(t.Platforms),
Location: t.Location.DeepCopy(),
Requires: t.Requires.DeepCopy(),
Namespace: t.Namespace,
}
return c
}
5 changes: 3 additions & 2 deletions taskfile/ast/tasks.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func (t *Tasks) FindMatchingTasks(call *Call) []*MatchingTask {
}

func (t1 *Tasks) Merge(t2 Tasks, include *Include, includedTaskfileVars *Vars) {
_ = t2.Range(func(k string, v *Task) error {
_ = t2.Range(func(name string, v *Task) error {
// We do a deep copy of the task struct here to ensure that no data can
// be changed elsewhere once the taskfile is merged.
task := v.DeepCopy()
Expand Down Expand Up @@ -95,7 +95,8 @@ func (t1 *Tasks) Merge(t2 Tasks, include *Include, includedTaskfileVars *Vars) {
}

// Add the task to the merged taskfile
taskNameWithNamespace := taskNameWithNamespace(k, include.Namespace)
taskNameWithNamespace := taskNameWithNamespace(name, include.Namespace)
task.Namespace = include.Namespace
task.Task = taskNameWithNamespace
t1.Set(taskNameWithNamespace, task)

Expand Down
11 changes: 11 additions & 0 deletions testdata/run_once_shared_deps/Taskfile.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
version: '3'

includes:
service-a: ./service-a
service-b: ./service-b

tasks:
build:
deps:
- service-a:build
- service-b:build
9 changes: 9 additions & 0 deletions testdata/run_once_shared_deps/library/Taskfile.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
version: '3'

tasks:
build:
run: once
cmds:
- echo "build library"
sources:
- src/**/*
15 changes: 15 additions & 0 deletions testdata/run_once_shared_deps/service-a/Taskfile.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
version: '3'

includes:
library:
taskfile: ../library/Taskfile.yml
dir: ../library

tasks:
build:
run: once
deps: [library:build]
cmds:
- echo "build a"
sources:
- src/**/*
1 change: 1 addition & 0 deletions testdata/run_once_shared_deps/service-a/src/imasource.go
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package main
15 changes: 15 additions & 0 deletions testdata/run_once_shared_deps/service-b/Taskfile.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
version: '3'

includes:
library:
taskfile: ../library/Taskfile.yml
dir: ../library

tasks:
build:
run: once
deps: [library:build]
cmds:
- echo "build b"
sources:
- src/**/*
1 change: 1 addition & 0 deletions testdata/run_once_shared_deps/service-b/src/imasource.go
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package main
1 change: 1 addition & 0 deletions variables.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ func (e *Executor) compiledTask(call *ast.Call, evaluateShVars bool) (*ast.Task,
Location: origTask.Location,
Requires: origTask.Requires,
Watch: origTask.Watch,
Namespace: origTask.Namespace,
}
new.Dir, err = execext.Expand(new.Dir)
if err != nil {
Expand Down

0 comments on commit 3aaa322

Please sign in to comment.