mirror of
https://github.com/go-task/task.git
synced 2025-01-06 03:53:54 +02:00
fix: run once in shared dependencies (#1655)
* fix: run once in shared dependencies * feat: add test
This commit is contained in:
parent
a9ff58d0fe
commit
3aaa3223a0
7
hash.go
7
hash.go
@ -4,15 +4,12 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/go-task/task/v3/internal/hash"
|
"github.com/go-task/task/v3/internal/hash"
|
||||||
|
"github.com/go-task/task/v3/internal/slicesext"
|
||||||
"github.com/go-task/task/v3/taskfile/ast"
|
"github.com/go-task/task/v3/taskfile/ast"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (e *Executor) GetHash(t *ast.Task) (string, error) {
|
func (e *Executor) GetHash(t *ast.Task) (string, error) {
|
||||||
r := t.Run
|
r := slicesext.FirstNonZero(t.Run, e.Taskfile.Run)
|
||||||
if r == "" {
|
|
||||||
r = e.Taskfile.Run
|
|
||||||
}
|
|
||||||
|
|
||||||
var h hash.HashFunc
|
var h hash.HashFunc
|
||||||
switch r {
|
switch r {
|
||||||
case "always":
|
case "always":
|
||||||
|
@ -15,7 +15,7 @@ func Empty(*ast.Task) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Name(t *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) {
|
func Hash(t *ast.Task) (string, error) {
|
||||||
|
@ -18,3 +18,13 @@ func UniqueJoin[T cmp.Ordered](ss ...[]T) []T {
|
|||||||
slices.Sort(r)
|
slices.Sort(r)
|
||||||
return slices.Compact(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
task_test.go
20
task_test.go
@ -1664,6 +1664,26 @@ func TestRunOnlyRunsJobsHashOnce(t *testing.T) {
|
|||||||
tt.Run(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) {
|
func TestDeferredCmds(t *testing.T) {
|
||||||
const dir = "testdata/deferred"
|
const dir = "testdata/deferred"
|
||||||
var buff bytes.Buffer
|
var buff bytes.Buffer
|
||||||
|
@ -39,11 +39,13 @@ type Task struct {
|
|||||||
Prefix string
|
Prefix string
|
||||||
IgnoreError bool
|
IgnoreError bool
|
||||||
Run string
|
Run string
|
||||||
|
Platforms []*Platform
|
||||||
|
Watch bool
|
||||||
|
Location *Location
|
||||||
|
// Populated during merging
|
||||||
|
Namespace string
|
||||||
IncludeVars *Vars
|
IncludeVars *Vars
|
||||||
IncludedTaskfileVars *Vars
|
IncludedTaskfileVars *Vars
|
||||||
Platforms []*Platform
|
|
||||||
Location *Location
|
|
||||||
Watch bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Task) Name() string {
|
func (t *Task) Name() string {
|
||||||
@ -53,6 +55,13 @@ func (t *Task) Name() string {
|
|||||||
return t.Task
|
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.
|
// 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) {
|
func (t *Task) WildcardMatch(name string) (bool, []string) {
|
||||||
// Convert the name into a regex string
|
// Convert the name into a regex string
|
||||||
@ -210,6 +219,7 @@ func (t *Task) DeepCopy() *Task {
|
|||||||
Platforms: deepcopy.Slice(t.Platforms),
|
Platforms: deepcopy.Slice(t.Platforms),
|
||||||
Location: t.Location.DeepCopy(),
|
Location: t.Location.DeepCopy(),
|
||||||
Requires: t.Requires.DeepCopy(),
|
Requires: t.Requires.DeepCopy(),
|
||||||
|
Namespace: t.Namespace,
|
||||||
}
|
}
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ func (t *Tasks) FindMatchingTasks(call *Call) []*MatchingTask {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t1 *Tasks) Merge(t2 Tasks, include *Include, includedTaskfileVars *Vars) {
|
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
|
// We do a deep copy of the task struct here to ensure that no data can
|
||||||
// be changed elsewhere once the taskfile is merged.
|
// be changed elsewhere once the taskfile is merged.
|
||||||
task := v.DeepCopy()
|
task := v.DeepCopy()
|
||||||
@ -95,7 +95,8 @@ func (t1 *Tasks) Merge(t2 Tasks, include *Include, includedTaskfileVars *Vars) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add the task to the merged taskfile
|
// Add the task to the merged taskfile
|
||||||
taskNameWithNamespace := taskNameWithNamespace(k, include.Namespace)
|
taskNameWithNamespace := taskNameWithNamespace(name, include.Namespace)
|
||||||
|
task.Namespace = include.Namespace
|
||||||
task.Task = taskNameWithNamespace
|
task.Task = taskNameWithNamespace
|
||||||
t1.Set(taskNameWithNamespace, task)
|
t1.Set(taskNameWithNamespace, task)
|
||||||
|
|
||||||
|
11
testdata/run_once_shared_deps/Taskfile.yml
vendored
Normal file
11
testdata/run_once_shared_deps/Taskfile.yml
vendored
Normal file
@ -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
testdata/run_once_shared_deps/library/Taskfile.yml
vendored
Normal file
9
testdata/run_once_shared_deps/library/Taskfile.yml
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
version: '3'
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
build:
|
||||||
|
run: once
|
||||||
|
cmds:
|
||||||
|
- echo "build library"
|
||||||
|
sources:
|
||||||
|
- src/**/*
|
15
testdata/run_once_shared_deps/service-a/Taskfile.yml
vendored
Normal file
15
testdata/run_once_shared_deps/service-a/Taskfile.yml
vendored
Normal file
@ -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
testdata/run_once_shared_deps/service-a/src/imasource.go
vendored
Normal file
1
testdata/run_once_shared_deps/service-a/src/imasource.go
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
package main
|
15
testdata/run_once_shared_deps/service-b/Taskfile.yml
vendored
Normal file
15
testdata/run_once_shared_deps/service-b/Taskfile.yml
vendored
Normal file
@ -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
testdata/run_once_shared_deps/service-b/src/imasource.go
vendored
Normal file
1
testdata/run_once_shared_deps/service-b/src/imasource.go
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
package main
|
@ -72,6 +72,7 @@ func (e *Executor) compiledTask(call *ast.Call, evaluateShVars bool) (*ast.Task,
|
|||||||
Location: origTask.Location,
|
Location: origTask.Location,
|
||||||
Requires: origTask.Requires,
|
Requires: origTask.Requires,
|
||||||
Watch: origTask.Watch,
|
Watch: origTask.Watch,
|
||||||
|
Namespace: origTask.Namespace,
|
||||||
}
|
}
|
||||||
new.Dir, err = execext.Expand(new.Dir)
|
new.Dir, err = execext.Expand(new.Dir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Loading…
Reference in New Issue
Block a user