feat: add remote.cache-dir taskrc option (#2572)

This commit is contained in:
Valentin Maerten
2025-12-18 08:32:11 +01:00
committed by GitHub
parent 28408ef3f4
commit 4ec6c453bd
10 changed files with 56 additions and 16 deletions

View File

@@ -50,6 +50,8 @@
variable (#2577, #2479 by @semihbkgr). variable (#2577, #2479 by @semihbkgr).
- Fixed false positive "property 'for' is not allowed" warnings in IntelliJ when - Fixed false positive "property 'for' is not allowed" warnings in IntelliJ when
using `for` loops in Taskfiles (#2576 by @vmaerten). using `for` loops in Taskfiles (#2576 by @vmaerten).
- Added `--remote-cache-dir` flag and `remote.cache-dir` taskrc option to
customize the cache directory for Remote Taskfiles (#2572 by @vmaerten).
## v3.45.5 - 2025-11-11 ## v3.45.5 - 2025-11-11

View File

@@ -22,7 +22,7 @@ function _task()
# Handle special arguments of options. # Handle special arguments of options.
case "$prev" in case "$prev" in
-d|--dir) -d|--dir|--remote-cache-dir)
_filedir -d _filedir -d
return $? return $?
;; ;;

View File

@@ -106,9 +106,10 @@ complete -c $GO_TASK_PROGNAME -s y -l yes -d 'assume yes t
complete -c $GO_TASK_PROGNAME -n "__task_is_experiment_enabled GENTLE_FORCE" -l force-all -d 'force execution of task and all dependencies' complete -c $GO_TASK_PROGNAME -n "__task_is_experiment_enabled GENTLE_FORCE" -l force-all -d 'force execution of task and all dependencies'
# RemoteTaskfiles experiment - Options # RemoteTaskfiles experiment - Options
complete -c $GO_TASK_PROGNAME -n "__task_is_experiment_enabled REMOTE_TASKFILES" -l offline -d 'use only local or cached Taskfiles' complete -c $GO_TASK_PROGNAME -n "__task_is_experiment_enabled REMOTE_TASKFILES" -l offline -d 'use only local or cached Taskfiles'
complete -c $GO_TASK_PROGNAME -n "__task_is_experiment_enabled REMOTE_TASKFILES" -l timeout -d 'timeout for remote Taskfile downloads' complete -c $GO_TASK_PROGNAME -n "__task_is_experiment_enabled REMOTE_TASKFILES" -l timeout -d 'timeout for remote Taskfile downloads'
complete -c $GO_TASK_PROGNAME -n "__task_is_experiment_enabled REMOTE_TASKFILES" -l expiry -d 'cache expiry duration' complete -c $GO_TASK_PROGNAME -n "__task_is_experiment_enabled REMOTE_TASKFILES" -l expiry -d 'cache expiry duration'
complete -c $GO_TASK_PROGNAME -n "__task_is_experiment_enabled REMOTE_TASKFILES" -l remote-cache-dir -d 'directory to cache remote Taskfiles' -xa "(__fish_complete_directories)"
# RemoteTaskfiles experiment - Operations # RemoteTaskfiles experiment - Operations
complete -c $GO_TASK_PROGNAME -n "__task_is_experiment_enabled REMOTE_TASKFILES" -l download -d 'download remote Taskfile' complete -c $GO_TASK_PROGNAME -n "__task_is_experiment_enabled REMOTE_TASKFILES" -l download -d 'download remote Taskfile'

View File

@@ -75,6 +75,7 @@ Register-ArgumentCompleter -CommandName task -ScriptBlock {
$completions += [CompletionResult]::new('--offline', '--offline', [CompletionResultType]::ParameterName, 'use cached Taskfiles') $completions += [CompletionResult]::new('--offline', '--offline', [CompletionResultType]::ParameterName, 'use cached Taskfiles')
$completions += [CompletionResult]::new('--timeout', '--timeout', [CompletionResultType]::ParameterName, 'download timeout') $completions += [CompletionResult]::new('--timeout', '--timeout', [CompletionResultType]::ParameterName, 'download timeout')
$completions += [CompletionResult]::new('--expiry', '--expiry', [CompletionResultType]::ParameterName, 'cache expiry') $completions += [CompletionResult]::new('--expiry', '--expiry', [CompletionResultType]::ParameterName, 'cache expiry')
$completions += [CompletionResult]::new('--remote-cache-dir', '--remote-cache-dir', [CompletionResultType]::ParameterName, 'cache directory')
# Operations # Operations
$completions += [CompletionResult]::new('--download', '--download', [CompletionResultType]::ParameterName, 'download remote Taskfile') $completions += [CompletionResult]::new('--download', '--download', [CompletionResultType]::ParameterName, 'download remote Taskfile')
$completions += [CompletionResult]::new('--clear-cache', '--clear-cache', [CompletionResultType]::ParameterName, 'clear cache') $completions += [CompletionResult]::new('--clear-cache', '--clear-cache', [CompletionResultType]::ParameterName, 'clear cache')

View File

@@ -100,6 +100,7 @@ _task() {
'(--offline --download)--offline[use only local or cached Taskfiles]' '(--offline --download)--offline[use only local or cached Taskfiles]'
'(--timeout)--timeout[timeout for remote Taskfile downloads]:duration: ' '(--timeout)--timeout[timeout for remote Taskfile downloads]:duration: '
'(--expiry)--expiry[cache expiry duration]:duration: ' '(--expiry)--expiry[cache expiry duration]:duration: '
'(--remote-cache-dir)--remote-cache-dir[directory to cache remote Taskfiles]:cache dir:_dirs'
) )
fi fi

View File

@@ -37,6 +37,7 @@ type (
TrustedHosts []string TrustedHosts []string
Timeout time.Duration Timeout time.Duration
CacheExpiryDuration time.Duration CacheExpiryDuration time.Duration
RemoteCacheDir string
Watch bool Watch bool
Verbose bool Verbose bool
Silent bool Silent bool
@@ -271,6 +272,19 @@ func (o *cacheExpiryDurationOption) ApplyToExecutor(r *Executor) {
r.CacheExpiryDuration = o.duration r.CacheExpiryDuration = o.duration
} }
// WithRemoteCacheDir sets the directory where remote taskfiles are cached.
func WithRemoteCacheDir(dir string) ExecutorOption {
return &remoteCacheDirOption{dir: dir}
}
type remoteCacheDirOption struct {
dir string
}
func (o *remoteCacheDirOption) ApplyToExecutor(e *Executor) {
e.RemoteCacheDir = o.dir
}
// WithWatch tells the [Executor] to keep running in the background and watch // WithWatch tells the [Executor] to keep running in the background and watch
// for changes to the fingerprint of the tasks that are run. When changes are // for changes to the fingerprint of the tasks that are run. When changes are
// detected, a new task run is triggered. // detected, a new task run is triggered.

View File

@@ -12,6 +12,7 @@ import (
"github.com/go-task/task/v3" "github.com/go-task/task/v3"
"github.com/go-task/task/v3/errors" "github.com/go-task/task/v3/errors"
"github.com/go-task/task/v3/experiments" "github.com/go-task/task/v3/experiments"
"github.com/go-task/task/v3/internal/env"
"github.com/go-task/task/v3/internal/sort" "github.com/go-task/task/v3/internal/sort"
"github.com/go-task/task/v3/taskfile/ast" "github.com/go-task/task/v3/taskfile/ast"
"github.com/go-task/task/v3/taskrc" "github.com/go-task/task/v3/taskrc"
@@ -79,6 +80,7 @@ var (
ClearCache bool ClearCache bool
Timeout time.Duration Timeout time.Duration
CacheExpiryDuration time.Duration CacheExpiryDuration time.Duration
RemoteCacheDir string
) )
func init() { func init() {
@@ -157,10 +159,11 @@ func init() {
if experiments.RemoteTaskfiles.Enabled() { if experiments.RemoteTaskfiles.Enabled() {
pflag.BoolVar(&Download, "download", false, "Downloads a cached version of a remote Taskfile.") pflag.BoolVar(&Download, "download", false, "Downloads a cached version of a remote Taskfile.")
pflag.BoolVar(&Offline, "offline", getConfig(config, func() *bool { return config.Remote.Offline }, false), "Forces Task to only use local or cached Taskfiles.") pflag.BoolVar(&Offline, "offline", getConfig(config, func() *bool { return config.Remote.Offline }, false), "Forces Task to only use local or cached Taskfiles.")
pflag.StringSliceVar(&TrustedHosts, "trusted-hosts", config.Remote.TrustedHosts, "List of trusted hosts for remote Taskfiles (comma-separated).") pflag.StringSliceVar(&TrustedHosts, "trusted-hosts", getConfig(config, func() *[]string { return &config.Remote.TrustedHosts }, nil), "List of trusted hosts for remote Taskfiles (comma-separated).")
pflag.DurationVar(&Timeout, "timeout", getConfig(config, func() *time.Duration { return config.Remote.Timeout }, time.Second*10), "Timeout for downloading remote Taskfiles.") pflag.DurationVar(&Timeout, "timeout", getConfig(config, func() *time.Duration { return config.Remote.Timeout }, time.Second*10), "Timeout for downloading remote Taskfiles.")
pflag.BoolVar(&ClearCache, "clear-cache", false, "Clear the remote cache.") pflag.BoolVar(&ClearCache, "clear-cache", false, "Clear the remote cache.")
pflag.DurationVar(&CacheExpiryDuration, "expiry", getConfig(config, func() *time.Duration { return config.Remote.CacheExpiry }, 0), "Expiry duration for cached remote Taskfiles.") pflag.DurationVar(&CacheExpiryDuration, "expiry", getConfig(config, func() *time.Duration { return config.Remote.CacheExpiry }, 0), "Expiry duration for cached remote Taskfiles.")
pflag.StringVar(&RemoteCacheDir, "remote-cache-dir", getConfig(config, func() *string { return config.Remote.CacheDir }, env.GetTaskEnv("REMOTE_DIR")), "Directory to cache remote Taskfiles.")
} }
pflag.Parse() pflag.Parse()
} }
@@ -247,6 +250,7 @@ func (o *flagsOption) ApplyToExecutor(e *task.Executor) {
task.WithTrustedHosts(TrustedHosts), task.WithTrustedHosts(TrustedHosts),
task.WithTimeout(Timeout), task.WithTimeout(Timeout),
task.WithCacheExpiryDuration(CacheExpiryDuration), task.WithCacheExpiryDuration(CacheExpiryDuration),
task.WithRemoteCacheDir(RemoteCacheDir),
task.WithWatch(Watch), task.WithWatch(Watch),
task.WithVerbose(Verbose), task.WithVerbose(Verbose),
task.WithSilent(Silent), task.WithSilent(Silent),

View File

@@ -153,16 +153,16 @@ func (e *Executor) setupTempDir() error {
} }
} }
remoteDir := env.GetTaskEnv("REMOTE_DIR") // RemoteCacheDir from taskrc/env can override the remote cache directory
if remoteDir != "" { if e.RemoteCacheDir != "" {
if filepath.IsAbs(remoteDir) || strings.HasPrefix(remoteDir, "~") { if filepath.IsAbs(e.RemoteCacheDir) || strings.HasPrefix(e.RemoteCacheDir, "~") {
remoteTempDir, err := execext.ExpandLiteral(remoteDir) remoteCacheDir, err := execext.ExpandLiteral(e.RemoteCacheDir)
if err != nil { if err != nil {
return err return err
} }
e.TempDir.Remote = remoteTempDir e.TempDir.Remote = remoteCacheDir
} else { } else {
e.TempDir.Remote = filepathext.SmartJoin(e.Dir, ".task") e.TempDir.Remote = filepathext.SmartJoin(e.Dir, e.RemoteCacheDir)
} }
} }

View File

@@ -24,6 +24,7 @@ type Remote struct {
Offline *bool `yaml:"offline"` Offline *bool `yaml:"offline"`
Timeout *time.Duration `yaml:"timeout"` Timeout *time.Duration `yaml:"timeout"`
CacheExpiry *time.Duration `yaml:"cache-expiry"` CacheExpiry *time.Duration `yaml:"cache-expiry"`
CacheDir *string `yaml:"cache-dir"`
TrustedHosts []string `yaml:"trusted-hosts"` TrustedHosts []string `yaml:"trusted-hosts"`
} }
@@ -46,7 +47,7 @@ func (t *TaskRC) Merge(other *TaskRC) {
t.Remote.Offline = cmp.Or(other.Remote.Offline, t.Remote.Offline) t.Remote.Offline = cmp.Or(other.Remote.Offline, t.Remote.Offline)
t.Remote.Timeout = cmp.Or(other.Remote.Timeout, t.Remote.Timeout) t.Remote.Timeout = cmp.Or(other.Remote.Timeout, t.Remote.Timeout)
t.Remote.CacheExpiry = cmp.Or(other.Remote.CacheExpiry, t.Remote.CacheExpiry) t.Remote.CacheExpiry = cmp.Or(other.Remote.CacheExpiry, t.Remote.CacheExpiry)
t.Remote.CacheDir = cmp.Or(other.Remote.CacheDir, t.Remote.CacheDir)
if len(other.Remote.TrustedHosts) > 0 { if len(other.Remote.TrustedHosts) > 0 {
merged := slices.Concat(other.Remote.TrustedHosts, t.Remote.TrustedHosts) merged := slices.Concat(other.Remote.TrustedHosts, t.Remote.TrustedHosts)
slices.Sort(merged) slices.Sort(merged)

View File

@@ -284,10 +284,11 @@ and look for a cached copy instead. This timeout can be configured by setting
the `--timeout` flag and specifying a duration. For example, `--timeout 5s` will the `--timeout` flag and specifying a duration. For example, `--timeout 5s` will
set the timeout to 5 seconds. set the timeout to 5 seconds.
By default, the cache is stored in the Task temp directory, represented by the By default, the cache is stored in the Task temp directory (`.task`). You can
`TASK_TEMP_DIR` environment variable. You can override the location of the cache override the location of the cache by using the `--remote-cache-dir` flag, the
by setting the `TASK_REMOTE_DIR` environment variable. This way, you can share `remote.cache-dir` option in your [configuration file](#cache-dir), or the
the cache between different projects. `TASK_REMOTE_DIR` environment variable. This way, you can share the cache
between different projects.
You can force Task to ignore the cache and download the latest version by using You can force Task to ignore the cache and download the latest version by using
the `--download` flag. the `--download` flag.
@@ -308,6 +309,7 @@ remote:
offline: false offline: false
timeout: "30s" timeout: "30s"
cache-expiry: "24h" cache-expiry: "24h"
cache-dir: ~/.task
trusted-hosts: trusted-hosts:
- github.com - github.com
- gitlab.com - gitlab.com
@@ -360,6 +362,20 @@ remote:
cache-expiry: "6h" cache-expiry: "6h"
``` ```
#### `cache-dir`
- **Type**: `string`
- **Default**: `.task`
- **Description**: Directory where remote Taskfiles are cached. Can be an
absolute path (e.g., `/var/cache/task`) or relative to the Taskfile directory.
- **CLI equivalent**: `--remote-cache-dir`
- **Environment variable**: `TASK_REMOTE_DIR` (lowest priority)
```yaml
remote:
cache-dir: ~/.task
```
#### `trusted-hosts` #### `trusted-hosts`
- **Type**: `array of strings` - **Type**: `array of strings`