Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 43 additions & 43 deletions internal/flags/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,49 +44,49 @@
`

var (
Version bool
Help bool
Init bool
Completion string
List bool
ListAll bool
ListJson bool
TaskSort string
Status bool
NoStatus bool
Nested bool
Insecure bool
Force bool
ForceAll bool
Watch bool
Verbose bool
Silent bool
DisableFuzzy bool
AssumeYes bool
Dry bool
Summary bool
ExitCode bool
Parallel bool
Concurrency int
Dir string
Entrypoint string
Output ast.Output
Color bool
Interval time.Duration
Failfast bool
Global bool
Experiments bool
Download bool
Offline bool
TrustedHosts []string
ClearCache bool
Timeout time.Duration
CacheExpiryDuration time.Duration
RemoteCacheDir string
CACert string
Cert string
CertKey string
Interactive bool
Version bool

Check failure on line 47 in internal/flags/flags.go

View workflow job for this annotation

GitHub Actions / Lint (1.26.x)

File is not properly formatted (gci)

Check failure on line 47 in internal/flags/flags.go

View workflow job for this annotation

GitHub Actions / Lint (1.25.x)

File is not properly formatted (gci)
Help bool
Init bool
Completion string
List bool
ListAll bool
ListJson bool
TaskSort string
Status bool
NoStatus bool
Nested bool
Insecure bool
Force bool
ForceAll bool
Watch bool
Verbose bool
Silent bool
DisableFuzzy bool
AssumeYes bool
Dry bool
Summary bool
ExitCode bool
Parallel bool
Concurrency int
Dir string
Entrypoint string
Output ast.Output
Color bool
Interval time.Duration
Failfast bool
Global bool
Experiments bool
Download bool
Offline bool
TrustedHosts []string
ClearCache bool
Timeout time.Duration
CacheExpiryDuration time.Duration
RemoteCacheDir string
CACert string
Cert string
CertKey string
Interactive bool
)

func init() {
Expand Down
21 changes: 18 additions & 3 deletions task.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import (
"context"
stderrors "errors"

Check failure on line 5 in task.go

View workflow job for this annotation

GitHub Actions / Lint (1.26.x)

import 'errors' is not allowed from list 'main': Use github.com/go-task/task/v3/errors instead (depguard)

Check failure on line 5 in task.go

View workflow job for this annotation

GitHub Actions / Lint (1.25.x)

import 'errors' is not allowed from list 'main': Use github.com/go-task/task/v3/errors instead (depguard)
"fmt"
"os"
"runtime"
Expand All @@ -25,6 +26,8 @@
"github.com/go-task/task/v3/taskfile/ast"
)

var errSharedExecutionSuccess = stderrors.New("shared execution succeeded")

const (
// MaximumTaskCall is the max number of times a task can be called.
// This exists to prevent infinite loops on cyclic dependencies
Expand Down Expand Up @@ -456,16 +459,28 @@
defer reacquire()

<-otherExecutionCtx.Done()

if cause := context.Cause(otherExecutionCtx); cause != nil && cause != errSharedExecutionSuccess {
return cause
}
return nil
}

ctx, cancel := context.WithCancel(ctx)
defer cancel()
ctx, cancel := context.WithCancelCause(ctx)
defer func() {
if err != nil {
cancel(err)
} else {
cancel(errSharedExecutionSuccess)
}
}()

e.executionHashes[h] = ctx
e.executionHashesMutex.Unlock()

return execute(ctx)
// Save err in variable so it also applied to the cancel defer
err = execute(ctx)
return err
}

// FindMatchingTasks returns a list of tasks that match the given call. A task
Expand Down
25 changes: 25 additions & 0 deletions task_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1952,6 +1952,31 @@ func TestRunOnceSharedDeps(t *testing.T) {
assert.Contains(t, buff.String(), `task: [service-b:build] echo "build b"`)
}

func TestRunOnceSharedDepsFail(t *testing.T) {
t.Parallel()

const dir = "testdata/run_once_shared_deps_fail"

var buff bytes.Buffer
e := task.NewExecutor(
task.WithDir(dir),
task.WithStdout(&buff),
task.WithStderr(&buff),
task.WithForceAll(true),
)
require.NoError(t, e.Setup())
require.Error(t, e.Run(t.Context(), &task.Call{Task: "build"}))

// The shared dependency should still only be attempted once.
rx := regexp.MustCompile(`task: \[service-[a,b]:library:build\] echo "build library" && exit 1`)
matches := rx.FindAllStringSubmatch(buff.String(), -1)
assert.Len(t, matches, 1)

// If the shared dependency fails, both branches must be blocked from running their own commands.
assert.NotContains(t, buff.String(), `task: [service-a:build] echo "build a"`)
assert.NotContains(t, buff.String(), `task: [service-b:build] echo "build b"`)
}

func TestRunWhenChanged(t *testing.T) {
t.Parallel()

Expand Down
13 changes: 13 additions & 0 deletions testdata/run_once_shared_deps_fail/Taskfile.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
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_fail/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" && exit 1


15 changes: 15 additions & 0 deletions testdata/run_once_shared_deps_fail/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"


13 changes: 13 additions & 0 deletions testdata/run_once_shared_deps_fail/service-b/Taskfile.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
version: '3'

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

tasks:
build:
run: once
deps: [library:build]
cmds:
- echo "build b"
Loading