Skip to content

Commit a84f09d

Browse files
authored
feat: remote taskfile improvements (cache/expiry) (#2176)
* feat: cache as node, RemoteNode and cache-first approach * feat: cache expiry * feat: pass ctx into reader methods instead of timeout * docs: updated remote taskfiles experiment doc * feat: use cache if download fails
1 parent f47f237 commit a84f09d

File tree

18 files changed

+570
-344
lines changed

18 files changed

+570
-344
lines changed

cmd/task/task.go

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import (
1818
"github.com/go-task/task/v3/internal/flags"
1919
"github.com/go-task/task/v3/internal/logger"
2020
"github.com/go-task/task/v3/internal/version"
21-
"github.com/go-task/task/v3/taskfile"
2221
"github.com/go-task/task/v3/taskfile/ast"
2322
)
2423

@@ -121,18 +120,9 @@ func run() error {
121120
return err
122121
}
123122

124-
// If the download flag is specified, we should stop execution as soon as
125-
// taskfile is downloaded
126-
if flags.Download {
127-
return nil
128-
}
129-
130123
if flags.ClearCache {
131-
cache, err := taskfile.NewCache(e.TempDir.Remote)
132-
if err != nil {
133-
return err
134-
}
135-
return cache.Clear()
124+
cachePath := filepath.Join(e.TempDir.Remote, "remote")
125+
return os.RemoveAll(cachePath)
136126
}
137127

138128
listOptions := task.NewListOptions(

cmd/tmp/main.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"net/http"
7+
"time"
8+
)
9+
10+
func main() {
11+
ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond)
12+
defer cancel()
13+
if err := run(ctx); err != nil {
14+
fmt.Println(ctx.Err())
15+
fmt.Println(err)
16+
}
17+
}
18+
19+
func run(ctx context.Context) error {
20+
req, err := http.NewRequest("GET", "https://taskfile.dev/schema.json", nil)
21+
if err != nil {
22+
fmt.Println(1)
23+
return err
24+
}
25+
26+
resp, err := http.DefaultClient.Do(req.WithContext(ctx))
27+
if err != nil {
28+
if ctx.Err() != nil {
29+
fmt.Println(2)
30+
return err
31+
}
32+
fmt.Println(3)
33+
return err
34+
}
35+
defer resp.Body.Close()
36+
37+
return nil
38+
}

errors/errors_taskfile.go

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -155,19 +155,14 @@ func (err *TaskfileVersionCheckError) Code() int {
155155
// TaskfileNetworkTimeoutError is returned when the user attempts to use a remote
156156
// Taskfile but a network connection could not be established within the timeout.
157157
type TaskfileNetworkTimeoutError struct {
158-
URI string
159-
Timeout time.Duration
160-
CheckedCache bool
158+
URI string
159+
Timeout time.Duration
161160
}
162161

163162
func (err *TaskfileNetworkTimeoutError) Error() string {
164-
var cacheText string
165-
if err.CheckedCache {
166-
cacheText = " and no offline copy was found in the cache"
167-
}
168163
return fmt.Sprintf(
169-
`task: Network connection timed out after %s while attempting to download Taskfile %q%s`,
170-
err.Timeout, err.URI, cacheText,
164+
`task: Network connection timed out after %s while attempting to download Taskfile %q`,
165+
err.Timeout, err.URI,
171166
)
172167
}
173168

executor.go

Lines changed: 35 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -27,26 +27,27 @@ type (
2727
// within them.
2828
Executor struct {
2929
// Flags
30-
Dir string
31-
Entrypoint string
32-
TempDir TempDir
33-
Force bool
34-
ForceAll bool
35-
Insecure bool
36-
Download bool
37-
Offline bool
38-
Timeout time.Duration
39-
Watch bool
40-
Verbose bool
41-
Silent bool
42-
AssumeYes bool
43-
AssumeTerm bool // Used for testing
44-
Dry bool
45-
Summary bool
46-
Parallel bool
47-
Color bool
48-
Concurrency int
49-
Interval time.Duration
30+
Dir string
31+
Entrypoint string
32+
TempDir TempDir
33+
Force bool
34+
ForceAll bool
35+
Insecure bool
36+
Download bool
37+
Offline bool
38+
Timeout time.Duration
39+
CacheExpiryDuration time.Duration
40+
Watch bool
41+
Verbose bool
42+
Silent bool
43+
AssumeYes bool
44+
AssumeTerm bool // Used for testing
45+
Dry bool
46+
Summary bool
47+
Parallel bool
48+
Color bool
49+
Concurrency int
50+
Interval time.Duration
5051

5152
// I/O
5253
Stdin io.Reader
@@ -240,6 +241,20 @@ func (o *timeoutOption) ApplyToExecutor(e *Executor) {
240241
e.Timeout = o.timeout
241242
}
242243

244+
// WithCacheExpiryDuration sets the duration after which the cache is considered
245+
// expired. By default, the cache is considered expired after 24 hours.
246+
func WithCacheExpiryDuration(duration time.Duration) ExecutorOption {
247+
return &cacheExpiryDurationOption{duration: duration}
248+
}
249+
250+
type cacheExpiryDurationOption struct {
251+
duration time.Duration
252+
}
253+
254+
func (o *cacheExpiryDurationOption) ApplyToExecutor(r *Executor) {
255+
r.CacheExpiryDuration = o.duration
256+
}
257+
243258
// WithWatch tells the [Executor] to keep running in the background and watch
244259
// for changes to the fingerprint of the tasks that are run. When changes are
245260
// detected, a new task run is triggered.

internal/flags/flags.go

Lines changed: 36 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -40,39 +40,40 @@ Options:
4040
`
4141

4242
var (
43-
Version bool
44-
Help bool
45-
Init bool
46-
Completion string
47-
List bool
48-
ListAll bool
49-
ListJson bool
50-
TaskSort string
51-
Status bool
52-
NoStatus bool
53-
Insecure bool
54-
Force bool
55-
ForceAll bool
56-
Watch bool
57-
Verbose bool
58-
Silent bool
59-
AssumeYes bool
60-
Dry bool
61-
Summary bool
62-
ExitCode bool
63-
Parallel bool
64-
Concurrency int
65-
Dir string
66-
Entrypoint string
67-
Output ast.Output
68-
Color bool
69-
Interval time.Duration
70-
Global bool
71-
Experiments bool
72-
Download bool
73-
Offline bool
74-
ClearCache bool
75-
Timeout time.Duration
43+
Version bool
44+
Help bool
45+
Init bool
46+
Completion string
47+
List bool
48+
ListAll bool
49+
ListJson bool
50+
TaskSort string
51+
Status bool
52+
NoStatus bool
53+
Insecure bool
54+
Force bool
55+
ForceAll bool
56+
Watch bool
57+
Verbose bool
58+
Silent bool
59+
AssumeYes bool
60+
Dry bool
61+
Summary bool
62+
ExitCode bool
63+
Parallel bool
64+
Concurrency int
65+
Dir string
66+
Entrypoint string
67+
Output ast.Output
68+
Color bool
69+
Interval time.Duration
70+
Global bool
71+
Experiments bool
72+
Download bool
73+
Offline bool
74+
ClearCache bool
75+
Timeout time.Duration
76+
CacheExpiryDuration time.Duration
7677
)
7778

7879
func init() {
@@ -131,6 +132,7 @@ func init() {
131132
pflag.BoolVar(&Offline, "offline", offline, "Forces Task to only use local or cached Taskfiles.")
132133
pflag.DurationVar(&Timeout, "timeout", time.Second*10, "Timeout for downloading remote Taskfiles.")
133134
pflag.BoolVar(&ClearCache, "clear-cache", false, "Clear the remote cache.")
135+
pflag.DurationVar(&CacheExpiryDuration, "expiry", 0, "Expiry duration for cached remote Taskfiles.")
134136
}
135137

136138
pflag.Parse()
@@ -212,6 +214,7 @@ func (o *flagsOption) ApplyToExecutor(e *task.Executor) {
212214
task.WithDownload(Download),
213215
task.WithOffline(Offline),
214216
task.WithTimeout(Timeout),
217+
task.WithCacheExpiryDuration(CacheExpiryDuration),
215218
task.WithWatch(Watch),
216219
task.WithVerbose(Verbose),
217220
task.WithSilent(Silent),

setup.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ func (e *Executor) getRootNode() (taskfile.Node, error) {
6464
}
6565

6666
func (e *Executor) readTaskfile(node taskfile.Node) error {
67+
ctx, cf := context.WithTimeout(context.Background(), e.Timeout)
68+
defer cf()
6769
debugFunc := func(s string) {
6870
e.Logger.VerboseOutf(logger.Magenta, s)
6971
}
@@ -74,13 +76,16 @@ func (e *Executor) readTaskfile(node taskfile.Node) error {
7476
taskfile.WithInsecure(e.Insecure),
7577
taskfile.WithDownload(e.Download),
7678
taskfile.WithOffline(e.Offline),
77-
taskfile.WithTimeout(e.Timeout),
7879
taskfile.WithTempDir(e.TempDir.Remote),
80+
taskfile.WithCacheExpiryDuration(e.CacheExpiryDuration),
7981
taskfile.WithDebugFunc(debugFunc),
8082
taskfile.WithPromptFunc(promptFunc),
8183
)
82-
graph, err := reader.Read(node)
84+
graph, err := reader.Read(ctx, node)
8385
if err != nil {
86+
if errors.Is(err, context.DeadlineExceeded) {
87+
return &errors.TaskfileNetworkTimeoutError{URI: node.Location(), Timeout: e.Timeout}
88+
}
8489
return err
8590
}
8691
if e.Taskfile, err = graph.Merge(); err != nil {

taskfile/cache.go

Lines changed: 0 additions & 72 deletions
This file was deleted.

0 commit comments

Comments
 (0)