diff --git a/help.go b/help.go index ca187cc412..abcdce92ea 100644 --- a/help.go +++ b/help.go @@ -190,7 +190,7 @@ func (e *Executor) ToEditorOutput(tasks []*ast.Task, noStatus bool) (*editors.Ta } upToDate, err := fingerprint.IsTaskUpToDate(context.Background(), task, fingerprint.WithMethod(method), - fingerprint.WithTempDir(e.TempDir), + fingerprint.WithTempDir(e.TempDir.Fingerprint), fingerprint.WithDry(e.Dry), fingerprint.WithLogger(e.Logger), ) diff --git a/setup.go b/setup.go index a877a59714..a6eb772d90 100644 --- a/setup.go +++ b/setup.go @@ -69,7 +69,7 @@ func (e *Executor) readTaskfile(node taskfile.Node) error { e.Download, e.Offline, e.Timeout, - e.TempDir, + e.TempDir.Remote, e.Logger, ) graph, err := reader.Read() @@ -104,12 +104,15 @@ func (e *Executor) setupFuzzyModel() { } func (e *Executor) setupTempDir() error { - if e.TempDir != "" { + if e.TempDir != (TempDir{}) { return nil } if os.Getenv("TASK_TEMP_DIR") == "" { - e.TempDir = filepathext.SmartJoin(e.Dir, ".task") + e.TempDir = TempDir{ + Remote: filepathext.SmartJoin(e.Dir, ".task"), + Fingerprint: filepathext.SmartJoin(e.Dir, ".task"), + } } else if filepath.IsAbs(os.Getenv("TASK_TEMP_DIR")) || strings.HasPrefix(os.Getenv("TASK_TEMP_DIR"), "~") { tempDir, err := execext.Expand(os.Getenv("TASK_TEMP_DIR")) if err != nil { @@ -117,9 +120,28 @@ func (e *Executor) setupTempDir() error { } projectDir, _ := filepath.Abs(e.Dir) projectName := filepath.Base(projectDir) - e.TempDir = filepathext.SmartJoin(tempDir, projectName) + e.TempDir = TempDir{ + Remote: tempDir, + Fingerprint: filepathext.SmartJoin(tempDir, projectName), + } + } else { - e.TempDir = filepathext.SmartJoin(e.Dir, os.Getenv("TASK_TEMP_DIR")) + e.TempDir = TempDir{ + Remote: filepathext.SmartJoin(e.Dir, os.Getenv("TASK_TEMP_DIR")), + Fingerprint: filepathext.SmartJoin(e.Dir, os.Getenv("TASK_TEMP_DIR")), + } + } + + if os.Getenv("TASK_REMOTE_DIR") != "" { + if filepath.IsAbs(os.Getenv("TASK_TEMP_DIR")) || strings.HasPrefix(os.Getenv("TASK_TEMP_DIR"), "~") { + remoteTempDir, err := execext.Expand(filepathext.SmartJoin(e.Dir, ".task")) + if err != nil { + return err + } + e.TempDir.Remote = remoteTempDir + } else { + e.TempDir.Remote = filepathext.SmartJoin(e.Dir, ".task") + } } return nil diff --git a/status.go b/status.go index a2dcf9016e..f18a60986d 100644 --- a/status.go +++ b/status.go @@ -27,7 +27,7 @@ func (e *Executor) Status(ctx context.Context, calls ...*ast.Call) error { // Check if the task is up-to-date isUpToDate, err := fingerprint.IsTaskUpToDate(ctx, t, fingerprint.WithMethod(method), - fingerprint.WithTempDir(e.TempDir), + fingerprint.WithTempDir(e.TempDir.Fingerprint), fingerprint.WithDry(e.Dry), fingerprint.WithLogger(e.Logger), ) @@ -46,7 +46,7 @@ func (e *Executor) statusOnError(t *ast.Task) error { if method == "" { method = e.Taskfile.Method } - checker, err := fingerprint.NewSourcesChecker(method, e.TempDir, e.Dry) + checker, err := fingerprint.NewSourcesChecker(method, e.TempDir.Fingerprint, e.Dry) if err != nil { return err } diff --git a/task.go b/task.go index 4ec598bec6..516ee20450 100644 --- a/task.go +++ b/task.go @@ -34,13 +34,18 @@ const ( MaximumTaskCall = 1000 ) +type TempDir struct { + Remote string + Fingerprint string +} + // Executor executes a Taskfile type Executor struct { Taskfile *ast.Taskfile Dir string Entrypoint string - TempDir string + TempDir TempDir Force bool ForceAll bool Insecure bool @@ -212,7 +217,7 @@ func (e *Executor) RunTask(ctx context.Context, call *ast.Call) error { upToDate, err := fingerprint.IsTaskUpToDate(ctx, t, fingerprint.WithMethod(method), - fingerprint.WithTempDir(e.TempDir), + fingerprint.WithTempDir(e.TempDir.Fingerprint), fingerprint.WithDry(e.Dry), fingerprint.WithLogger(e.Logger), ) diff --git a/task_test.go b/task_test.go index f94b57aaa5..0dd489caaf 100644 --- a/task_test.go +++ b/task_test.go @@ -62,8 +62,11 @@ func (fct fileContentTest) Run(t *testing.T) { } e := &task.Executor{ - Dir: fct.Dir, - TempDir: filepathext.SmartJoin(fct.Dir, ".task"), + Dir: fct.Dir, + TempDir: task.TempDir{ + Remote: filepathext.SmartJoin(fct.Dir, ".task"), + Fingerprint: filepathext.SmartJoin(fct.Dir, ".task"), + }, Entrypoint: fct.Entrypoint, Stdout: io.Discard, Stderr: io.Discard, @@ -272,11 +275,14 @@ func TestStatus(t *testing.T) { var buff bytes.Buffer e := &task.Executor{ - Dir: dir, - TempDir: filepathext.SmartJoin(dir, ".task"), - Stdout: &buff, - Stderr: &buff, - Silent: true, + Dir: dir, + TempDir: task.TempDir{ + Remote: filepathext.SmartJoin(dir, ".task"), + Fingerprint: filepathext.SmartJoin(dir, ".task"), + }, + Stdout: &buff, + Stderr: &buff, + Silent: true, } require.NoError(t, e.Setup()) // gen-foo creates foo.txt, and will always fail it's status check. @@ -468,7 +474,10 @@ func TestStatusChecksum(t *testing.T) { } var buff bytes.Buffer - tempdir := filepathext.SmartJoin(dir, ".task") + tempdir := task.TempDir{ + Remote: filepathext.SmartJoin(dir, ".task"), + Fingerprint: filepathext.SmartJoin(dir, ".task"), + } e := task.Executor{ Dir: dir, TempDir: tempdir, @@ -485,7 +494,7 @@ func TestStatusChecksum(t *testing.T) { // Capture the modification time, so we can ensure the checksum file // is not regenerated when the hash hasn't changed. - s, err := os.Stat(filepathext.SmartJoin(tempdir, "checksum/"+test.task)) + s, err := os.Stat(filepathext.SmartJoin(tempdir.Fingerprint, "checksum/"+test.task)) require.NoError(t, err) time := s.ModTime() @@ -493,7 +502,7 @@ func TestStatusChecksum(t *testing.T) { require.NoError(t, e.Run(context.Background(), &ast.Call{Task: test.task})) assert.Equal(t, `task: Task "`+test.task+`" is up to date`+"\n", buff.String()) - s, err = os.Stat(filepathext.SmartJoin(tempdir, "checksum/"+test.task)) + s, err = os.Stat(filepathext.SmartJoin(tempdir.Fingerprint, "checksum/"+test.task)) require.NoError(t, err) assert.Equal(t, time, s.ModTime()) }) @@ -814,8 +823,11 @@ func TestStatusVariables(t *testing.T) { var buff bytes.Buffer e := task.Executor{ - Dir: dir, - TempDir: filepathext.SmartJoin(dir, ".task"), + Dir: dir, + TempDir: task.TempDir{ + Remote: filepathext.SmartJoin(dir, ".task"), + Fingerprint: filepathext.SmartJoin(dir, ".task"), + }, Stdout: &buff, Stderr: &buff, Silent: false, @@ -963,11 +975,14 @@ func TestDryChecksum(t *testing.T) { _ = os.Remove(checksumFile) e := task.Executor{ - Dir: dir, - TempDir: filepathext.SmartJoin(dir, ".task"), - Stdout: io.Discard, - Stderr: io.Discard, - Dry: true, + Dir: dir, + TempDir: task.TempDir{ + Remote: filepathext.SmartJoin(dir, ".task"), + Fingerprint: filepathext.SmartJoin(dir, ".task"), + }, + Stdout: io.Discard, + Stderr: io.Discard, + Dry: true, } require.NoError(t, e.Setup()) require.NoError(t, e.Run(context.Background(), &ast.Call{Task: "default"})) diff --git a/variables.go b/variables.go index 1502988389..d69764c7c6 100644 --- a/variables.go +++ b/variables.go @@ -222,8 +222,8 @@ func (e *Executor) compiledTask(call *ast.Call, evaluateShVars bool) (*ast.Task, } if len(origTask.Status) > 0 { - timestampChecker := fingerprint.NewTimestampChecker(e.TempDir, e.Dry) - checksumChecker := fingerprint.NewChecksumChecker(e.TempDir, e.Dry) + timestampChecker := fingerprint.NewTimestampChecker(e.TempDir.Fingerprint, e.Dry) + checksumChecker := fingerprint.NewChecksumChecker(e.TempDir.Fingerprint, e.Dry) for _, checker := range []fingerprint.SourcesCheckable{timestampChecker, checksumChecker} { value, err := checker.Value(&new) diff --git a/website/docs/experiments/remote_taskfiles.mdx b/website/docs/experiments/remote_taskfiles.mdx index a1259b7621..8df5ac8b5b 100644 --- a/website/docs/experiments/remote_taskfiles.mdx +++ b/website/docs/experiments/remote_taskfiles.mdx @@ -112,6 +112,9 @@ 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](../reference/environment.mdx) +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. + {/* prettier-ignore-start */} [enabling-experiments]: ./experiments.mdx#enabling-experiments [man-in-the-middle-attacks]: https://en.wikipedia.org/wiki/Man-in-the-middle_attack diff --git a/website/docs/reference/environment.mdx b/website/docs/reference/environment.mdx index 55d46ac8cc..ce9b7334b3 100644 --- a/website/docs/reference/environment.mdx +++ b/website/docs/reference/environment.mdx @@ -8,10 +8,11 @@ sidebar_position: 4 Task allows you to configure some behavior using environment variables. This page lists all the environment variables that Task supports. -| ENV | Default | Description | -| --------------- | ------- | ----------------------------------------------------------------------------------------------------------------- | -| `TASK_TEMP_DIR` | `.task` | Location of the temp dir. Can relative to the project like `tmp/task` or absolute like `/tmp/.task` or `~/.task`. | -| `FORCE_COLOR` | | Force color output usage. | +| ENV | Default | Description | +| ----------------- | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | +| `TASK_TEMP_DIR` | `.task` | Location of the temp dir. Can relative to the project like `tmp/task` or absolute like `/tmp/.task` or `~/.task`. | +| `TASK_REMOTE_DIR` | `TASK_TEMP_DIR` | Location of the remote temp dir (used for caching). Can relative to the project like `tmp/task` or absolute like `/tmp/.task` or `~/.task`. | +| `FORCE_COLOR` | | Force color output usage. | ## Custom Colors