mirror of
https://github.com/go-task/task.git
synced 2024-12-12 10:45:49 +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"
|
||||
|
||||
"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":
|
||||
|
@ -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) {
|
||||
|
@ -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
task_test.go
20
task_test.go
@ -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
|
||||
|
@ -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 {
|
||||
@ -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
|
||||
@ -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
|
||||
}
|
||||
|
@ -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()
|
||||
@ -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)
|
||||
|
||||
|
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,
|
||||
Requires: origTask.Requires,
|
||||
Watch: origTask.Watch,
|
||||
Namespace: origTask.Namespace,
|
||||
}
|
||||
new.Dir, err = execext.Expand(new.Dir)
|
||||
if err != nil {
|
||||
|
Loading…
Reference in New Issue
Block a user