Skip to content

Commit 3aaa322

Browse files
authored
fix: run once in shared dependencies (#1655)
* fix: run once in shared dependencies * feat: add test
1 parent a9ff58d commit 3aaa322

File tree

13 files changed

+128
-37
lines changed

13 files changed

+128
-37
lines changed

hash.go

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,12 @@ import (
44
"fmt"
55

66
"github.com/go-task/task/v3/internal/hash"
7+
"github.com/go-task/task/v3/internal/slicesext"
78
"github.com/go-task/task/v3/taskfile/ast"
89
)
910

1011
func (e *Executor) GetHash(t *ast.Task) (string, error) {
11-
r := t.Run
12-
if r == "" {
13-
r = e.Taskfile.Run
14-
}
15-
12+
r := slicesext.FirstNonZero(t.Run, e.Taskfile.Run)
1613
var h hash.HashFunc
1714
switch r {
1815
case "always":

internal/hash/hash.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ func Empty(*ast.Task) (string, error) {
1515
}
1616

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

2121
func Hash(t *ast.Task) (string, error) {

internal/slicesext/slicesext.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,13 @@ func UniqueJoin[T cmp.Ordered](ss ...[]T) []T {
1818
slices.Sort(r)
1919
return slices.Compact(r)
2020
}
21+
22+
func FirstNonZero[T comparable](values ...T) T {
23+
var zero T
24+
for _, v := range values {
25+
if v != zero {
26+
return v
27+
}
28+
}
29+
return zero
30+
}

task_test.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1664,6 +1664,26 @@ func TestRunOnlyRunsJobsHashOnce(t *testing.T) {
16641664
tt.Run(t)
16651665
}
16661666

1667+
func TestRunOnceSharedDeps(t *testing.T) {
1668+
const dir = "testdata/run_once_shared_deps"
1669+
1670+
var buff bytes.Buffer
1671+
e := task.Executor{
1672+
Dir: dir,
1673+
Stdout: &buff,
1674+
Stderr: &buff,
1675+
ForceAll: true,
1676+
}
1677+
require.NoError(t, e.Setup())
1678+
require.NoError(t, e.Run(context.Background(), &ast.Call{Task: "build"}))
1679+
1680+
rx := regexp.MustCompile(`task: \[service-[a,b]:library:build\] echo "build library"`)
1681+
matches := rx.FindAllStringSubmatch(buff.String(), -1)
1682+
assert.Len(t, matches, 1)
1683+
assert.Contains(t, buff.String(), `task: [service-a:build] echo "build a"`)
1684+
assert.Contains(t, buff.String(), `task: [service-b:build] echo "build b"`)
1685+
}
1686+
16671687
func TestDeferredCmds(t *testing.T) {
16681688
const dir = "testdata/deferred"
16691689
var buff bytes.Buffer

taskfile/ast/task.go

Lines changed: 39 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -13,37 +13,39 @@ import (
1313

1414
// Task represents a task
1515
type Task struct {
16-
Task string
17-
Cmds []*Cmd
18-
Deps []*Dep
19-
Label string
20-
Desc string
21-
Prompt string
22-
Summary string
23-
Requires *Requires
24-
Aliases []string
25-
Sources []*Glob
26-
Generates []*Glob
27-
Status []string
28-
Preconditions []*Precondition
29-
Dir string
30-
Set []string
31-
Shopt []string
32-
Vars *Vars
33-
Env *Vars
34-
Dotenv []string
35-
Silent bool
36-
Interactive bool
37-
Internal bool
38-
Method string
39-
Prefix string
40-
IgnoreError bool
41-
Run string
16+
Task string
17+
Cmds []*Cmd
18+
Deps []*Dep
19+
Label string
20+
Desc string
21+
Prompt string
22+
Summary string
23+
Requires *Requires
24+
Aliases []string
25+
Sources []*Glob
26+
Generates []*Glob
27+
Status []string
28+
Preconditions []*Precondition
29+
Dir string
30+
Set []string
31+
Shopt []string
32+
Vars *Vars
33+
Env *Vars
34+
Dotenv []string
35+
Silent bool
36+
Interactive bool
37+
Internal bool
38+
Method string
39+
Prefix string
40+
IgnoreError bool
41+
Run string
42+
Platforms []*Platform
43+
Watch bool
44+
Location *Location
45+
// Populated during merging
46+
Namespace string
4247
IncludeVars *Vars
4348
IncludedTaskfileVars *Vars
44-
Platforms []*Platform
45-
Location *Location
46-
Watch bool
4749
}
4850

4951
func (t *Task) Name() string {
@@ -53,6 +55,13 @@ func (t *Task) Name() string {
5355
return t.Task
5456
}
5557

58+
func (t *Task) LocalName() string {
59+
name := t.Task
60+
name = strings.TrimPrefix(name, t.Namespace)
61+
name = strings.TrimPrefix(name, ":")
62+
return name
63+
}
64+
5665
// WildcardMatch will check if the given string matches the name of the Task and returns any wildcard values.
5766
func (t *Task) WildcardMatch(name string) (bool, []string) {
5867
// Convert the name into a regex string
@@ -210,6 +219,7 @@ func (t *Task) DeepCopy() *Task {
210219
Platforms: deepcopy.Slice(t.Platforms),
211220
Location: t.Location.DeepCopy(),
212221
Requires: t.Requires.DeepCopy(),
222+
Namespace: t.Namespace,
213223
}
214224
return c
215225
}

taskfile/ast/tasks.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ func (t *Tasks) FindMatchingTasks(call *Call) []*MatchingTask {
4747
}
4848

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

9797
// Add the task to the merged taskfile
98-
taskNameWithNamespace := taskNameWithNamespace(k, include.Namespace)
98+
taskNameWithNamespace := taskNameWithNamespace(name, include.Namespace)
99+
task.Namespace = include.Namespace
99100
task.Task = taskNameWithNamespace
100101
t1.Set(taskNameWithNamespace, task)
101102

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
version: '3'
2+
3+
includes:
4+
service-a: ./service-a
5+
service-b: ./service-b
6+
7+
tasks:
8+
build:
9+
deps:
10+
- service-a:build
11+
- service-b:build
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
version: '3'
2+
3+
tasks:
4+
build:
5+
run: once
6+
cmds:
7+
- echo "build library"
8+
sources:
9+
- src/**/*
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
version: '3'
2+
3+
includes:
4+
library:
5+
taskfile: ../library/Taskfile.yml
6+
dir: ../library
7+
8+
tasks:
9+
build:
10+
run: once
11+
deps: [library:build]
12+
cmds:
13+
- echo "build a"
14+
sources:
15+
- src/**/*
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
package main

0 commit comments

Comments
 (0)