mirror of
https://github.com/go-task/task.git
synced 2026-07-03 09:28:46 +00:00
Compare commits
8 Commits
nightly
...
enable-rem
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9f6dfa7fbf | ||
|
|
09a9aec407 | ||
|
|
9571430fed | ||
|
|
63abdd080c | ||
|
|
0467e0d603 | ||
|
|
ff9c4f24a9 | ||
|
|
468cacd4ca | ||
|
|
f2f0d62723 |
@@ -1,6 +1,7 @@
|
||||
package experiments
|
||||
|
||||
import (
|
||||
"cmp"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -24,12 +25,15 @@ func (err InvalidValueError) Error() string {
|
||||
}
|
||||
|
||||
type InactiveError struct {
|
||||
Name string
|
||||
Name string
|
||||
Reason string
|
||||
}
|
||||
|
||||
func (err InactiveError) Error() string {
|
||||
reason := cmp.Or(err.Reason, "is inactive and cannot be enabled")
|
||||
return fmt.Sprintf(
|
||||
"task: Experiment %q is inactive and cannot be enabled",
|
||||
"task: Experiment %q %s",
|
||||
err.Name,
|
||||
reason,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -9,27 +9,54 @@ import (
|
||||
)
|
||||
|
||||
type Experiment struct {
|
||||
Name string // The name of the experiment.
|
||||
AllowedValues []int // The values that can enable this experiment.
|
||||
Value int // The version of the experiment that is enabled.
|
||||
Name string // The name of the experiment.
|
||||
AllowedValues []int // The values that can enable this experiment.
|
||||
Value int // The version of the experiment that is enabled.
|
||||
InactiveReason string // If not active, the reason why it is inactive.
|
||||
}
|
||||
|
||||
func getValue(xName string, config *ast.TaskRC) int {
|
||||
var value int
|
||||
if config != nil {
|
||||
value = config.Experiments[xName]
|
||||
}
|
||||
if value == 0 {
|
||||
value, _ = strconv.Atoi(getEnv(xName))
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
// New creates a new experiment with the given name and sets the values that can
|
||||
// enable it.
|
||||
func New(xName string, config *ast.TaskRC, allowedValues ...int) Experiment {
|
||||
var value int
|
||||
if config != nil {
|
||||
value = config.Experiments[xName]
|
||||
}
|
||||
|
||||
if value == 0 {
|
||||
value, _ = strconv.Atoi(getEnv(xName))
|
||||
}
|
||||
|
||||
x := Experiment{
|
||||
Name: xName,
|
||||
AllowedValues: allowedValues,
|
||||
Value: value,
|
||||
Value: getValue(xName, config),
|
||||
}
|
||||
xList = append(xList, x)
|
||||
return x
|
||||
}
|
||||
|
||||
// NewReleased creates a new experiment that is released and no longer needs to
|
||||
// be enabled. It will always be inactive and cannot be enabled.
|
||||
func NewReleased(xName string, config *ast.TaskRC) Experiment {
|
||||
x := Experiment{
|
||||
Name: xName,
|
||||
Value: getValue(xName, config),
|
||||
InactiveReason: "is released and no longer needs to be enabled",
|
||||
}
|
||||
xList = append(xList, x)
|
||||
return x
|
||||
}
|
||||
|
||||
// NewAbandoned creates a new experiment that has been abandoned and is no
|
||||
// longer supported. It will always be inactive and cannot be enabled.
|
||||
func NewAbandoned(xName string, config *ast.TaskRC) Experiment {
|
||||
x := Experiment{
|
||||
Name: xName,
|
||||
Value: getValue(xName, config),
|
||||
InactiveReason: "has been abandoned and is no longer supported",
|
||||
}
|
||||
xList = append(xList, x)
|
||||
return x
|
||||
@@ -46,7 +73,8 @@ func (x Experiment) Active() bool {
|
||||
func (x Experiment) Valid() error {
|
||||
if !x.Active() && x.Value != 0 {
|
||||
return &InactiveError{
|
||||
Name: x.Name,
|
||||
Name: x.Name,
|
||||
Reason: x.InactiveReason,
|
||||
}
|
||||
}
|
||||
if !x.Enabled() && x.Value != 0 {
|
||||
|
||||
@@ -16,16 +16,16 @@ const envPrefix = "TASK_X_"
|
||||
|
||||
// Active experiments.
|
||||
var (
|
||||
GentleForce Experiment
|
||||
RemoteTaskfiles Experiment
|
||||
EnvPrecedence Experiment
|
||||
GentleForce Experiment
|
||||
EnvPrecedence Experiment
|
||||
)
|
||||
|
||||
// Inactive experiments. These are experiments that cannot be enabled, but are
|
||||
// preserved for error handling.
|
||||
var (
|
||||
AnyVariables Experiment
|
||||
MapVariables Experiment
|
||||
AnyVariables Experiment
|
||||
MapVariables Experiment
|
||||
RemoteTaskfiles Experiment
|
||||
)
|
||||
|
||||
// An internal list of all the initialized experiments used for iterating.
|
||||
@@ -41,10 +41,11 @@ func ParseWithConfig(dir string, config *ast.TaskRC) {
|
||||
readDotEnv(dir)
|
||||
// Initialize the experiments
|
||||
GentleForce = New("GENTLE_FORCE", config, 1)
|
||||
RemoteTaskfiles = New("REMOTE_TASKFILES", config, 1)
|
||||
EnvPrecedence = New("ENV_PRECEDENCE", config, 1)
|
||||
AnyVariables = New("ANY_VARIABLES", config)
|
||||
MapVariables = New("MAP_VARIABLES", config)
|
||||
// Inactive experiments
|
||||
AnyVariables = NewReleased("ANY_VARIABLES", config)
|
||||
MapVariables = NewReleased("MAP_VARIABLES", config)
|
||||
RemoteTaskfiles = NewReleased("REMOTE_TASKFILES", config)
|
||||
}
|
||||
|
||||
// Validate checks if any experiments have been enabled while being inactive.
|
||||
|
||||
@@ -155,6 +155,16 @@ func init() {
|
||||
pflag.BoolVarP(&Failfast, "failfast", "F", getConfig(config, "FAILFAST", func() *bool { return &config.Failfast }, false), "When running tasks in parallel, stop all tasks if one fails.")
|
||||
pflag.BoolVarP(&Global, "global", "g", false, "Runs global Taskfile, from $HOME/{T,t}askfile.{yml,yaml}.")
|
||||
pflag.BoolVar(&Experiments, "experiments", false, "Lists all the available experiments and whether or not they are enabled.")
|
||||
pflag.BoolVar(&Download, "download", false, "Downloads a cached version of a remote Taskfile.")
|
||||
pflag.BoolVar(&Offline, "offline", getConfig(config, "REMOTE_OFFLINE", func() *bool { return config.Remote.Offline }, false), "Forces Task to only use local or cached Taskfiles.")
|
||||
pflag.StringSliceVar(&TrustedHosts, "trusted-hosts", getConfig(config, "REMOTE_TRUSTED_HOSTS", func() *[]string { return &config.Remote.TrustedHosts }, nil), "List of trusted hosts for remote Taskfiles (comma-separated).")
|
||||
pflag.DurationVar(&Timeout, "timeout", getConfig(config, "REMOTE_TIMEOUT", 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, "REMOTE_CACHE_EXPIRY", func() *time.Duration { return config.Remote.CacheExpiry }, 0), "Expiry duration for cached remote Taskfiles.")
|
||||
pflag.StringVar(&RemoteCacheDir, "remote-cache-dir", getConfig(config, "REMOTE_CACHE_DIR", func() *string { return config.Remote.CacheDir }, env.GetTaskEnv("REMOTE_DIR")), "Directory to cache remote Taskfiles.")
|
||||
pflag.StringVar(&CACert, "cacert", getConfig(config, "REMOTE_CACERT", func() *string { return config.Remote.CACert }, ""), "Path to a custom CA certificate for HTTPS connections.")
|
||||
pflag.StringVar(&Cert, "cert", getConfig(config, "REMOTE_CERT", func() *string { return config.Remote.Cert }, ""), "Path to a client certificate for HTTPS connections.")
|
||||
pflag.StringVar(&CertKey, "cert-key", getConfig(config, "REMOTE_CERT_KEY", func() *string { return config.Remote.CertKey }, ""), "Path to a client certificate key for HTTPS connections.")
|
||||
|
||||
// Gentle force experiment will override the force flag and add a new force-all flag
|
||||
if experiments.GentleForce.Enabled() {
|
||||
@@ -164,19 +174,6 @@ func init() {
|
||||
pflag.BoolVarP(&ForceAll, "force", "f", false, "Forces execution even when the task is up-to-date.")
|
||||
}
|
||||
|
||||
// Remote Taskfiles experiment will adds the "download" and "offline" flags
|
||||
if experiments.RemoteTaskfiles.Enabled() {
|
||||
pflag.BoolVar(&Download, "download", false, "Downloads a cached version of a remote Taskfile.")
|
||||
pflag.BoolVar(&Offline, "offline", getConfig(config, "REMOTE_OFFLINE", func() *bool { return config.Remote.Offline }, false), "Forces Task to only use local or cached Taskfiles.")
|
||||
pflag.StringSliceVar(&TrustedHosts, "trusted-hosts", getConfig(config, "REMOTE_TRUSTED_HOSTS", func() *[]string { return &config.Remote.TrustedHosts }, nil), "List of trusted hosts for remote Taskfiles (comma-separated).")
|
||||
pflag.DurationVar(&Timeout, "timeout", getConfig(config, "REMOTE_TIMEOUT", 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, "REMOTE_CACHE_EXPIRY", func() *time.Duration { return config.Remote.CacheExpiry }, 0), "Expiry duration for cached remote Taskfiles.")
|
||||
pflag.StringVar(&RemoteCacheDir, "remote-cache-dir", getConfig(config, "REMOTE_CACHE_DIR", func() *string { return config.Remote.CacheDir }, env.GetTaskEnv("REMOTE_DIR")), "Directory to cache remote Taskfiles.")
|
||||
pflag.StringVar(&CACert, "cacert", getConfig(config, "REMOTE_CACERT", func() *string { return config.Remote.CACert }, ""), "Path to a custom CA certificate for HTTPS connections.")
|
||||
pflag.StringVar(&Cert, "cert", getConfig(config, "REMOTE_CERT", func() *string { return config.Remote.Cert }, ""), "Path to a client certificate for HTTPS connections.")
|
||||
pflag.StringVar(&CertKey, "cert-key", getConfig(config, "REMOTE_CERT_KEY", func() *string { return config.Remote.CertKey }, ""), "Path to a client certificate key for HTTPS connections.")
|
||||
}
|
||||
pflag.Parse()
|
||||
|
||||
// Auto-detect color based on environment when not explicitly configured
|
||||
|
||||
@@ -1073,8 +1073,6 @@ func TestIncludesMultiLevel(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestIncludesRemote(t *testing.T) {
|
||||
enableExperimentForTest(t, &experiments.RemoteTaskfiles, 1)
|
||||
|
||||
dir := "testdata/includes_remote"
|
||||
os.RemoveAll(filepath.Join(dir, ".task", "remote"))
|
||||
|
||||
@@ -1277,8 +1275,6 @@ func TestIncludesEmptyMain(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestIncludesHttp(t *testing.T) {
|
||||
enableExperimentForTest(t, &experiments.RemoteTaskfiles, 1)
|
||||
|
||||
dir, err := filepath.Abs("testdata/includes_http")
|
||||
require.NoError(t, err)
|
||||
|
||||
|
||||
@@ -8,8 +8,6 @@ import (
|
||||
|
||||
giturls "github.com/chainguard-dev/git-urls"
|
||||
|
||||
"github.com/go-task/task/v3/errors"
|
||||
"github.com/go-task/task/v3/experiments"
|
||||
"github.com/go-task/task/v3/internal/fsext"
|
||||
)
|
||||
|
||||
@@ -67,9 +65,6 @@ func NewNode(
|
||||
default:
|
||||
node, err = NewFileNode(entrypoint, dir, opts...)
|
||||
}
|
||||
if _, isRemote := node.(RemoteNode); isRemote && !experiments.RemoteTaskfiles.Enabled() {
|
||||
return nil, errors.New("task: Remote taskfiles are not enabled. You can read more about this experiment and how to enable it at https://taskfile.dev/experiments/remote-taskfiles")
|
||||
}
|
||||
|
||||
return node, err
|
||||
}
|
||||
|
||||
@@ -370,6 +370,10 @@ export default defineConfig({
|
||||
text: 'Guide',
|
||||
link: '/docs/guide'
|
||||
},
|
||||
{
|
||||
text: 'Remote Taskfiles',
|
||||
link: '/docs/remote-taskfiles'
|
||||
},
|
||||
{
|
||||
text: 'Reference',
|
||||
collapsed: true,
|
||||
|
||||
@@ -1,504 +1,14 @@
|
||||
---
|
||||
title: 'Remote Taskfiles (#1317)'
|
||||
description: Experimentation for using Taskfiles stored in remote locations
|
||||
outline: deep
|
||||
---
|
||||
|
||||
# Remote Taskfiles (#1317)
|
||||
|
||||
::: warning
|
||||
The Remote Taskfiles experiment has now [been released][changelog] :tada:. To
|
||||
learn more, you can read the [remote Taskfile docs][remote-taskfile-docs] or
|
||||
check out our [blog post][blog-post].
|
||||
|
||||
All experimental features are subject to breaking changes and/or removal _at any
|
||||
time_. We strongly recommend that you do not use these features in a production
|
||||
environment. They are intended for testing and feedback only.
|
||||
|
||||
:::
|
||||
|
||||
::: info
|
||||
|
||||
To enable this experiment, set the environment variable:
|
||||
`TASK_X_REMOTE_TASKFILES=1`. Check out
|
||||
[our guide to enabling experiments](./index.md#enabling-experiments) for more
|
||||
information.
|
||||
|
||||
:::
|
||||
|
||||
::: danger
|
||||
|
||||
Never run remote Taskfiles from sources that you do not trust.
|
||||
|
||||
:::
|
||||
|
||||
This experiment allows you to use Taskfiles which are stored in remote
|
||||
locations. This applies to both the root Taskfile (aka. Entrypoint) and also
|
||||
when including Taskfiles.
|
||||
|
||||
Task uses "nodes" to reference remote Taskfiles. There are a few different types
|
||||
of node which you can use:
|
||||
|
||||
::: code-group
|
||||
|
||||
```text [HTTP/HTTPS]
|
||||
https://raw.githubusercontent.com/go-task/task/main/website/src/public/Taskfile.yml
|
||||
```
|
||||
|
||||
```text [Git over HTTP]
|
||||
https://github.com/go-task/task.git//website/src/public/Taskfile.yml?ref=main
|
||||
```
|
||||
|
||||
```text [Git over SSH]
|
||||
git@github.com/go-task/task.git//website/src/public/Taskfile.yml?ref=main
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
## Node Types
|
||||
|
||||
### HTTP/HTTPS
|
||||
|
||||
`https://raw.githubusercontent.com/go-task/task/main/website/src/public/Taskfile.yml`
|
||||
|
||||
This is the most basic type of remote node and works by downloading the file
|
||||
from the specified URL. The file must be a valid Taskfile and can be of any
|
||||
name. If a file is not found at the specified URL, Task will append each of the
|
||||
supported file names in turn until it finds a valid file. If it still does not
|
||||
find a valid Taskfile, an error is returned.
|
||||
|
||||
### Git over HTTP
|
||||
|
||||
`https://github.com/go-task/task.git//website/src/public/Taskfile.yml?ref=main`
|
||||
|
||||
This type of node works by downloading the file from a Git repository over
|
||||
HTTP/HTTPS. The first part of the URL is the base URL of the Git repository.
|
||||
This is the same URL that you would use to clone the repo over HTTP.
|
||||
|
||||
- You can optionally add the path to the Taskfile in the repository by appending
|
||||
`//<path>` to the URL.
|
||||
- You can also optionally specify a branch or tag to use by appending
|
||||
`?ref=<ref>` to the end of the URL. If you omit a reference, the default
|
||||
branch will be used.
|
||||
|
||||
### Git over SSH
|
||||
|
||||
`git@github.com/go-task/task.git//website/src/public/Taskfile.yml?ref=main`
|
||||
|
||||
This type of node works by downloading the file from a Git repository over SSH.
|
||||
The first part of the URL is the user and base URL of the Git repository. This
|
||||
is the same URL that you would use to clone the repo over SSH.
|
||||
|
||||
To use Git over SSH, you need to make sure that your SSH agent has your private
|
||||
SSH keys added so that they can be used during authentication.
|
||||
|
||||
- You can optionally add the path to the Taskfile in the repository by appending
|
||||
`//<path>` to the URL.
|
||||
- You can also optionally specify a branch or tag to use by appending
|
||||
`?ref=<ref>` to the end of the URL. If you omit a reference, the default
|
||||
branch will be used.
|
||||
|
||||
Task has an example remote Taskfile in our repository that you can use for
|
||||
testing and that we will use throughout this document:
|
||||
|
||||
```yaml
|
||||
version: '3'
|
||||
|
||||
tasks:
|
||||
default:
|
||||
cmds:
|
||||
- task: hello
|
||||
|
||||
hello:
|
||||
cmds:
|
||||
- echo "Hello Task!"
|
||||
```
|
||||
|
||||
## Specifying a remote entrypoint
|
||||
|
||||
By default, Task will look for one of the supported file names on your local
|
||||
filesystem. If you want to use a remote file instead, you can pass its URI into
|
||||
the `--taskfile`/`-t` flag just like you would to specify a different local
|
||||
file. For example:
|
||||
|
||||
::: code-group
|
||||
|
||||
```shell [HTTP/HTTPS]
|
||||
$ task --taskfile https://raw.githubusercontent.com/go-task/task/main/website/src/public/Taskfile.yml
|
||||
task: [hello] echo "Hello Task!"
|
||||
Hello Task!
|
||||
```
|
||||
|
||||
```shell [Git over HTTP]
|
||||
$ task --taskfile https://github.com/go-task/task.git//website/src/public/Taskfile.yml?ref=main
|
||||
task: [hello] echo "Hello Task!"
|
||||
Hello Task!
|
||||
```
|
||||
|
||||
```shell [Git over SSH]
|
||||
$ task --taskfile git@github.com/go-task/task.git//website/src/public/Taskfile.yml?ref=main
|
||||
task: [hello] echo "Hello Task!"
|
||||
Hello Task!
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
## Including remote Taskfiles
|
||||
|
||||
Including a remote file works exactly the same way that including a local file
|
||||
does. You just need to replace the local path with a remote URI. Any tasks in
|
||||
the remote Taskfile will be available to run from your main Taskfile.
|
||||
|
||||
::: code-group
|
||||
|
||||
```yaml [HTTP/HTTPS]
|
||||
version: '3'
|
||||
|
||||
includes:
|
||||
my-remote-namespace: https://raw.githubusercontent.com/go-task/task/main/website/src/public/Taskfile.yml
|
||||
```
|
||||
|
||||
```yaml [Git over HTTP]
|
||||
version: '3'
|
||||
|
||||
includes:
|
||||
my-remote-namespace: https://github.com/go-task/task.git//website/src/public/Taskfile.yml?ref=main
|
||||
```
|
||||
|
||||
```yaml [Git over SSH]
|
||||
version: '3'
|
||||
|
||||
includes:
|
||||
my-remote-namespace: git@github.com/go-task/task.git//website/src/public/Taskfile.yml?ref=main
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
```shell
|
||||
$ task my-remote-namespace:hello
|
||||
task: [hello] echo "Hello Task!"
|
||||
Hello Task!
|
||||
```
|
||||
|
||||
### Authenticating using environment variables
|
||||
|
||||
The Taskfile location is processed by the templating system, so you can
|
||||
reference environment variables in your URL if you need to add authentication.
|
||||
For example:
|
||||
|
||||
```yaml
|
||||
version: '3'
|
||||
|
||||
includes:
|
||||
my-remote-namespace: https://{{.TOKEN}}@raw.githubusercontent.com/my-org/my-repo/main/Taskfile.yml
|
||||
```
|
||||
|
||||
## Special Variables
|
||||
|
||||
The file-path [special variables](../reference/templating.md#file-paths) behave
|
||||
differently when a Taskfile is loaded from a remote source, because there is no
|
||||
local file or directory that corresponds 1:1 to the Taskfile:
|
||||
|
||||
| Variable | Value when loaded remotely |
|
||||
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `TASKFILE` / `ROOT_TASKFILE` | The original URL, unchanged |
|
||||
| `TASKFILE_DIR` / `ROOT_DIR` | Empty string — a directory variable cannot point to a URL |
|
||||
| `TASK_DIR` | Resolved against `USER_WORKING_DIR` (relative `dir:` → joined with `USER_WORKING_DIR`, empty `dir:` → `USER_WORKING_DIR`, absolute `dir:` → kept as-is) |
|
||||
|
||||
If a remote Taskfile includes a local Taskfile (or vice-versa), each variable
|
||||
reflects the source of the Taskfile it refers to.
|
||||
|
||||
## Security
|
||||
|
||||
### Automatic checksums
|
||||
|
||||
Running commands from sources that you do not control is always a potential
|
||||
security risk. For this reason, we have added some automatic checks when using
|
||||
remote Taskfiles:
|
||||
|
||||
1. When running a task from a remote Taskfile for the first time, Task will
|
||||
print a warning to the console asking you to check that you are sure that you
|
||||
trust the source of the Taskfile. If you do not accept the prompt, then Task
|
||||
will exit with code `104` (not trusted) and nothing will run. If you accept
|
||||
the prompt, the remote Taskfile will run and further calls to the remote
|
||||
Taskfile will not prompt you again.
|
||||
2. Whenever you run a remote Taskfile, Task will create and store a checksum of
|
||||
the file that you are running. If the checksum changes, then Task will print
|
||||
another warning to the console to inform you that the contents of the remote
|
||||
file has changed. If you do not accept the prompt, then Task will exit with
|
||||
code `104` (not trusted) and nothing will run. If you accept the prompt, the
|
||||
checksum will be updated and the remote Taskfile will run.
|
||||
|
||||
Sometimes you need to run Task in an environment that does not have an
|
||||
interactive terminal, so you are not able to accept a prompt. In these cases you
|
||||
are able to tell task to accept these prompts automatically by using the `--yes`
|
||||
flag or the `--trust` flag. The `--trust` flag allows you to specify trusted
|
||||
hosts for remote Taskfiles, while `--yes` applies to all prompts in Task. You
|
||||
can also configure trusted hosts in your [taskrc configuration](#trusted-hosts) using
|
||||
`remote.trusted-hosts`. Before enabling automatic trust, you should:
|
||||
|
||||
1. Be sure that you trust the source and contents of the remote Taskfile.
|
||||
2. Consider using a pinned version of the remote Taskfile (e.g. A link
|
||||
containing a commit hash) to prevent Task from automatically accepting a
|
||||
prompt that says a remote Taskfile has changed.
|
||||
|
||||
### Manual checksum pinning
|
||||
|
||||
Alternatively, if you expect the contents of your remote files to be a constant
|
||||
value, you can pin the checksum of the included file instead:
|
||||
|
||||
```yaml
|
||||
version: '3'
|
||||
|
||||
includes:
|
||||
included:
|
||||
taskfile: https://taskfile.dev
|
||||
checksum: c153e97e0b3a998a7ed2e61064c6ddaddd0de0c525feefd6bba8569827d8efe9
|
||||
```
|
||||
|
||||
This will disable the automatic checksum prompts discussed above. However, if
|
||||
the checksums do not match, Task will exit immediately with an error. When
|
||||
setting this up for the first time, you may not know the correct value of the
|
||||
checksum. There are a couple of ways you can obtain this:
|
||||
|
||||
1. Add the include normally without the `checksum` key. The first time you run
|
||||
the included Taskfile, a `.task/remote` temporary directory is created. Find
|
||||
the correct set of files for your included Taskfile and open the file that
|
||||
ends with `.checksum`. You can copy the contents of this file and paste it
|
||||
into the `checksum` key of your include. This method is safest as it allows
|
||||
you to inspect the downloaded Taskfile before you pin it.
|
||||
2. Alternatively, add the include with a temporary random value in the
|
||||
`checksum` key. When you try to run the Taskfile, you will get an error that
|
||||
will report the incorrect expected checksum and the actual checksum. You can
|
||||
copy the actual checksum and replace your temporary random value.
|
||||
|
||||
### TLS
|
||||
|
||||
Task currently supports both `http` and `https` URLs. However, the `http`
|
||||
requests will not execute by default unless you run the task with the
|
||||
`--insecure` flag. This is to protect you from accidentally running a remote
|
||||
Taskfile that is downloaded via an unencrypted connection. Sources that are not
|
||||
protected by TLS are vulnerable to man-in-the-middle attacks and should be
|
||||
avoided unless you know what you are doing.
|
||||
|
||||
#### Custom Certificates
|
||||
|
||||
If your remote Taskfiles are hosted on a server that uses a custom CA
|
||||
certificate (e.g., a corporate internal server), you can specify the CA
|
||||
certificate using the `--cacert` flag:
|
||||
|
||||
```shell
|
||||
task --taskfile https://internal.example.com/Taskfile.yml --cacert /path/to/ca.crt
|
||||
```
|
||||
|
||||
For servers that require client certificate authentication (mTLS), you can
|
||||
provide a client certificate and key:
|
||||
|
||||
```shell
|
||||
task --taskfile https://secure.example.com/Taskfile.yml \
|
||||
--cert /path/to/client.crt \
|
||||
--cert-key /path/to/client.key
|
||||
```
|
||||
|
||||
::: warning
|
||||
|
||||
Encrypted private keys are not currently supported. If your key is encrypted,
|
||||
you must decrypt it first:
|
||||
|
||||
```shell
|
||||
openssl rsa -in encrypted.key -out decrypted.key
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
These options can also be configured in the [configuration file](#configuration).
|
||||
|
||||
## Caching & Running Offline
|
||||
|
||||
Whenever you run a remote Taskfile, the latest copy will be downloaded from the
|
||||
internet and cached locally. This cached file will be used for all future
|
||||
invocations of the Taskfile until the cache expires. Once it expires, Task will
|
||||
download the latest copy of the file and update the cache. By default, the cache
|
||||
is set to expire immediately. This means that Task will always fetch the latest
|
||||
version. However, the cache expiry duration can be modified by setting the
|
||||
`--expiry` flag.
|
||||
|
||||
If for any reason you lose access to the internet or you are running Task in
|
||||
offline mode (via the `--offline` flag or `TASK_OFFLINE` environment variable),
|
||||
Task will run the any available cached files _even if they are expired_. This
|
||||
means that you should never be stuck without the ability to run your tasks as
|
||||
long as you have downloaded a remote Taskfile at least once.
|
||||
|
||||
By default, Task will timeout requests to download remote files after 10 seconds
|
||||
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 (`.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.
|
||||
|
||||
You can use the `--clear-cache` flag to clear all cached remote files.
|
||||
|
||||
## Configuration
|
||||
|
||||
This experiment adds a new `remote` section to the
|
||||
[configuration file](../reference/config.md).
|
||||
|
||||
- **Type**: `object`
|
||||
- **Description**: Remote configuration settings for handling remote Taskfiles
|
||||
|
||||
```yaml
|
||||
remote:
|
||||
insecure: false
|
||||
offline: false
|
||||
timeout: "30s"
|
||||
cache-expiry: "24h"
|
||||
cache-dir: ~/.task
|
||||
trusted-hosts:
|
||||
- github.com
|
||||
- gitlab.com
|
||||
cacert: ""
|
||||
cert: ""
|
||||
cert-key: ""
|
||||
```
|
||||
|
||||
#### `insecure`
|
||||
|
||||
- **Type**: `boolean`
|
||||
- **Default**: `false`
|
||||
- **Description**: Allow insecure connections when fetching remote Taskfiles
|
||||
- **CLI equivalent**: `--insecure`
|
||||
- **Environment variable**: `TASK_REMOTE_INSECURE`
|
||||
|
||||
```yaml
|
||||
remote:
|
||||
insecure: true
|
||||
```
|
||||
|
||||
#### `offline`
|
||||
|
||||
- **Type**: `boolean`
|
||||
- **Default**: `false`
|
||||
- **Description**: Work in offline mode, preventing remote Taskfile fetching
|
||||
- **CLI equivalent**: `--offline`
|
||||
- **Environment variable**: `TASK_REMOTE_OFFLINE`
|
||||
|
||||
```yaml
|
||||
remote:
|
||||
offline: true
|
||||
```
|
||||
|
||||
#### `timeout`
|
||||
|
||||
- **Type**: `string`
|
||||
- **Default**: 10s
|
||||
- **Pattern**: `^[0-9]+(ns|us|µs|ms|s|m|h)$`
|
||||
- **Description**: Timeout duration for remote operations (e.g., '30s', '5m')
|
||||
- **CLI equivalent**: `--timeout`
|
||||
- **Environment variable**: `TASK_REMOTE_TIMEOUT`
|
||||
|
||||
```yaml
|
||||
remote:
|
||||
timeout: "1m"
|
||||
```
|
||||
|
||||
#### `cache-expiry`
|
||||
|
||||
- **Type**: `string`
|
||||
- **Default**: 0s (no cache)
|
||||
- **Pattern**: `^[0-9]+(ns|us|µs|ms|s|m|h)$`
|
||||
- **Description**: Cache expiry duration for remote Taskfiles (e.g., '1h',
|
||||
'24h')
|
||||
- **CLI equivalent**: `--expiry`
|
||||
- **Environment variable**: `TASK_REMOTE_CACHE_EXPIRY`
|
||||
|
||||
```yaml
|
||||
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_CACHE_DIR`
|
||||
|
||||
```yaml
|
||||
remote:
|
||||
cache-dir: ~/.task
|
||||
```
|
||||
|
||||
#### `trusted-hosts`
|
||||
|
||||
- **Type**: `array of strings`
|
||||
- **Default**: `[]` (empty list)
|
||||
- **Description**: List of trusted hosts for remote Taskfiles. Hosts in this
|
||||
list will not prompt for confirmation when downloading Taskfiles
|
||||
- **CLI equivalent**: `--trusted-hosts`
|
||||
- **Environment variable**: `TASK_REMOTE_TRUSTED_HOSTS` (comma-separated)
|
||||
|
||||
```yaml
|
||||
remote:
|
||||
trusted-hosts:
|
||||
- github.com
|
||||
- gitlab.com
|
||||
- raw.githubusercontent.com
|
||||
- example.com:8080
|
||||
```
|
||||
|
||||
Hosts in the trusted hosts list will automatically be trusted without prompting for
|
||||
confirmation when they are first downloaded or when their checksums change. The
|
||||
host matching includes the port if specified in the URL. Use with caution and
|
||||
only add hosts you fully trust.
|
||||
|
||||
You can also specify trusted hosts via the command line:
|
||||
|
||||
```shell
|
||||
# Trust specific host for this execution
|
||||
task --trusted-hosts github.com -t https://github.com/user/repo.git//Taskfile.yml
|
||||
|
||||
# Trust multiple hosts (comma-separated)
|
||||
task --trusted-hosts github.com,gitlab.com -t https://github.com/user/repo.git//Taskfile.yml
|
||||
|
||||
# Trust a host with a specific port
|
||||
task --trusted-hosts example.com:8080 -t https://example.com:8080/Taskfile.yml
|
||||
```
|
||||
|
||||
#### `cacert`
|
||||
|
||||
- **Type**: `string`
|
||||
- **Default**: `""`
|
||||
- **Description**: Path to a custom CA certificate file for TLS verification
|
||||
|
||||
```yaml
|
||||
remote:
|
||||
cacert: "/path/to/ca.crt"
|
||||
```
|
||||
|
||||
#### `cert`
|
||||
|
||||
- **Type**: `string`
|
||||
- **Default**: `""`
|
||||
- **Description**: Path to a client certificate file for mTLS authentication
|
||||
|
||||
```yaml
|
||||
remote:
|
||||
cert: "/path/to/client.crt"
|
||||
```
|
||||
|
||||
#### `cert-key`
|
||||
|
||||
- **Type**: `string`
|
||||
- **Default**: `""`
|
||||
- **Description**: Path to the client certificate private key file
|
||||
|
||||
```yaml
|
||||
remote:
|
||||
cert-key: "/path/to/client.key"
|
||||
```
|
||||
[changelog]: ../changelog.md#v3511---2026-05-16
|
||||
[remote-taskfile-docs]: ../remote-taskfiles.md
|
||||
[blog-post]: ../../blog/remote-taskfiles
|
||||
|
||||
@@ -91,7 +91,7 @@ tasks:
|
||||
|
||||
:::
|
||||
|
||||
### Reading a Taskfile from stdin
|
||||
### Running a Taskfile from stdin
|
||||
|
||||
Taskfile also supports reading from stdin. This is useful if you are generating
|
||||
Taskfiles dynamically and don't want write them to disk. To tell task to read
|
||||
@@ -104,6 +104,41 @@ task -t - < ./Taskfile.yml
|
||||
cat ./Taskfile.yml | task -t -
|
||||
```
|
||||
|
||||
### Running a remote Taskfile
|
||||
|
||||
::: danger
|
||||
|
||||
Never run remote Taskfiles from sources that you do not trust.
|
||||
|
||||
:::
|
||||
|
||||
It is possible to directly run a Taskfile from a remote source via HTTP(S) or
|
||||
Git by using the `--taskfile`/`-t` flag. This is useful if you want to reuse a
|
||||
set of tasks in multiple projects. For more information, take a look at our
|
||||
[remote Taskfiles documentation](./remote-taskfiles.md).
|
||||
|
||||
::: code-group
|
||||
|
||||
```shell [HTTP/HTTPS]
|
||||
$ task --taskfile https://raw.githubusercontent.com/go-task/task/main/website/src/public/Taskfile.yml
|
||||
task: [hello] echo "Hello Task!"
|
||||
Hello Task!
|
||||
```
|
||||
|
||||
```shell [Git over HTTP]
|
||||
$ task --taskfile https://github.com/go-task/task.git//website/src/public/Taskfile.yml?ref=main
|
||||
task: [hello] echo "Hello Task!"
|
||||
Hello Task!
|
||||
```
|
||||
|
||||
```shell [Git over SSH]
|
||||
$ task --taskfile git@github.com/go-task/task.git//website/src/public/Taskfile.yml?ref=main
|
||||
task: [hello] echo "Hello Task!"
|
||||
Hello Task!
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
## Environment variables
|
||||
|
||||
### Task
|
||||
@@ -248,6 +283,26 @@ the `DockerTasks.yml` file.
|
||||
Relative paths are resolved relative to the directory containing the including
|
||||
Taskfile.
|
||||
|
||||
### Remote Taskfiles
|
||||
|
||||
::: danger
|
||||
|
||||
Never run remote Taskfiles from sources that you do not trust.
|
||||
|
||||
:::
|
||||
|
||||
It is possible to include a Taskfile from a remote source via HTTP(S) or Git.
|
||||
This is useful if you want to reuse a set of tasks in multiple projects. For
|
||||
more information, take a look at our
|
||||
[remote Taskfiles documentation](./remote-taskfiles.md).
|
||||
|
||||
```yaml
|
||||
version: '3'
|
||||
|
||||
includes:
|
||||
my-remote-namespace: https://raw.githubusercontent.com/go-task/task/main/website/src/public/Taskfile.yml
|
||||
```
|
||||
|
||||
### OS-specific Taskfiles
|
||||
|
||||
You can include OS-specific Taskfiles by using a templating function:
|
||||
@@ -940,7 +995,8 @@ You can use `--force` or `-f` if you want to force a task to run even when
|
||||
up-to-date.
|
||||
|
||||
Also, `task --status [tasks]...` will exit with a non-zero
|
||||
[exit code](/docs/reference/cli#exit-codes) if any of the tasks are not up-to-date.
|
||||
[exit code](/docs/reference/cli#exit-codes) if any of the tasks are not
|
||||
up-to-date.
|
||||
|
||||
`status` can be combined with the
|
||||
[fingerprinting](#by-fingerprinting-locally-generated-files-and-their-sources)
|
||||
@@ -1024,8 +1080,8 @@ tasks:
|
||||
|
||||
The `if` attribute allows you to conditionally skip tasks or commands based on a
|
||||
shell command's exit code. Unlike `preconditions` which fail and stop execution,
|
||||
`if` simply skips the task or command when the condition is not met and continues
|
||||
with the rest of the Taskfile.
|
||||
`if` simply skips the task or command when the condition is not met and
|
||||
continues with the rest of the Taskfile.
|
||||
|
||||
#### Task-level `if`
|
||||
|
||||
@@ -1061,9 +1117,9 @@ tasks:
|
||||
|
||||
#### Using templates in `if` conditions
|
||||
|
||||
You can use Go template expressions in `if` conditions. Template expressions like
|
||||
<span v-pre>`{{eq .VAR "value"}}`</span> evaluate to `true` or `false`, which are valid shell
|
||||
commands (`true` exits with 0, `false` exits with 1):
|
||||
You can use Go template expressions in `if` conditions. Template expressions
|
||||
like <span v-pre>`{{eq .VAR "value"}}`</span> evaluate to `true` or `false`,
|
||||
which are valid shell commands (`true` exits with 0, `false` exits with 1):
|
||||
|
||||
```yaml
|
||||
version: '3'
|
||||
@@ -1071,7 +1127,7 @@ version: '3'
|
||||
tasks:
|
||||
conditional:
|
||||
vars:
|
||||
ENABLE_FEATURE: "true"
|
||||
ENABLE_FEATURE: 'true'
|
||||
cmds:
|
||||
- cmd: echo "Feature is enabled"
|
||||
if: '{{eq .ENABLE_FEATURE "true"}}'
|
||||
@@ -1081,7 +1137,8 @@ tasks:
|
||||
|
||||
#### Using `if` with `for` loops
|
||||
|
||||
When used inside a `for` loop, the `if` condition is evaluated for each iteration:
|
||||
When used inside a `for` loop, the `if` condition is evaluated for each
|
||||
iteration:
|
||||
|
||||
```yaml
|
||||
version: '3'
|
||||
@@ -1103,11 +1160,11 @@ processing c
|
||||
|
||||
#### `if` vs `preconditions`
|
||||
|
||||
| Aspect | `if` | `preconditions` |
|
||||
|--------|------|-----------------|
|
||||
| On failure | Skips (continues) | Fails (stops) |
|
||||
| Message | Only in verbose mode | Always shown |
|
||||
| Use case | "Run if possible" | "Must be true" |
|
||||
| Aspect | `if` | `preconditions` |
|
||||
| ---------- | -------------------- | --------------- |
|
||||
| On failure | Skips (continues) | Fails (stops) |
|
||||
| Message | Only in verbose mode | Always shown |
|
||||
| Use case | "Run if possible" | "Must be true" |
|
||||
|
||||
Use `if` when you want optional conditional execution that shouldn't stop the
|
||||
workflow. Use `preconditions` when the condition must be met for the task to
|
||||
@@ -1337,8 +1394,8 @@ $ task deploy
|
||||
Deploying 1.0.0 to prod
|
||||
```
|
||||
|
||||
If the variable is already set (via CLI, environment, or Taskfile), no prompt
|
||||
is shown:
|
||||
If the variable is already set (via CLI, environment, or Taskfile), no prompt is
|
||||
shown:
|
||||
|
||||
```shell
|
||||
$ task deploy ENVIRONMENT=prod VERSION=1.0.0
|
||||
@@ -1638,8 +1695,8 @@ in logs, but is **not a substitute** for proper secret management practices.
|
||||
- ❌ Secrets in command output (stdout/stderr)
|
||||
- ❌ Secret values copied into derived (non-secret) variables
|
||||
|
||||
Always use proper secret management tools (HashiCorp Vault, AWS Secrets
|
||||
Manager, etc.) for production environments.
|
||||
Always use proper secret management tools (HashiCorp Vault, AWS Secrets Manager,
|
||||
etc.) for production environments.
|
||||
|
||||
:::
|
||||
|
||||
@@ -1767,7 +1824,7 @@ tasks:
|
||||
If you use dotenv files, add them to `.gitignore`:
|
||||
|
||||
```yaml
|
||||
dotenv: ['.env.local'] # Load from .env.local (in .gitignore)
|
||||
dotenv: ['.env.local'] # Load from .env.local (in .gitignore)
|
||||
```
|
||||
|
||||
:::
|
||||
@@ -1844,8 +1901,7 @@ tasks:
|
||||
matrix:
|
||||
OS: ['windows', 'linux', 'darwin']
|
||||
ARCH: ['amd64', 'arm64']
|
||||
cmd:
|
||||
echo "{{.ITEM.OS}}/{{.ITEM.ARCH}}"
|
||||
cmd: echo "{{.ITEM.OS}}/{{.ITEM.ARCH}}"
|
||||
```
|
||||
|
||||
This will output:
|
||||
@@ -1877,8 +1933,7 @@ tasks:
|
||||
ref: .OS_VAR
|
||||
ARCH:
|
||||
ref: .ARCH_VAR
|
||||
cmd:
|
||||
echo "{{.ITEM.OS}}/{{.ITEM.ARCH}}"
|
||||
cmd: echo "{{.ITEM.OS}}/{{.ITEM.ARCH}}"
|
||||
```
|
||||
|
||||
### Looping over your task's sources or generated files
|
||||
@@ -1923,8 +1978,8 @@ files that match that glob.
|
||||
Paths will always be returned as paths relative to the task directory. If you
|
||||
need to convert this to an absolute path, you can use the built-in `joinPath`
|
||||
function. There are some
|
||||
[special variables](/docs/reference/templating#special-variables) that you may find
|
||||
useful for this.
|
||||
[special variables](/docs/reference/templating#special-variables) that you may
|
||||
find useful for this.
|
||||
|
||||
::: code-group
|
||||
|
||||
@@ -2201,8 +2256,9 @@ $ task start:foo:3
|
||||
Starting foo with 3 replicas
|
||||
```
|
||||
|
||||
Using wildcards with aliases
|
||||
Wildcards also work with aliases. If a task has an alias, you can use the alias name with wildcards to capture arguments. For example:
|
||||
Using wildcards with aliases Wildcards also work with aliases. If a task has an
|
||||
alias, you can use the alias name with wildcards to capture arguments. For
|
||||
example:
|
||||
|
||||
```yaml
|
||||
version: '3'
|
||||
@@ -2211,11 +2267,12 @@ tasks:
|
||||
start:*:
|
||||
aliases: [run:*]
|
||||
vars:
|
||||
SERVICE: "{{index .MATCH 0}}"
|
||||
SERVICE: '{{index .MATCH 0}}'
|
||||
cmds:
|
||||
- echo "Running {{.SERVICE}}"
|
||||
```
|
||||
In this example, you can call the task using the alias run:*:
|
||||
|
||||
In this example, you can call the task using the alias run:\*:
|
||||
|
||||
```shell
|
||||
$ task run:foo
|
||||
@@ -2266,8 +2323,8 @@ commands are executed in the reverse order if you schedule multiple of them.
|
||||
:::
|
||||
|
||||
A special variable `.EXIT_CODE` is exposed when a command exited with a non-zero
|
||||
[exit code](/docs/reference/cli#exit-codes). You can check its presence to know if
|
||||
the task completed successfully or not:
|
||||
[exit code](/docs/reference/cli#exit-codes). You can check its presence to know
|
||||
if the task completed successfully or not:
|
||||
|
||||
```yaml
|
||||
version: '3'
|
||||
@@ -2276,7 +2333,8 @@ tasks:
|
||||
default:
|
||||
cmds:
|
||||
- defer:
|
||||
echo '{{if .EXIT_CODE}}Failed with {{.EXIT_CODE}}!{{else}}Success!{{end}}'
|
||||
echo '{{if .EXIT_CODE}}Failed with
|
||||
{{.EXIT_CODE}}!{{else}}Success!{{end}}'
|
||||
- exit 1
|
||||
```
|
||||
|
||||
@@ -2468,8 +2526,8 @@ tasks:
|
||||
```
|
||||
|
||||
Warning prompts are called before executing a task. If a prompt is denied Task
|
||||
will exit with [exit code](/docs/reference/cli#exit-codes) 205. If approved, Task
|
||||
will continue as normal.
|
||||
will exit with [exit code](/docs/reference/cli#exit-codes) 205. If approved,
|
||||
Task will continue as normal.
|
||||
|
||||
```shell
|
||||
❯ task example
|
||||
@@ -2863,8 +2921,8 @@ if called by another task, either directly or as a dependency.
|
||||
The watcher can misbehave in certain scenarios, in particular for long-running
|
||||
servers. There is a [known bug](https://github.com/go-task/task/issues/160)
|
||||
where child processes of the running might not be killed appropriately. It's
|
||||
advised to avoid running commands as `go run` and prefer `go build [...] &&
|
||||
./binary` instead.
|
||||
advised to avoid running commands as `go run` and prefer
|
||||
`go build [...] && ./binary` instead.
|
||||
|
||||
If you are having issues, you might want to try tools specifically designed for
|
||||
live-reloading, like [Air](https://github.com/air-verse/air/). Also, be sure to
|
||||
|
||||
@@ -128,7 +128,8 @@ Disable fuzzy matching for task names. When enabled, Task will not suggest
|
||||
similar task names when you mistype a task name.
|
||||
|
||||
- **Config equivalent**: [`disable-fuzzy`](./config.md#disable-fuzzy)
|
||||
- **Environment variable**: [`TASK_DISABLE_FUZZY`](./environment.md#task-disable-fuzzy)
|
||||
- **Environment variable**:
|
||||
[`TASK_DISABLE_FUZZY`](./environment.md#task-disable-fuzzy)
|
||||
|
||||
```bash
|
||||
task buidl --disable-fuzzy
|
||||
@@ -180,7 +181,8 @@ task test lint --parallel
|
||||
Limit the number of concurrent tasks. Zero means unlimited.
|
||||
|
||||
- **Config equivalent**: [`concurrency`](./config.md#concurrency)
|
||||
- **Environment variable**: [`TASK_CONCURRENCY`](./environment.md#task-concurrency)
|
||||
- **Environment variable**:
|
||||
[`TASK_CONCURRENCY`](./environment.md#task-concurrency)
|
||||
|
||||
```bash
|
||||
task test --concurrency 4
|
||||
@@ -248,7 +250,8 @@ task test --output group
|
||||
|
||||
Message template to print before grouped output.
|
||||
|
||||
- **Environment variable**: [`TASK_OUTPUT_GROUP_BEGIN`](./environment.md#task-output-group-begin)
|
||||
- **Environment variable**:
|
||||
[`TASK_OUTPUT_GROUP_BEGIN`](./environment.md#task-output-group-begin)
|
||||
|
||||
```bash
|
||||
task test --output group --output-group-begin "::group::{{.TASK}}"
|
||||
@@ -258,7 +261,8 @@ task test --output group --output-group-begin "::group::{{.TASK}}"
|
||||
|
||||
Message template to print after grouped output.
|
||||
|
||||
- **Environment variable**: [`TASK_OUTPUT_GROUP_END`](./environment.md#task-output-group-end)
|
||||
- **Environment variable**:
|
||||
[`TASK_OUTPUT_GROUP_END`](./environment.md#task-output-group-end)
|
||||
|
||||
```bash
|
||||
task test --output group --output-group-end "::endgroup::"
|
||||
@@ -268,7 +272,8 @@ task test --output group --output-group-end "::endgroup::"
|
||||
|
||||
Only show command output on non-zero exit codes.
|
||||
|
||||
- **Environment variable**: [`TASK_OUTPUT_GROUP_ERROR_ONLY`](./environment.md#task-output-group-error-only)
|
||||
- **Environment variable**:
|
||||
[`TASK_OUTPUT_GROUP_ERROR_ONLY`](./environment.md#task-output-group-error-only)
|
||||
|
||||
```bash
|
||||
task test --output group --output-group-error-only
|
||||
@@ -351,7 +356,8 @@ task build --watch --interval 1s
|
||||
|
||||
Automatically answer "yes" to all prompts.
|
||||
|
||||
- **Environment variable**: [`TASK_ASSUME_YES`](./environment.md#task-assume-yes)
|
||||
- **Environment variable**:
|
||||
[`TASK_ASSUME_YES`](./environment.md#task-assume-yes)
|
||||
|
||||
```bash
|
||||
task deploy --yes
|
||||
@@ -366,12 +372,69 @@ Task automatically detects non-TTY environments (like CI pipelines) and skips
|
||||
prompts. This flag can also be set in `.taskrc.yml` to enable prompts by
|
||||
default.
|
||||
|
||||
- **Environment variable**: [`TASK_INTERACTIVE`](./environment.md#task-interactive)
|
||||
- **Environment variable**:
|
||||
[`TASK_INTERACTIVE`](./environment.md#task-interactive)
|
||||
|
||||
```bash
|
||||
task deploy --interactive
|
||||
```
|
||||
|
||||
### Remote
|
||||
|
||||
The following flags are used to control the behavior of
|
||||
[remote Taskfiles](../remote-taskfiles.md).
|
||||
|
||||
#### `--insecure`
|
||||
|
||||
Allow insecure connections when fetching remote Taskfiles.
|
||||
|
||||
#### `--offline`
|
||||
|
||||
Work in offline mode, preventing remote Taskfile fetching.
|
||||
|
||||
#### `--download`
|
||||
|
||||
Forces task to download remote Taskfiles and ignore any cached versions.
|
||||
|
||||
#### `--timeout`
|
||||
|
||||
Timeout duration for remote operations (e.g., '30s', '5m').
|
||||
|
||||
#### `--clear-cache`
|
||||
|
||||
Wipe the cache of remote Taskfiles and checksums.
|
||||
|
||||
#### `--expiry`
|
||||
|
||||
Cache expiry duration for remote Taskfiles (e.g., '1h', '24h').
|
||||
|
||||
#### `--remote-cache-dir`
|
||||
|
||||
Directory where remote Taskfiles are cached. Can be an absolute path (e.g.,
|
||||
`/var/cache/task`) or relative to the Taskfile directory.
|
||||
|
||||
#### `--trusted-hosts`
|
||||
|
||||
List of (comma-separated) trusted hosts for remote Taskfiles. Hosts in this list
|
||||
will not prompt for confirmation when downloading Taskfiles.
|
||||
|
||||
Hosts in the trusted hosts list will automatically be trusted without prompting
|
||||
for confirmation when they are first downloaded or when their checksums change.
|
||||
The host matching includes the port if specified in the URL. Use with caution
|
||||
and only add hosts you fully trust.
|
||||
|
||||
#### `--cacert`
|
||||
|
||||
Path to a custom CA certificate file for TLS verification.
|
||||
|
||||
#### `--cert`
|
||||
|
||||
Path to a client certificate file for mTLS authentication.
|
||||
|
||||
#### `--cert-key`
|
||||
|
||||
Path to the client certificate private key file.
|
||||
|
||||
## Exit Codes
|
||||
|
||||
Task uses specific exit codes to indicate different types of errors:
|
||||
|
||||
@@ -108,7 +108,8 @@ silent: true
|
||||
|
||||
- **Type**: `boolean`
|
||||
- **Default**: `true`
|
||||
- **Description**: Enable colored output. Colors are automatically enabled in CI environments (`CI=true`).
|
||||
- **Description**: Enable colored output. Colors are automatically enabled in CI
|
||||
environments (`CI=true`).
|
||||
- **CLI equivalent**: [`-c, --color`](./cli.md#-c---color)
|
||||
- **Environment variable**: [`TASK_COLOR`](./environment.md#task-color)
|
||||
|
||||
@@ -120,9 +121,11 @@ color: false
|
||||
|
||||
- **Type**: `boolean`
|
||||
- **Default**: `false`
|
||||
- **Description**: Disable fuzzy matching for task names. When enabled, Task will not suggest similar task names when you mistype a task name.
|
||||
- **Description**: Disable fuzzy matching for task names. When enabled, Task
|
||||
will not suggest similar task names when you mistype a task name.
|
||||
- **CLI equivalent**: [`--disable-fuzzy`](./cli.md#--disable-fuzzy)
|
||||
- **Environment variable**: [`TASK_DISABLE_FUZZY`](./environment.md#task-disable-fuzzy)
|
||||
- **Environment variable**:
|
||||
[`TASK_DISABLE_FUZZY`](./environment.md#task-disable-fuzzy)
|
||||
|
||||
```yaml
|
||||
disable-fuzzy: true
|
||||
@@ -134,7 +137,8 @@ disable-fuzzy: true
|
||||
- **Minimum**: `1`
|
||||
- **Description**: Number of concurrent tasks to run
|
||||
- **CLI equivalent**: [`-C, --concurrency`](./cli.md#-c---concurrency-number)
|
||||
- **Environment variable**: [`TASK_CONCURRENCY`](./environment.md#task-concurrency)
|
||||
- **Environment variable**:
|
||||
[`TASK_CONCURRENCY`](./environment.md#task-concurrency)
|
||||
|
||||
```yaml
|
||||
concurrency: 4
|
||||
@@ -158,8 +162,8 @@ failfast: true
|
||||
- **Default**: `false`
|
||||
- **Description**: Prompt for missing required variables instead of failing.
|
||||
When enabled, Task will display an interactive prompt for any missing required
|
||||
variable. Requires a TTY. Task automatically detects non-TTY environments
|
||||
(CI pipelines, etc.) and skips prompts.
|
||||
variable. Requires a TTY. Task automatically detects non-TTY environments (CI
|
||||
pipelines, etc.) and skips prompts.
|
||||
- **CLI equivalent**: [`--interactive`](./cli.md#--interactive)
|
||||
|
||||
```yaml
|
||||
@@ -178,6 +182,157 @@ interactive: true
|
||||
temp-dir: .task
|
||||
```
|
||||
|
||||
### `remote`
|
||||
|
||||
- **Type**: `object`
|
||||
- **Description**: Remote configuration settings for handling
|
||||
[remote Taskfiles](../remote-taskfiles.md).
|
||||
|
||||
#### `remote.insecure`
|
||||
|
||||
- **Type**: `boolean`
|
||||
- **Default**: `false`
|
||||
- **Description**: Allow insecure connections when fetching remote Taskfiles
|
||||
- **CLI equivalent**: `--insecure`
|
||||
- **Environment variable**:
|
||||
[`TASK_REMOTE_INSECURE`](./environment.md#task_remote_insecure)
|
||||
|
||||
```yaml
|
||||
remote:
|
||||
insecure: true
|
||||
```
|
||||
|
||||
#### `remote.offline`
|
||||
|
||||
- **Type**: `boolean`
|
||||
- **Default**: `false`
|
||||
- **Description**: Work in offline mode, preventing remote Taskfile fetching
|
||||
- **CLI equivalent**: `--offline`
|
||||
- **Environment variable**:
|
||||
[`TASK_REMOTE_OFFLINE`](./environment.md#task_remote_offline)
|
||||
|
||||
```yaml
|
||||
remote:
|
||||
offline: true
|
||||
```
|
||||
|
||||
#### `remote.timeout`
|
||||
|
||||
- **Type**: `string`
|
||||
- **Default**: 10s
|
||||
- **Pattern**: `^[0-9]+(ns|us|µs|ms|s|m|h)$`
|
||||
- **Description**: Timeout duration for remote operations (e.g., '30s', '5m')
|
||||
- **CLI equivalent**: `--timeout`
|
||||
- **Environment variable**:
|
||||
[`TASK_REMOTE_TIMEOUT`](./environment.md#task_remote_timeout)
|
||||
|
||||
```yaml
|
||||
remote:
|
||||
timeout: '1m'
|
||||
```
|
||||
|
||||
#### `remote.cache-expiry`
|
||||
|
||||
- **Type**: `string`
|
||||
- **Default**: 0s (no cache)
|
||||
- **Pattern**: `^[0-9]+(ns|us|µs|ms|s|m|h)$`
|
||||
- **Description**: Cache expiry duration for remote Taskfiles (e.g., '1h',
|
||||
'24h')
|
||||
- **CLI equivalent**: `--expiry`
|
||||
- **Environment variable**:
|
||||
[`TASK_REMOTE_CACHE_EXPIRY`](./environment.md#task_remote_cache_expiry)
|
||||
|
||||
```yaml
|
||||
remote:
|
||||
cache-expiry: '6h'
|
||||
```
|
||||
|
||||
#### `remote.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_CACHE_DIR`](./environment.md#task_remote_cache_dir)
|
||||
|
||||
```yaml
|
||||
remote:
|
||||
cache-dir: ~/.task
|
||||
```
|
||||
|
||||
#### `remote.trusted-hosts`
|
||||
|
||||
- **Type**: `array of strings`
|
||||
- **Default**: `[]` (empty list)
|
||||
- **Description**: List of trusted hosts for remote Taskfiles. Hosts in this
|
||||
list will not prompt for confirmation when downloading Taskfiles
|
||||
- **CLI equivalent**: `--trusted-hosts`
|
||||
- **Environment variable**:
|
||||
[`TASK_REMOTE_TRUSTED_HOSTS`](./environment.md#task_remote_trusted_hosts)
|
||||
(comma-separated)
|
||||
|
||||
```yaml
|
||||
remote:
|
||||
trusted-hosts:
|
||||
- github.com
|
||||
- gitlab.com
|
||||
- raw.githubusercontent.com
|
||||
- example.com:8080
|
||||
```
|
||||
|
||||
Hosts in the trusted hosts list will automatically be trusted without prompting
|
||||
for confirmation when they are first downloaded or when their checksums change.
|
||||
The host matching includes the port if specified in the URL. Use with caution
|
||||
and only add hosts you fully trust.
|
||||
|
||||
You can also specify trusted hosts via the command line:
|
||||
|
||||
```shell
|
||||
# Trust specific host for this execution
|
||||
task --trusted-hosts github.com -t https://github.com/user/repo.git//Taskfile.yml
|
||||
|
||||
# Trust multiple hosts (comma-separated)
|
||||
task --trusted-hosts github.com,gitlab.com -t https://github.com/user/repo.git//Taskfile.yml
|
||||
|
||||
# Trust a host with a specific port
|
||||
task --trusted-hosts example.com:8080 -t https://example.com:8080/Taskfile.yml
|
||||
```
|
||||
|
||||
#### `remote.cacert`
|
||||
|
||||
- **Type**: `string`
|
||||
- **Default**: `""`
|
||||
- **Description**: Path to a custom CA certificate file for TLS verification
|
||||
|
||||
```yaml
|
||||
remote:
|
||||
cacert: '/path/to/ca.crt'
|
||||
```
|
||||
|
||||
#### `remote.cert`
|
||||
|
||||
- **Type**: `string`
|
||||
- **Default**: `""`
|
||||
- **Description**: Path to a client certificate file for mTLS authentication
|
||||
|
||||
```yaml
|
||||
remote:
|
||||
cert: '/path/to/client.crt'
|
||||
```
|
||||
|
||||
#### `remote.cert-key`
|
||||
|
||||
- **Type**: `string`
|
||||
- **Default**: `""`
|
||||
- **Description**: Path to the client certificate private key file
|
||||
|
||||
```yaml
|
||||
remote:
|
||||
cert-key: '/path/to/client.key'
|
||||
```
|
||||
|
||||
## Example Configuration
|
||||
|
||||
Here's a complete example of a `.taskrc.yml` file with all available options:
|
||||
@@ -190,7 +345,20 @@ color: true
|
||||
disable-fuzzy: false
|
||||
concurrency: 2
|
||||
temp-dir: .task
|
||||
remote:
|
||||
insecure: false
|
||||
offline: false
|
||||
timeout: '30s'
|
||||
cache-expiry: '24h'
|
||||
cache-dir: ~/.task
|
||||
trusted-hosts:
|
||||
- github.com
|
||||
- gitlab.com
|
||||
cacert: ''
|
||||
cert: ''
|
||||
cert-key: ''
|
||||
|
||||
# Enable experimental features
|
||||
experiments:
|
||||
REMOTE_TASKFILES: 1
|
||||
GENTLE_FORCE: 1
|
||||
```
|
||||
|
||||
@@ -20,7 +20,8 @@ their configuration file equivalents.
|
||||
## Variables
|
||||
|
||||
All [configuration file options](./config.md) can also be set via environment
|
||||
variables. The priority order is: CLI flags > environment variables > config files > defaults.
|
||||
variables. The priority order is: CLI flags > environment variables > config
|
||||
files > defaults.
|
||||
|
||||
### `TASK_VERBOSE`
|
||||
|
||||
@@ -67,7 +68,8 @@ variables. The priority order is: CLI flags > environment variables > config fil
|
||||
|
||||
- **Type**: `boolean` (`true`, `false`, `1`, `0`)
|
||||
- **Default**: `false`
|
||||
- **Description**: Compiles and prints tasks in the order that they would be run, without executing them
|
||||
- **Description**: Compiles and prints tasks in the order that they would be
|
||||
run, without executing them
|
||||
|
||||
### `TASK_ASSUME_YES`
|
||||
|
||||
@@ -92,14 +94,16 @@ variables. The priority order is: CLI flags > environment variables > config fil
|
||||
- **Type**: `string`
|
||||
- **Description**: Message template to print before a task's grouped output.
|
||||
Only applies when the output style is `group`.
|
||||
- **CLI equivalent**: [`--output-group-begin`](./cli.md#--output-group-begin-template)
|
||||
- **CLI equivalent**:
|
||||
[`--output-group-begin`](./cli.md#--output-group-begin-template)
|
||||
|
||||
### `TASK_OUTPUT_GROUP_END`
|
||||
|
||||
- **Type**: `string`
|
||||
- **Description**: Message template to print after a task's grouped output.
|
||||
Only applies when the output style is `group`.
|
||||
- **CLI equivalent**: [`--output-group-end`](./cli.md#--output-group-end-template)
|
||||
- **Description**: Message template to print after a task's grouped output. Only
|
||||
applies when the output style is `group`.
|
||||
- **CLI equivalent**:
|
||||
[`--output-group-end`](./cli.md#--output-group-end-template)
|
||||
|
||||
### `TASK_OUTPUT_GROUP_ERROR_ONLY`
|
||||
|
||||
@@ -107,7 +111,8 @@ variables. The priority order is: CLI flags > environment variables > config fil
|
||||
- **Default**: `false`
|
||||
- **Description**: Swallow output from successful tasks. Only applies when the
|
||||
output style is `group`.
|
||||
- **CLI equivalent**: [`--output-group-error-only`](./cli.md#--output-group-error-only)
|
||||
- **CLI equivalent**:
|
||||
[`--output-group-error-only`](./cli.md#--output-group-error-only)
|
||||
|
||||
### `TASK_TEMP_DIR`
|
||||
|
||||
@@ -118,16 +123,64 @@ Taskfile, not the working directory. Defaults to: `./.task`.
|
||||
|
||||
### `TASK_CORE_UTILS`
|
||||
|
||||
This env controls whether the Bash interpreter will use its own
|
||||
core utilities implemented in Go, or the ones available in the system.
|
||||
Valid values are `true` (`1`) or `false` (`0`). By default, this is `true` on
|
||||
Windows and `false` on other operating systems. We might consider making this
|
||||
enabled by default on all platforms in the future.
|
||||
This env controls whether the Bash interpreter will use its own core utilities
|
||||
implemented in Go, or the ones available in the system. Valid values are `true`
|
||||
(`1`) or `false` (`0`). By default, this is `true` on Windows and `false` on
|
||||
other operating systems. We might consider making this enabled by default on all
|
||||
platforms in the future.
|
||||
|
||||
### `FORCE_COLOR`
|
||||
|
||||
Force color output usage.
|
||||
|
||||
## Remote Taskfile Variables
|
||||
|
||||
The following variables are used to control the behavior of
|
||||
[remote Taskfiles](../remote-taskfiles.md).
|
||||
|
||||
### `TASK_REMOTE_INSECURE`
|
||||
|
||||
Allow insecure connections when fetching remote Taskfiles.
|
||||
|
||||
### `TASK_REMOTE_OFFLINE`
|
||||
|
||||
Work in offline mode, preventing remote Taskfile fetching.
|
||||
|
||||
### `TASK_REMOTE_TIMEOUT`
|
||||
|
||||
Timeout duration for remote operations (e.g., '30s', '5m').
|
||||
|
||||
### `TASK_REMOTE_CACHE_EXPIRY`
|
||||
|
||||
Cache expiry duration for remote Taskfiles (e.g., '1h', '24h').
|
||||
|
||||
### `TASK_REMOTE_CACHE_DIR`
|
||||
|
||||
Directory where remote Taskfiles are cached. Can be an absolute path (e.g.,
|
||||
`/var/cache/task`) or relative to the Taskfile directory.
|
||||
|
||||
### `TASK_REMOTE_TRUSTED_HOSTS`
|
||||
|
||||
List of (comma-separated) trusted hosts for remote Taskfiles. Hosts in this list
|
||||
will not prompt for confirmation when downloading Taskfiles.
|
||||
|
||||
Hosts in the trusted hosts list will automatically be trusted without prompting
|
||||
for confirmation when they are first downloaded or when their checksums change.
|
||||
The host matching includes the port if specified in the URL. Use with caution
|
||||
and only add hosts you fully trust.
|
||||
|
||||
### `TASK_REMOTE_CACERT`
|
||||
|
||||
Path to a custom CA certificate file for TLS verification.
|
||||
|
||||
### `TASK_REMOTE_CERT`
|
||||
|
||||
Path to a client certificate file for mTLS authentication.
|
||||
|
||||
### `TASK_REMOTE_CERT_KEY`
|
||||
|
||||
Path to the client certificate private key file.
|
||||
|
||||
### Custom Colors
|
||||
|
||||
All color variables are [ANSI color codes][ansi]. You can specify multiple codes
|
||||
|
||||
336
website/src/docs/remote-taskfiles.md
Normal file
336
website/src/docs/remote-taskfiles.md
Normal file
@@ -0,0 +1,336 @@
|
||||
---
|
||||
outline: deep
|
||||
---
|
||||
|
||||
# Remote Taskfiles
|
||||
|
||||
::: danger
|
||||
|
||||
Never run remote Taskfiles from sources that you do not trust.
|
||||
|
||||
:::
|
||||
|
||||
Task allows you to use Taskfiles which are stored in remote locations. This
|
||||
applies to both the root Taskfile (aka. Entrypoint) and also when including
|
||||
Taskfiles.
|
||||
|
||||
Task uses "nodes" to reference remote Taskfiles. There are a few different types
|
||||
of node which you can use:
|
||||
|
||||
::: code-group
|
||||
|
||||
```text [HTTP/HTTPS]
|
||||
https://raw.githubusercontent.com/go-task/task/main/website/src/public/Taskfile.yml
|
||||
```
|
||||
|
||||
```text [Git over HTTP]
|
||||
https://github.com/go-task/task.git//website/src/public/Taskfile.yml?ref=main
|
||||
```
|
||||
|
||||
```text [Git over SSH]
|
||||
git@github.com/go-task/task.git//website/src/public/Taskfile.yml?ref=main
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
## Node Types
|
||||
|
||||
### HTTP/HTTPS
|
||||
|
||||
`https://raw.githubusercontent.com/go-task/task/main/website/src/public/Taskfile.yml`
|
||||
|
||||
This is the most basic type of remote node and works by downloading the file
|
||||
from the specified URL. The file must be a valid Taskfile and can be of any
|
||||
name. If a file is not found at the specified URL, Task will append each of the
|
||||
supported file names in turn until it finds a valid file. If it still does not
|
||||
find a valid Taskfile, an error is returned.
|
||||
|
||||
### Git over HTTP
|
||||
|
||||
`https://github.com/go-task/task.git//website/src/public/Taskfile.yml?ref=main`
|
||||
|
||||
This type of node works by downloading the file from a Git repository over
|
||||
HTTP/HTTPS. The first part of the URL is the base URL of the Git repository.
|
||||
This is the same URL that you would use to clone the repo over HTTP.
|
||||
|
||||
- You can optionally add the path to the Taskfile in the repository by appending
|
||||
`//<path>` to the URL.
|
||||
- You can also optionally specify a branch or tag to use by appending
|
||||
`?ref=<ref>` to the end of the URL. If you omit a reference, the default
|
||||
branch will be used.
|
||||
|
||||
### Git over SSH
|
||||
|
||||
`git@github.com/go-task/task.git//website/src/public/Taskfile.yml?ref=main`
|
||||
|
||||
This type of node works by downloading the file from a Git repository over SSH.
|
||||
The first part of the URL is the user and base URL of the Git repository. This
|
||||
is the same URL that you would use to clone the repo over SSH.
|
||||
|
||||
To use Git over SSH, you need to make sure that your SSH agent has your private
|
||||
SSH keys added so that they can be used during authentication.
|
||||
|
||||
- You can optionally add the path to the Taskfile in the repository by appending
|
||||
`//<path>` to the URL.
|
||||
- You can also optionally specify a branch or tag to use by appending
|
||||
`?ref=<ref>` to the end of the URL. If you omit a reference, the default
|
||||
branch will be used.
|
||||
|
||||
Task has an example remote Taskfile in our repository that you can use for
|
||||
testing and that we will use throughout this document:
|
||||
|
||||
```yaml
|
||||
version: '3'
|
||||
|
||||
tasks:
|
||||
default:
|
||||
cmds:
|
||||
- task: hello
|
||||
|
||||
hello:
|
||||
cmds:
|
||||
- echo "Hello Task!"
|
||||
```
|
||||
|
||||
## Specifying a remote entrypoint
|
||||
|
||||
By default, Task will look for one of the supported file names on your local
|
||||
filesystem. If you want to use a remote file instead, you can pass its URI into
|
||||
the `--taskfile`/`-t` flag just like you would to specify a different local
|
||||
file. For example:
|
||||
|
||||
::: code-group
|
||||
|
||||
```shell [HTTP/HTTPS]
|
||||
$ task --taskfile https://raw.githubusercontent.com/go-task/task/main/website/src/public/Taskfile.yml
|
||||
task: [hello] echo "Hello Task!"
|
||||
Hello Task!
|
||||
```
|
||||
|
||||
```shell [Git over HTTP]
|
||||
$ task --taskfile https://github.com/go-task/task.git//website/src/public/Taskfile.yml?ref=main
|
||||
task: [hello] echo "Hello Task!"
|
||||
Hello Task!
|
||||
```
|
||||
|
||||
```shell [Git over SSH]
|
||||
$ task --taskfile git@github.com/go-task/task.git//website/src/public/Taskfile.yml?ref=main
|
||||
task: [hello] echo "Hello Task!"
|
||||
Hello Task!
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
## Including remote Taskfiles
|
||||
|
||||
Including a remote file works exactly the same way that including a local file
|
||||
does. You just need to replace the local path with a remote URI. Any tasks in
|
||||
the remote Taskfile will be available to run from your main Taskfile.
|
||||
|
||||
::: code-group
|
||||
|
||||
```yaml [HTTP/HTTPS]
|
||||
version: '3'
|
||||
|
||||
includes:
|
||||
my-remote-namespace: https://raw.githubusercontent.com/go-task/task/main/website/src/public/Taskfile.yml
|
||||
```
|
||||
|
||||
```yaml [Git over HTTP]
|
||||
version: '3'
|
||||
|
||||
includes:
|
||||
my-remote-namespace: https://github.com/go-task/task.git//website/src/public/Taskfile.yml?ref=main
|
||||
```
|
||||
|
||||
```yaml [Git over SSH]
|
||||
version: '3'
|
||||
|
||||
includes:
|
||||
my-remote-namespace: git@github.com/go-task/task.git//website/src/public/Taskfile.yml?ref=main
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
```shell
|
||||
$ task my-remote-namespace:hello
|
||||
task: [hello] echo "Hello Task!"
|
||||
Hello Task!
|
||||
```
|
||||
|
||||
### Authenticating using environment variables
|
||||
|
||||
The Taskfile location is processed by the templating system, so you can
|
||||
reference environment variables in your URL if you need to add authentication.
|
||||
For example:
|
||||
|
||||
```yaml
|
||||
version: '3'
|
||||
|
||||
includes:
|
||||
my-remote-namespace: https://{{.TOKEN}}@raw.githubusercontent.com/my-org/my-repo/main/Taskfile.yml
|
||||
```
|
||||
|
||||
## Special Variables
|
||||
|
||||
The file-path [special variables](../reference/templating.md#file-paths) behave
|
||||
differently when a Taskfile is loaded from a remote source, because there is no
|
||||
local file or directory that corresponds 1:1 to the Taskfile:
|
||||
|
||||
| Variable | Value when loaded remotely |
|
||||
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `TASKFILE` / `ROOT_TASKFILE` | The original URL, unchanged |
|
||||
| `TASKFILE_DIR` / `ROOT_DIR` | Empty string — a directory variable cannot point to a URL |
|
||||
| `TASK_DIR` | Resolved against `USER_WORKING_DIR` (relative `dir:` → joined with `USER_WORKING_DIR`, empty `dir:` → `USER_WORKING_DIR`, absolute `dir:` → kept as-is) |
|
||||
|
||||
If a remote Taskfile includes a local Taskfile (or vice-versa), each variable
|
||||
reflects the source of the Taskfile it refers to.
|
||||
|
||||
## Security
|
||||
|
||||
### Automatic checksums
|
||||
|
||||
Running commands from sources that you do not control is always a potential
|
||||
security risk. For this reason, we have added some automatic checks when using
|
||||
remote Taskfiles:
|
||||
|
||||
1. When running a task from a remote Taskfile for the first time, Task will
|
||||
print a warning to the console asking you to check that you are sure that you
|
||||
trust the source of the Taskfile. If you do not accept the prompt, then Task
|
||||
will exit with code `104` (not trusted) and nothing will run. If you accept
|
||||
the prompt, the remote Taskfile will run and further calls to the remote
|
||||
Taskfile will not prompt you again.
|
||||
2. Whenever you run a remote Taskfile, Task will create and store a checksum of
|
||||
the file that you are running. If the checksum changes, then Task will print
|
||||
another warning to the console to inform you that the contents of the remote
|
||||
file has changed. If you do not accept the prompt, then Task will exit with
|
||||
code `104` (not trusted) and nothing will run. If you accept the prompt, the
|
||||
checksum will be updated and the remote Taskfile will run.
|
||||
|
||||
Sometimes you need to run Task in an environment that does not have an
|
||||
interactive terminal, so you are not able to accept a prompt. In these cases you
|
||||
are able to tell task to accept these prompts automatically by using the `--yes`
|
||||
flag or the `--trust` flag. The `--trust` flag allows you to specify trusted
|
||||
hosts for remote Taskfiles, while `--yes` applies to all prompts in Task. You
|
||||
can also configure trusted hosts in your
|
||||
[taskrc configuration](./reference/config.md#remotetrusted-hosts) using
|
||||
`remote.trusted-hosts`. Before enabling automatic trust, you should:
|
||||
|
||||
1. Be sure that you trust the source and contents of the remote Taskfile.
|
||||
2. Consider using a pinned version of the remote Taskfile (e.g. A link
|
||||
containing a commit hash) to prevent Task from automatically accepting a
|
||||
prompt that says a remote Taskfile has changed.
|
||||
|
||||
### Manual checksum pinning
|
||||
|
||||
Alternatively, if you expect the contents of your remote files to be a constant
|
||||
value, you can pin the checksum of the included file instead:
|
||||
|
||||
```yaml
|
||||
version: '3'
|
||||
|
||||
includes:
|
||||
included:
|
||||
taskfile: https://taskfile.dev
|
||||
checksum: c153e97e0b3a998a7ed2e61064c6ddaddd0de0c525feefd6bba8569827d8efe9
|
||||
```
|
||||
|
||||
This will disable the automatic checksum prompts discussed above. However, if
|
||||
the checksums do not match, Task will exit immediately with an error. When
|
||||
setting this up for the first time, you may not know the correct value of the
|
||||
checksum. There are a couple of ways you can obtain this:
|
||||
|
||||
1. Add the include normally without the `checksum` key. The first time you run
|
||||
the included Taskfile, a `.task/remote` temporary directory is created. Find
|
||||
the correct set of files for your included Taskfile and open the file that
|
||||
ends with `.checksum`. You can copy the contents of this file and paste it
|
||||
into the `checksum` key of your include. This method is safest as it allows
|
||||
you to inspect the downloaded Taskfile before you pin it.
|
||||
2. Alternatively, add the include with a temporary random value in the
|
||||
`checksum` key. When you try to run the Taskfile, you will get an error that
|
||||
will report the incorrect expected checksum and the actual checksum. You can
|
||||
copy the actual checksum and replace your temporary random value.
|
||||
|
||||
### TLS
|
||||
|
||||
Task currently supports both `http` and `https` URLs. However, the `http`
|
||||
requests will not execute by default unless you run the task with the
|
||||
`--insecure` flag. This is to protect you from accidentally running a remote
|
||||
Taskfile that is downloaded via an unencrypted connection. Sources that are not
|
||||
protected by TLS are vulnerable to man-in-the-middle attacks and should be
|
||||
avoided unless you know what you are doing.
|
||||
|
||||
#### Custom Certificates
|
||||
|
||||
If your remote Taskfiles are hosted on a server that uses a custom CA
|
||||
certificate (e.g., a corporate internal server), you can specify the CA
|
||||
certificate using the `--cacert` flag:
|
||||
|
||||
```shell
|
||||
task --taskfile https://internal.example.com/Taskfile.yml --cacert /path/to/ca.crt
|
||||
```
|
||||
|
||||
For servers that require client certificate authentication (mTLS), you can
|
||||
provide a client certificate and key:
|
||||
|
||||
```shell
|
||||
task --taskfile https://secure.example.com/Taskfile.yml \
|
||||
--cert /path/to/client.crt \
|
||||
--cert-key /path/to/client.key
|
||||
```
|
||||
|
||||
::: warning
|
||||
|
||||
Encrypted private keys are not currently supported. If your key is encrypted,
|
||||
you must decrypt it first:
|
||||
|
||||
```shell
|
||||
openssl rsa -in encrypted.key -out decrypted.key
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
These options can also be configured in the
|
||||
[configuration file](#configuration).
|
||||
|
||||
## Caching & Running Offline
|
||||
|
||||
Whenever you run a remote Taskfile, the latest copy will be downloaded from the
|
||||
internet and cached locally. This cached file will be used for all future
|
||||
invocations of the Taskfile until the cache expires. Once it expires, Task will
|
||||
download the latest copy of the file and update the cache. By default, the cache
|
||||
is set to expire immediately. This means that Task will always fetch the latest
|
||||
version. However, the cache expiry duration can be modified by setting the
|
||||
`--expiry` flag.
|
||||
|
||||
If for any reason you lose access to the internet or you are running Task in
|
||||
offline mode (via the `--offline` flag or `TASK_OFFLINE` environment variable),
|
||||
Task will run the any available cached files _even if they are expired_. This
|
||||
means that you should never be stuck without the ability to run your tasks as
|
||||
long as you have downloaded a remote Taskfile at least once.
|
||||
|
||||
By default, Task will timeout requests to download remote files after 10 seconds
|
||||
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 (`.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](./reference/config.md#remotecache-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.
|
||||
|
||||
You can use the `--clear-cache` flag to clear all cached remote files.
|
||||
|
||||
## Configuration
|
||||
|
||||
It is also possible to adjust remote Taskfile functionality can be edited via a
|
||||
configuration file. Check out the
|
||||
|
||||
- [CLI flags](./reference/cli.md#remote)
|
||||
- [Environment Variables](./reference/environment.md#remote-taskfile-variables)
|
||||
- [Config File](./reference/config.md#remote)
|
||||
Reference in New Issue
Block a user