Skip to content
Merged
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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@
variable (#2577, #2479 by @semihbkgr).
- Fixed false positive "property 'for' is not allowed" warnings in IntelliJ when
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

Expand Down
2 changes: 1 addition & 1 deletion completion/bash/task.bash
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ function _task()

# Handle special arguments of options.
case "$prev" in
-d|--dir)
-d|--dir|--remote-cache-dir)
_filedir -d
return $?
;;
Expand Down
7 changes: 4 additions & 3 deletions completion/fish/task.fish
Original file line number Diff line number Diff line change
Expand Up @@ -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'

# 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 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 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 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
complete -c $GO_TASK_PROGNAME -n "__task_is_experiment_enabled REMOTE_TASKFILES" -l download -d 'download remote Taskfile'
Expand Down
1 change: 1 addition & 0 deletions completion/ps/task.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ Register-ArgumentCompleter -CommandName task -ScriptBlock {
$completions += [CompletionResult]::new('--offline', '--offline', [CompletionResultType]::ParameterName, 'use cached Taskfiles')
$completions += [CompletionResult]::new('--timeout', '--timeout', [CompletionResultType]::ParameterName, 'download timeout')
$completions += [CompletionResult]::new('--expiry', '--expiry', [CompletionResultType]::ParameterName, 'cache expiry')
$completions += [CompletionResult]::new('--remote-cache-dir', '--remote-cache-dir', [CompletionResultType]::ParameterName, 'cache directory')
# Operations
$completions += [CompletionResult]::new('--download', '--download', [CompletionResultType]::ParameterName, 'download remote Taskfile')
$completions += [CompletionResult]::new('--clear-cache', '--clear-cache', [CompletionResultType]::ParameterName, 'clear cache')
Expand Down
1 change: 1 addition & 0 deletions completion/zsh/_task
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ _task() {
'(--offline --download)--offline[use only local or cached Taskfiles]'
'(--timeout)--timeout[timeout for remote Taskfile downloads]:duration: '
'(--expiry)--expiry[cache expiry duration]:duration: '
'(--remote-cache-dir)--remote-cache-dir[directory to cache remote Taskfiles]:cache dir:_dirs'
)
fi

Expand Down
14 changes: 14 additions & 0 deletions executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ type (
TrustedHosts []string
Timeout time.Duration
CacheExpiryDuration time.Duration
RemoteCacheDir string
Watch bool
Verbose bool
Silent bool
Expand Down Expand Up @@ -271,6 +272,19 @@ func (o *cacheExpiryDurationOption) ApplyToExecutor(r *Executor) {
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
// for changes to the fingerprint of the tasks that are run. When changes are
// detected, a new task run is triggered.
Expand Down
6 changes: 5 additions & 1 deletion internal/flags/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/go-task/task/v3"
"github.com/go-task/task/v3/errors"
"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/taskfile/ast"
"github.com/go-task/task/v3/taskrc"
Expand Down Expand Up @@ -79,6 +80,7 @@ var (
ClearCache bool
Timeout time.Duration
CacheExpiryDuration time.Duration
RemoteCacheDir string
)

func init() {
Expand Down Expand Up @@ -157,10 +159,11 @@ func init() {
if experiments.RemoteTaskfiles.Enabled() {
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.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.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.StringVar(&RemoteCacheDir, "remote-cache-dir", getConfig(config, func() *string { return config.Remote.CacheDir }, env.GetTaskEnv("REMOTE_DIR")), "Directory to cache remote Taskfiles.")
}
pflag.Parse()
}
Expand Down Expand Up @@ -247,6 +250,7 @@ func (o *flagsOption) ApplyToExecutor(e *task.Executor) {
task.WithTrustedHosts(TrustedHosts),
task.WithTimeout(Timeout),
task.WithCacheExpiryDuration(CacheExpiryDuration),
task.WithRemoteCacheDir(RemoteCacheDir),
task.WithWatch(Watch),
task.WithVerbose(Verbose),
task.WithSilent(Silent),
Expand Down
12 changes: 6 additions & 6 deletions setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,16 +153,16 @@ func (e *Executor) setupTempDir() error {
}
}

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

Expand Down
3 changes: 2 additions & 1 deletion taskrc/ast/taskrc.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ type Remote struct {
Offline *bool `yaml:"offline"`
Timeout *time.Duration `yaml:"timeout"`
CacheExpiry *time.Duration `yaml:"cache-expiry"`
CacheDir *string `yaml:"cache-dir"`
TrustedHosts []string `yaml:"trusted-hosts"`
}

Expand All @@ -46,7 +47,7 @@ func (t *TaskRC) Merge(other *TaskRC) {
t.Remote.Offline = cmp.Or(other.Remote.Offline, t.Remote.Offline)
t.Remote.Timeout = cmp.Or(other.Remote.Timeout, t.Remote.Timeout)
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 {
merged := slices.Concat(other.Remote.TrustedHosts, t.Remote.TrustedHosts)
slices.Sort(merged)
Expand Down
24 changes: 20 additions & 4 deletions website/src/docs/experiments/remote-taskfiles.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
set the timeout to 5 seconds.

By default, the cache is stored in the Task temp directory, represented by the
`TASK_TEMP_DIR` environment variable. You can override the location of the cache
by setting the `TASK_REMOTE_DIR` environment variable. This way, you can share
the cache between different projects.
By default, the cache is stored in the Task temp directory (`.task`). You can
override the location of the cache by using the `--remote-cache-dir` flag, the
`remote.cache-dir` option in your [configuration file](#cache-dir), or the
`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
the `--download` flag.
Expand All @@ -308,6 +309,7 @@ remote:
offline: false
timeout: "30s"
cache-expiry: "24h"
cache-dir: ~/.task
trusted-hosts:
- github.com
- gitlab.com
Expand Down Expand Up @@ -360,6 +362,20 @@ remote:
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`

- **Type**: `array of strings`
Expand Down
Loading