mirror of
https://github.com/go-task/task.git
synced 2026-07-01 08:34:19 +00:00
Compare commits
8 Commits
feat/compl
...
docs/homeb
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cf9d6b73a5 | ||
|
|
48b215db0a | ||
|
|
0aa0496f85 | ||
|
|
d601746d4b | ||
|
|
e415d7135e | ||
|
|
a61f8ade36 | ||
|
|
9910c33557 | ||
|
|
b93897a6c3 |
17
.github/renovate.json
vendored
17
.github/renovate.json
vendored
@@ -6,20 +6,31 @@
|
|||||||
"schedule:weekly",
|
"schedule:weekly",
|
||||||
":semanticCommitTypeAll(chore)"
|
":semanticCommitTypeAll(chore)"
|
||||||
],
|
],
|
||||||
"mode": "full",
|
|
||||||
"addLabels":["area: dependencies"],
|
"addLabels":["area: dependencies"],
|
||||||
|
"osvVulnerabilityAlerts": true,
|
||||||
|
"postUpdateOptions": ["gomodTidy"],
|
||||||
"customManagers": [
|
"customManagers": [
|
||||||
{
|
{
|
||||||
"customType": "regex",
|
"customType": "regex",
|
||||||
"fileMatch": ["^\\.github/workflows/.*\\.ya?ml$"],
|
"managerFilePatterns": ["/^\\.github/workflows/.*\\.ya?ml$/"],
|
||||||
"matchStrings": [
|
"matchStrings": [
|
||||||
"uses:\\s*golangci/golangci-lint-action@\\S+\\s+with:\\s+version:\\s*(?<currentValue>v[\\d.]+)"
|
"uses:\\s*golangci/golangci-lint-action@\\S+(?:\\s*#[^\\n]*)?\\s+with:\\s+version:\\s*(?<currentValue>v[\\d.]+)"
|
||||||
],
|
],
|
||||||
"datasourceTemplate": "github-releases",
|
"datasourceTemplate": "github-releases",
|
||||||
"depNameTemplate": "golangci/golangci-lint"
|
"depNameTemplate": "golangci/golangci-lint"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"packageRules": [
|
"packageRules": [
|
||||||
|
{
|
||||||
|
"matchManagers": ["gomod"],
|
||||||
|
"matchDepTypes": ["indirect"],
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"matchUpdateTypes": ["digest", "pinDigest"],
|
||||||
|
"groupName": "all non-major dependencies",
|
||||||
|
"groupSlug": "all-minor-patch"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"matchManagers": ["github-actions"],
|
"matchManagers": ["github-actions"],
|
||||||
"addLabels": ["area: github actions"]
|
"addLabels": ["area: github actions"]
|
||||||
|
|||||||
@@ -80,22 +80,21 @@ nfpms:
|
|||||||
- src: completion/zsh/_task
|
- src: completion/zsh/_task
|
||||||
dst: /usr/local/share/zsh/site-functions/_task
|
dst: /usr/local/share/zsh/site-functions/_task
|
||||||
|
|
||||||
brews:
|
homebrew_casks:
|
||||||
- name: go-task
|
- name: go-task
|
||||||
description: A fast, cross-platform build tool inspired by Make, designed for modern workflows.
|
description: A fast, cross-platform build tool inspired by Make, designed for modern workflows.
|
||||||
license: MIT
|
|
||||||
homepage: https://taskfile.dev
|
homepage: https://taskfile.dev
|
||||||
directory: Formula
|
binaries:
|
||||||
|
- task
|
||||||
|
completions:
|
||||||
|
bash: completion/bash/task.bash
|
||||||
|
zsh: completion/zsh/_task
|
||||||
|
fish: completion/fish/task.fish
|
||||||
|
directory: Casks
|
||||||
repository:
|
repository:
|
||||||
owner: go-task
|
owner: go-task
|
||||||
name: homebrew-tap
|
name: homebrew-tap
|
||||||
token: "{{.Env.GH_GORELEASER_TOKEN}}" # So that it runs as the task-bot user
|
token: "{{.Env.GH_GORELEASER_TOKEN}}" # So that it runs as the task-bot user
|
||||||
test: system "#{bin}/task", "--help"
|
|
||||||
install: |-
|
|
||||||
bin.install "task"
|
|
||||||
bash_completion.install "completion/bash/task.bash" => "task"
|
|
||||||
zsh_completion.install "completion/zsh/_task" => "_task"
|
|
||||||
fish_completion.install "completion/fish/task.fish"
|
|
||||||
commit_author:
|
commit_author:
|
||||||
name: task-bot
|
name: task-bot
|
||||||
email: 106601941+task-bot@users.noreply.github.com
|
email: 106601941+task-bot@users.noreply.github.com
|
||||||
|
|||||||
16
CHANGELOG.md
16
CHANGELOG.md
@@ -10,11 +10,11 @@
|
|||||||
by @Legimity).
|
by @Legimity).
|
||||||
- PowerShell completions now work with aliases of the `task` command, not just
|
- PowerShell completions now work with aliases of the `task` command, not just
|
||||||
the `task` binary itself (#2852 by @kojiishi).
|
the `task` binary itself (#2852 by @kojiishi).
|
||||||
- Fixed task and namespace aliases not being completed by the Zsh completion.
|
- Fixed task and namespace aliases not being completed by the Zsh completion. A
|
||||||
A `show-aliases` zstyle can turn this off (#2865, #2864 by @vmaerten).
|
`show-aliases` zstyle can turn this off (#2865, #2864 by @vmaerten).
|
||||||
- Fixed task names containing certain characters (e.g. `\`, `_`, `^`) leaking
|
- Fixed task names containing certain characters (e.g. `\`, `_`, `^`) leaking
|
||||||
into checksum/timestamp filenames, breaking `sources:`/`generates:`
|
into checksum/timestamp filenames, breaking `sources:`/`generates:` up-to-date
|
||||||
up-to-date detection (#2886 by @s3onghyun).
|
detection (#2886 by @s3onghyun).
|
||||||
- Fixed `for: matrix:` loops using `ref:` rows producing wrong values when the
|
- Fixed `for: matrix:` loops using `ref:` rows producing wrong values when the
|
||||||
same task was run concurrently (e.g. by parallel `deps`) with different vars
|
same task was run concurrently (e.g. by parallel `deps`) with different vars
|
||||||
(#2890, #2894 by @amitmishra11).
|
(#2890, #2894 by @amitmishra11).
|
||||||
@@ -23,13 +23,15 @@
|
|||||||
- Added the `use_gitignore` setting (global or per-task) to skip files matched
|
- Added the `use_gitignore` setting (global or per-task) to skip files matched
|
||||||
by your `.gitignore` when fingerprinting `sources`/`generates` and when
|
by your `.gitignore` when fingerprinting `sources`/`generates` and when
|
||||||
watching (#2773 by @vmaerten).
|
watching (#2773 by @vmaerten).
|
||||||
- Added support for configuring output flags (`--output`, `--output-group-begin`,
|
- Added support for configuring output flags (`--output`,
|
||||||
`--output-group-end`, `--output-group-error-only`) via the `TASK_OUTPUT*`
|
`--output-group-begin`, `--output-group-end`, `--output-group-error-only`) via
|
||||||
environment variables (#2873 by @liiight).
|
the `TASK_OUTPUT*` environment variables (#2873 by @liiight).
|
||||||
- Added a `--temp-dir` flag (with `TASK_TEMP_DIR` env var and `temp-dir` taskrc
|
- Added a `--temp-dir` flag (with `TASK_TEMP_DIR` env var and `temp-dir` taskrc
|
||||||
config) to customise the directory where Task stores temporary files such as
|
config) to customise the directory where Task stores temporary files such as
|
||||||
checksums. Relative paths are resolved against the root Taskfile (#2891 by
|
checksums. Relative paths are resolved against the root Taskfile (#2891 by
|
||||||
@kjasn).
|
@kjasn).
|
||||||
|
- Defined environment variable behavior for remote taskfiles (#2267, #2847 by
|
||||||
|
@vmaerten).
|
||||||
|
|
||||||
## v3.51.1 - 2026-05-16
|
## v3.51.1 - 2026-05-16
|
||||||
|
|
||||||
|
|||||||
27
compiler.go
27
compiler.go
@@ -15,6 +15,7 @@ import (
|
|||||||
"github.com/go-task/task/v3/internal/logger"
|
"github.com/go-task/task/v3/internal/logger"
|
||||||
"github.com/go-task/task/v3/internal/templater"
|
"github.com/go-task/task/v3/internal/templater"
|
||||||
"github.com/go-task/task/v3/internal/version"
|
"github.com/go-task/task/v3/internal/version"
|
||||||
|
"github.com/go-task/task/v3/taskfile"
|
||||||
"github.com/go-task/task/v3/taskfile/ast"
|
"github.com/go-task/task/v3/taskfile/ast"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -206,10 +207,19 @@ func (c *Compiler) getSpecialVars(t *ast.Task, call *Call) (map[string]string, e
|
|||||||
// Use filepath.ToSlash for all paths to ensure consistent forward slashes
|
// Use filepath.ToSlash for all paths to ensure consistent forward slashes
|
||||||
// across platforms. This prevents issues with backslashes being interpreted
|
// across platforms. This prevents issues with backslashes being interpreted
|
||||||
// as escape sequences when paths are used in shell commands on Windows.
|
// as escape sequences when paths are used in shell commands on Windows.
|
||||||
|
var rootTaskfile, rootDir string
|
||||||
|
if taskfile.IsRemoteEntrypoint(c.Entrypoint) {
|
||||||
|
rootTaskfile = c.Entrypoint
|
||||||
|
rootDir = ""
|
||||||
|
} else {
|
||||||
|
rootTaskfile = filepath.ToSlash(filepathext.SmartJoin(c.Dir, c.Entrypoint))
|
||||||
|
rootDir = filepath.ToSlash(c.Dir)
|
||||||
|
}
|
||||||
|
|
||||||
allVars := map[string]string{
|
allVars := map[string]string{
|
||||||
"TASK_EXE": filepath.ToSlash(os.Args[0]),
|
"TASK_EXE": filepath.ToSlash(os.Args[0]),
|
||||||
"ROOT_TASKFILE": filepath.ToSlash(filepathext.SmartJoin(c.Dir, c.Entrypoint)),
|
"ROOT_TASKFILE": rootTaskfile,
|
||||||
"ROOT_DIR": filepath.ToSlash(c.Dir),
|
"ROOT_DIR": rootDir,
|
||||||
"USER_WORKING_DIR": filepath.ToSlash(c.UserWorkingDir),
|
"USER_WORKING_DIR": filepath.ToSlash(c.UserWorkingDir),
|
||||||
"TASK_VERSION": version.GetVersion(),
|
"TASK_VERSION": version.GetVersion(),
|
||||||
"PATH_LIST_SEPARATOR": string(os.PathListSeparator),
|
"PATH_LIST_SEPARATOR": string(os.PathListSeparator),
|
||||||
@@ -217,9 +227,22 @@ func (c *Compiler) getSpecialVars(t *ast.Task, call *Call) (map[string]string, e
|
|||||||
}
|
}
|
||||||
if t != nil {
|
if t != nil {
|
||||||
allVars["TASK"] = t.Task
|
allVars["TASK"] = t.Task
|
||||||
|
if taskfile.IsRemoteEntrypoint(t.Location.Taskfile) {
|
||||||
|
allVars["TASKFILE"] = t.Location.Taskfile
|
||||||
|
allVars["TASKFILE_DIR"] = ""
|
||||||
|
switch {
|
||||||
|
case t.Dir == "":
|
||||||
|
allVars["TASK_DIR"] = filepath.ToSlash(c.UserWorkingDir)
|
||||||
|
case filepath.IsAbs(t.Dir):
|
||||||
|
allVars["TASK_DIR"] = filepath.ToSlash(t.Dir)
|
||||||
|
default:
|
||||||
|
allVars["TASK_DIR"] = filepath.ToSlash(filepathext.SmartJoin(c.UserWorkingDir, t.Dir))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
allVars["TASK_DIR"] = filepath.ToSlash(filepathext.SmartJoin(c.Dir, t.Dir))
|
allVars["TASK_DIR"] = filepath.ToSlash(filepathext.SmartJoin(c.Dir, t.Dir))
|
||||||
allVars["TASKFILE"] = filepath.ToSlash(t.Location.Taskfile)
|
allVars["TASKFILE"] = filepath.ToSlash(t.Location.Taskfile)
|
||||||
allVars["TASKFILE_DIR"] = filepath.ToSlash(filepath.Dir(t.Location.Taskfile))
|
allVars["TASKFILE_DIR"] = filepath.ToSlash(filepath.Dir(t.Location.Taskfile))
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
allVars["TASK"] = ""
|
allVars["TASK"] = ""
|
||||||
allVars["TASK_DIR"] = ""
|
allVars["TASK_DIR"] = ""
|
||||||
|
|||||||
135
compiler_internal_test.go
Normal file
135
compiler_internal_test.go
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
package task
|
||||||
|
|
||||||
|
import (
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
"github.com/go-task/task/v3/internal/filepathext"
|
||||||
|
"github.com/go-task/task/v3/taskfile/ast"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGetSpecialVarsRemote(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
uwd := t.TempDir()
|
||||||
|
uwdSlash := filepath.ToSlash(uwd)
|
||||||
|
localProj := filepath.Join(uwd, "proj")
|
||||||
|
localProjSlash := filepath.ToSlash(localProj)
|
||||||
|
localTaskfile := filepath.Join(localProj, "Taskfile.yml")
|
||||||
|
localTaskfileSlash := filepath.ToSlash(localTaskfile)
|
||||||
|
absTaskDir := filepath.Join(uwd, "opt", "work")
|
||||||
|
absTaskDirSlash := filepath.ToSlash(absTaskDir)
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
entrypoint string
|
||||||
|
compilerDir string
|
||||||
|
taskDir string
|
||||||
|
taskfileLocation string
|
||||||
|
wantRootTaskfile string
|
||||||
|
wantRootDir string
|
||||||
|
wantTaskfile string
|
||||||
|
wantTaskfileDir string
|
||||||
|
wantTaskDir string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "local entrypoint, local task",
|
||||||
|
entrypoint: localTaskfile,
|
||||||
|
compilerDir: localProj,
|
||||||
|
taskDir: "",
|
||||||
|
taskfileLocation: localTaskfile,
|
||||||
|
wantRootTaskfile: localTaskfileSlash,
|
||||||
|
wantRootDir: localProjSlash,
|
||||||
|
wantTaskfile: localTaskfileSlash,
|
||||||
|
wantTaskfileDir: localProjSlash,
|
||||||
|
wantTaskDir: localProjSlash,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "https entrypoint, empty task.dir",
|
||||||
|
entrypoint: "https://taskfile.dev/Taskfile.yml",
|
||||||
|
compilerDir: "",
|
||||||
|
taskDir: "",
|
||||||
|
taskfileLocation: "https://taskfile.dev/Taskfile.yml",
|
||||||
|
wantRootTaskfile: "https://taskfile.dev/Taskfile.yml",
|
||||||
|
wantRootDir: "",
|
||||||
|
wantTaskfile: "https://taskfile.dev/Taskfile.yml",
|
||||||
|
wantTaskfileDir: "",
|
||||||
|
wantTaskDir: uwdSlash,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "https entrypoint, relative task.dir",
|
||||||
|
entrypoint: "https://taskfile.dev/Taskfile.yml",
|
||||||
|
compilerDir: "",
|
||||||
|
taskDir: "subdir",
|
||||||
|
taskfileLocation: "https://taskfile.dev/Taskfile.yml",
|
||||||
|
wantRootTaskfile: "https://taskfile.dev/Taskfile.yml",
|
||||||
|
wantRootDir: "",
|
||||||
|
wantTaskfile: "https://taskfile.dev/Taskfile.yml",
|
||||||
|
wantTaskfileDir: "",
|
||||||
|
wantTaskDir: filepath.ToSlash(filepathext.SmartJoin(uwd, "subdir")),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "https entrypoint, absolute task.dir",
|
||||||
|
entrypoint: "https://taskfile.dev/Taskfile.yml",
|
||||||
|
compilerDir: "",
|
||||||
|
taskDir: absTaskDir,
|
||||||
|
taskfileLocation: "https://taskfile.dev/Taskfile.yml",
|
||||||
|
wantRootTaskfile: "https://taskfile.dev/Taskfile.yml",
|
||||||
|
wantRootDir: "",
|
||||||
|
wantTaskfile: "https://taskfile.dev/Taskfile.yml",
|
||||||
|
wantTaskfileDir: "",
|
||||||
|
wantTaskDir: absTaskDirSlash,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "git entrypoint",
|
||||||
|
entrypoint: "https://github.com/foo/bar.git//Taskfile.yml?ref=main",
|
||||||
|
compilerDir: "",
|
||||||
|
taskDir: "",
|
||||||
|
taskfileLocation: "https://github.com/foo/bar.git//Taskfile.yml?ref=main",
|
||||||
|
wantRootTaskfile: "https://github.com/foo/bar.git//Taskfile.yml?ref=main",
|
||||||
|
wantRootDir: "",
|
||||||
|
wantTaskfile: "https://github.com/foo/bar.git//Taskfile.yml?ref=main",
|
||||||
|
wantTaskfileDir: "",
|
||||||
|
wantTaskDir: uwdSlash,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "local root, remote included task",
|
||||||
|
entrypoint: localTaskfile,
|
||||||
|
compilerDir: localProj,
|
||||||
|
taskDir: "",
|
||||||
|
taskfileLocation: "https://taskfile.dev/included.yml",
|
||||||
|
wantRootTaskfile: localTaskfileSlash,
|
||||||
|
wantRootDir: localProjSlash,
|
||||||
|
wantTaskfile: "https://taskfile.dev/included.yml",
|
||||||
|
wantTaskfileDir: "",
|
||||||
|
wantTaskDir: uwdSlash,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
c := &Compiler{
|
||||||
|
Dir: tt.compilerDir,
|
||||||
|
Entrypoint: tt.entrypoint,
|
||||||
|
UserWorkingDir: uwd,
|
||||||
|
}
|
||||||
|
task := &ast.Task{
|
||||||
|
Task: "mytask",
|
||||||
|
Dir: tt.taskDir,
|
||||||
|
Location: &ast.Location{Taskfile: tt.taskfileLocation},
|
||||||
|
}
|
||||||
|
|
||||||
|
vars, err := c.getSpecialVars(task, nil)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, tt.wantRootTaskfile, vars["ROOT_TASKFILE"], "ROOT_TASKFILE")
|
||||||
|
assert.Equal(t, tt.wantRootDir, vars["ROOT_DIR"], "ROOT_DIR")
|
||||||
|
assert.Equal(t, tt.wantTaskfile, vars["TASKFILE"], "TASKFILE")
|
||||||
|
assert.Equal(t, tt.wantTaskfileDir, vars["TASKFILE_DIR"], "TASKFILE_DIR")
|
||||||
|
assert.Equal(t, tt.wantTaskDir, vars["TASK_DIR"], "TASK_DIR")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -98,6 +98,9 @@ func (vars *Vars) Values() iter.Seq[Var] {
|
|||||||
// ToCacheMap converts Vars to an unordered map containing only the static
|
// ToCacheMap converts Vars to an unordered map containing only the static
|
||||||
// variables
|
// variables
|
||||||
func (vars *Vars) ToCacheMap() (m map[string]any) {
|
func (vars *Vars) ToCacheMap() (m map[string]any) {
|
||||||
|
if vars == nil || vars.om == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
defer vars.mutex.RUnlock()
|
defer vars.mutex.RUnlock()
|
||||||
vars.mutex.RLock()
|
vars.mutex.RLock()
|
||||||
m = make(map[string]any, vars.Len())
|
m = make(map[string]any, vars.Len())
|
||||||
|
|||||||
55
taskfile/ast/vars_test.go
Normal file
55
taskfile/ast/vars_test.go
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
package ast
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestVars_ToCacheMap(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
t.Run("nil receiver returns nil", func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
var vars *Vars
|
||||||
|
assert.Nil(t, vars.ToCacheMap())
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("empty vars returns empty map", func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
vars := NewVars()
|
||||||
|
m := vars.ToCacheMap()
|
||||||
|
assert.NotNil(t, m)
|
||||||
|
assert.Empty(t, m)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("static values are included", func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
vars := NewVars(
|
||||||
|
&VarElement{Key: "FOO", Value: Var{Value: "bar"}},
|
||||||
|
&VarElement{Key: "NUM", Value: Var{Value: 42}},
|
||||||
|
)
|
||||||
|
m := vars.ToCacheMap()
|
||||||
|
assert.Equal(t, map[string]any{"FOO": "bar", "NUM": 42}, m)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("live values take precedence over static values", func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
vars := NewVars(
|
||||||
|
&VarElement{Key: "FOO", Value: Var{Value: "bar", Live: "live-bar"}},
|
||||||
|
)
|
||||||
|
m := vars.ToCacheMap()
|
||||||
|
assert.Equal(t, map[string]any{"FOO": "live-bar"}, m)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("dynamic variables are excluded", func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
sh := "echo hello"
|
||||||
|
vars := NewVars(
|
||||||
|
&VarElement{Key: "STATIC", Value: Var{Value: "ok"}},
|
||||||
|
&VarElement{Key: "DYNAMIC", Value: Var{Sh: &sh}},
|
||||||
|
)
|
||||||
|
m := vars.ToCacheMap()
|
||||||
|
assert.Equal(t, map[string]any{"STATIC": "ok"}, m)
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -73,7 +73,7 @@ func NewNode(
|
|||||||
return node, err
|
return node, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func isRemoteEntrypoint(entrypoint string) bool {
|
func IsRemoteEntrypoint(entrypoint string) bool {
|
||||||
scheme, _ := getScheme(entrypoint)
|
scheme, _ := getScheme(entrypoint)
|
||||||
switch scheme {
|
switch scheme {
|
||||||
case "git", "http", "https":
|
case "git", "http", "https":
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ func (node *FileNode) Read() ([]byte, error) {
|
|||||||
|
|
||||||
func (node *FileNode) ResolveEntrypoint(entrypoint string) (string, error) {
|
func (node *FileNode) ResolveEntrypoint(entrypoint string) (string, error) {
|
||||||
// If the file is remote, we don't need to resolve the path
|
// If the file is remote, we don't need to resolve the path
|
||||||
if isRemoteEntrypoint(entrypoint) {
|
if IsRemoteEntrypoint(entrypoint) {
|
||||||
return entrypoint, nil
|
return entrypoint, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -188,7 +188,7 @@ func (node *GitNode) ReadContext(ctx context.Context) ([]byte, error) {
|
|||||||
|
|
||||||
func (node *GitNode) ResolveEntrypoint(entrypoint string) (string, error) {
|
func (node *GitNode) ResolveEntrypoint(entrypoint string) (string, error) {
|
||||||
// If the file is remote, we don't need to resolve the path
|
// If the file is remote, we don't need to resolve the path
|
||||||
if isRemoteEntrypoint(entrypoint) {
|
if IsRemoteEntrypoint(entrypoint) {
|
||||||
return entrypoint, nil
|
return entrypoint, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ func (node *StdinNode) Read() ([]byte, error) {
|
|||||||
|
|
||||||
func (node *StdinNode) ResolveEntrypoint(entrypoint string) (string, error) {
|
func (node *StdinNode) ResolveEntrypoint(entrypoint string) (string, error) {
|
||||||
// If the file is remote, we don't need to resolve the path
|
// If the file is remote, we don't need to resolve the path
|
||||||
if isRemoteEntrypoint(entrypoint) {
|
if IsRemoteEntrypoint(entrypoint) {
|
||||||
return entrypoint, nil
|
return entrypoint, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -190,6 +190,21 @@ includes:
|
|||||||
my-remote-namespace: https://{{.TOKEN}}@raw.githubusercontent.com/my-org/my-repo/main/Taskfile.yml
|
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
|
## Security
|
||||||
|
|
||||||
### Automatic checksums
|
### Automatic checksums
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ apk add task
|
|||||||
### [Homebrew](https://brew.sh)   {#homebrew}
|
### [Homebrew](https://brew.sh)   {#homebrew}
|
||||||
|
|
||||||
Task is available via our official Homebrew tap
|
Task is available via our official Homebrew tap
|
||||||
[[source](https://github.com/go-task/homebrew-tap/blob/main/Formula/go-task.rb)]:
|
[[source](https://github.com/go-task/homebrew-tap/blob/main/Casks/go-task.rb)]:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
brew install go-task/tap/go-task
|
brew install go-task/tap/go-task
|
||||||
|
|||||||
@@ -565,6 +565,9 @@ tasks:
|
|||||||
- echo "{{.MULTILINE | catLines}}" # Replace newlines with spaces
|
- echo "{{.MULTILINE | catLines}}" # Replace newlines with spaces
|
||||||
```
|
```
|
||||||
|
|
||||||
|
In pipeline form, `join` receives the list from the left-hand side. The
|
||||||
|
equivalent non-pipeline form is <span v-pre>`{{join " " .WORDS}}`</span>.
|
||||||
|
|
||||||
#### Shell Argument Parsing
|
#### Shell Argument Parsing
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
|
|||||||
Reference in New Issue
Block a user