1
0
mirror of https://github.com/go-task/task.git synced 2025-11-25 22:32:55 +02:00

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
This commit is contained in:
Pete Davison
2025-04-19 12:12:08 +01:00
committed by GitHub
parent f47f237093
commit a84f09d45f
18 changed files with 579 additions and 353 deletions

View File

@@ -2,11 +2,12 @@ package taskfile
import (
"context"
"fmt"
"io"
"net/http"
"net/url"
"path/filepath"
"time"
"strings"
"github.com/go-task/task/v3/errors"
"github.com/go-task/task/v3/internal/execext"
@@ -18,14 +19,12 @@ type HTTPNode struct {
*BaseNode
URL *url.URL // stores url pointing actual remote file. (e.g. with Taskfile.yml)
entrypoint string // stores entrypoint url. used for building graph vertices.
timeout time.Duration
}
func NewHTTPNode(
entrypoint string,
dir string,
insecure bool,
timeout time.Duration,
opts ...NodeOption,
) (*HTTPNode, error) {
base := NewBaseNode(dir, opts...)
@@ -41,7 +40,6 @@ func NewHTTPNode(
BaseNode: base,
URL: url,
entrypoint: entrypoint,
timeout: timeout,
}, nil
}
@@ -49,12 +47,12 @@ func (node *HTTPNode) Location() string {
return node.entrypoint
}
func (node *HTTPNode) Remote() bool {
return true
func (node *HTTPNode) Read() ([]byte, error) {
return node.ReadContext(context.Background())
}
func (node *HTTPNode) Read(ctx context.Context) ([]byte, error) {
url, err := RemoteExists(ctx, node.URL, node.timeout)
func (node *HTTPNode) ReadContext(ctx context.Context) ([]byte, error) {
url, err := RemoteExists(ctx, node.URL)
if err != nil {
return nil, err
}
@@ -66,8 +64,8 @@ func (node *HTTPNode) Read(ctx context.Context) ([]byte, error) {
resp, err := http.DefaultClient.Do(req.WithContext(ctx))
if err != nil {
if errors.Is(err, context.DeadlineExceeded) {
return nil, &errors.TaskfileNetworkTimeoutError{URI: node.URL.String(), Timeout: node.timeout}
if ctx.Err() != nil {
return nil, err
}
return nil, errors.TaskfileFetchFailedError{URI: node.URL.String()}
}
@@ -116,7 +114,14 @@ func (node *HTTPNode) ResolveDir(dir string) (string, error) {
return filepathext.SmartJoin(parent, path), nil
}
func (node *HTTPNode) FilenameAndLastDir() (string, string) {
func (node *HTTPNode) CacheKey() string {
checksum := strings.TrimRight(checksum([]byte(node.Location())), "=")
dir, filename := filepath.Split(node.entrypoint)
return filepath.Base(dir), filename
lastDir := filepath.Base(dir)
prefix := filename
// Means it's not "", nor "." nor "/", so it's a valid directory
if len(lastDir) > 1 {
prefix = fmt.Sprintf("%s-%s", lastDir, filename)
}
return fmt.Sprintf("%s.%s", prefix, checksum)
}