Compare commits

..

32 Commits

Author SHA1 Message Date
Valentin Maerten
554c9811f2 feat(homebrew): migrate from Formula to Cask
Switch GoReleaser config from `brews` to `homebrew_casks` and update
documentation links to reference Casks/go-task.rb instead of
Formula/go-task.rb.
2026-02-21 16:01:10 +01:00
Valentin Maerten
c62f9c7147 fix(build): exclude unsupported windows/arm target 2026-02-21 15:18:04 +01:00
Valentin Maerten
c4ecff753d chore: changelog for #2607 2026-02-18 19:00:15 +01:00
Valentin Maerten
2ed77716be feat(config): add environment variable support for all taskrc options (#2607) 2026-02-18 18:58:13 +01:00
Valentin Maerten
a2f8e144ca chore: changelog for #2632 2026-02-18 18:57:53 +01:00
Timothy Rule
2cdd7d3e43 fix: Call ReplaceVars() to resolve Ref's for imported global vars. (#2632) 2026-02-18 18:55:20 +01:00
Andrey Nering
56b316a124 ci: fix lint 2026-02-17 15:43:13 -03:00
renovate[bot]
39ce6a21ac chore(deps): update all non-major dependencies 2026-02-17 15:43:13 -03:00
Andrey Nering
fc5f6fa3aa fix: pin yaml package to v3 for now (#2693) 2026-02-17 15:29:51 -03:00
Valentin Maerten
44a2f2e5f5 docs: add Cloudsmith attribution for deb/rpm package hosting 2026-02-15 17:22:01 +01:00
Valentin Maerten
d356c649aa chore: changelog for #2682 2026-02-15 17:01:02 +01:00
Valentin Maerten
ca24d32f37 chore: changelog for #2669 2026-02-15 14:56:52 +01:00
Timothy Rule
f63a63fa6c fix: improve error message when searching for Taskfile. (#2682) 2026-02-15 14:56:35 +01:00
renovate[bot]
c0ff7105e7 chore(deps): update peter-evans/find-comment action to v4 (#2684)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-15 14:49:49 +01:00
Valentin Maerten
8b063d6b92 fix(git): check cache before context timeout in getOrCloneRepo (#2669) 2026-02-15 14:46:55 +01:00
Valentin Maerten
dc8ac5e79f chore: changelog for #2686 2026-02-15 14:45:47 +01:00
Timothy Rule
df7810ab63 fix: copy watch when merging tasks during import (#2686) 2026-02-15 14:42:59 +01:00
Pete Davison
82783417ea docs: update integration doc with details of extension config namespace change (#2428)
* docs: update integration doc with details of extension config namespace change

* docs: add descriptions of sorting modes
2026-02-14 20:47:06 +00:00
renovate[bot]
d5bed6b716 chore(deps): update peter-evans/create-or-update-comment action to v5 (#2673)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-02 09:42:48 +01:00
renovate[bot]
c8f722c0d5 chore(deps): update actions/upload-artifact action to v6 (#2672)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-02 09:35:52 +01:00
Andrey Nering
b7743eda88 chore(goreleaser): update descriptions 2026-01-31 16:20:31 -03:00
Valentin Maerten
c0796e9701 chore: changelog for #2656 2026-01-31 18:53:52 +01:00
Trim21
cf54be3266 fix(node_git): always use unix path style (#2656) 2026-01-31 18:49:22 +01:00
Jens Erat
e129ae2fac docs: fix dir headline level (#2665)
The other commands in this section are on headline level 4, which probably is also the expected one for `dir`.
2026-01-28 18:21:50 +00:00
Andrey Nering
ed69256512 chore: update readme title and description to match website 2026-01-27 22:28:02 -03:00
Andrey Nering
40ad9719d4 chore(website): improve home page title, including on opengraph 2026-01-27 22:18:49 -03:00
Andrey Nering
48f75f0913 docs(cli): mention --list with --silent 2026-01-27 21:53:52 -03:00
Andrey Nering
f000ea2b22 chore(website): have a good opengraph image 2026-01-27 21:53:52 -03:00
Andrey Nering
e8be687a40 chore(website): add "edit this page on github" links 2026-01-27 21:53:52 -03:00
renovate[bot]
788605a3a9 chore(deps): update actions/setup-go action to v6 (#2662)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-26 21:42:04 +01:00
Andrey Nering
697cf442a2 docs(blog): adjust post title 2026-01-26 09:51:43 -03:00
Andrey Nering
e957edf783 chore(website): add goodx sponsor 2026-01-26 09:39:06 -03:00
73 changed files with 2268 additions and 914 deletions

View File

@@ -25,7 +25,7 @@ jobs:
- name: golangci-lint
uses: golangci/golangci-lint-action@v9
with:
version: v2.8.0
version: v2.10.1
lint-jsonschema:
runs-on: ubuntu-latest

View File

@@ -17,45 +17,45 @@ jobs:
with:
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 0
- uses: actions/setup-go@v5
- uses: actions/setup-go@v6
with:
go-version: '1.25.x'
go-version: '1.26.x'
cache: true
- uses: goreleaser/goreleaser-action@v6
with:
version: '~> v2'
args: release --snapshot --clean --config .goreleaser-pr.yml
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v6
with:
name: task_linux_amd64
path: dist/task_linux_amd64.tar.gz
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v6
with:
name: task_linux_arm64
path: dist/task_linux_arm64.tar.gz
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v6
with:
name: task_darwin_amd64
path: dist/task_darwin_amd64.tar.gz
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v6
with:
name: task_darwin_arm64
path: dist/task_darwin_arm64.tar.gz
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v6
with:
name: task_windows_amd64
path: dist/task_windows_amd64.zip
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v6
with:
name: checksums
path: dist/task_checksums.txt
- uses: peter-evans/find-comment@v3
- uses: peter-evans/find-comment@v4
id: find-comment
with:
token: ${{ secrets.GH_PAT || github.token }}
issue-number: ${{ github.event.pull_request.number }}
body-includes: '📦 Build artifacts ready!'
- uses: peter-evans/create-or-update-comment@v4
- uses: peter-evans/create-or-update-comment@v5
with:
token: ${{ secrets.GH_PAT || github.token }}
comment-id: ${{ steps.find-comment.outputs.comment-id }}

View File

@@ -16,7 +16,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v6
with:
go-version: 1.25.x
go-version: 1.26.x
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v6

View File

@@ -21,7 +21,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v6
with:
go-version: 1.25.x
go-version: 1.26.x
- uses: actions/setup-node@v6
with:

View File

@@ -22,6 +22,8 @@ builds:
goarch: '386'
- goos: darwin
goarch: riscv64
- goos: windows
goarch: arm
- goos: windows
goarch: riscv64
env:
@@ -60,7 +62,7 @@ nfpms:
- vendor: Task
homepage: https://taskfile.dev
maintainer: The Task authors <task@taskfile.dev>
description: Simple task runner written in Go
description: A fast, cross-platform build tool inspired by Make, designed for modern workflows.
section: golang
license: MIT
conflicts:
@@ -78,21 +80,20 @@ nfpms:
- src: completion/zsh/_task
dst: /usr/local/share/zsh/site-functions/_task
brews:
homebrew_casks:
- name: go-task
description: Task runner / simpler Make alternative written in Go
license: MIT
description: A fast, cross-platform build tool inspired by Make, designed for modern workflows.
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:
owner: go-task
name: homebrew-tap
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:
name: task-bot
email: 106601941+task-bot@users.noreply.github.com
@@ -100,8 +101,8 @@ brews:
winget:
- name: Task
publisher: Task
short_description: A task runner / simpler Make alternative written in Go
description: Task is a task runner / build tool that aims to be simpler and easier to use than, for example, GNU Make.
short_description: The modern task runner.
description: A fast, cross-platform build tool inspired by Make, designed for modern workflows.
license: MIT
homepage: https://taskfile.dev/
publisher_url: https://taskfile.dev/
@@ -144,7 +145,7 @@ npms:
- name: "@go-task/cli"
repository: "git+https://github.com/go-task/task.git"
bugs: https://github.com/go-task/task/issues
description: A task runner / simpler Make alternative written in Go
description: A fast, cross-platform build tool inspired by Make, designed for modern workflows.
homepage: https://taskfile.dev
license: MIT
author: "The Task authors"
@@ -155,7 +156,6 @@ npms:
- "build-tool"
- "task-runner"
cloudsmiths:
- organization: "task"
repository: "{{if not .IsNightly}}task{{end}}"

View File

@@ -1,5 +1,21 @@
# Changelog
## Unreleased
- Fixed included Taskfiles with `watch: true` not triggering watch mode when
called from the root Taskfile (#2686, #1763 by @trulede).
- Fixed Remote Git Taskfiles failing on Windows due to backslashes in URL paths
(#2656 by @Trim21).
- Fixed remote git Taskfiles timing out when resolving includes after accepting
the trust prompt (#2669, #2668 by @vmaerten).
- Fixed unclear error message when Taskfile search stops at a directory
ownership boundary (#2682, #1683 by @trulede).
- Fixed global variables from imported Taskfiles not resolving `ref:` values
correctly (#2632 by @trulede).
- Every `.taskrc.yml` option can now be overridden with a `TASK_`-prefixed
environment variable, making CI and container configuration easier (#2607,
#1066 by @vmaerten).
## v3.48.0 - 2026-01-26
- Fixed `if:` conditions when using to check dynamic variables. Also, skip

View File

@@ -3,10 +3,10 @@
<img src="website/src/public/img/logo.svg" width="200px" height="200px" />
</a>
<h1>Task</h1>
<h1>Task: The Modern Task Runner</h1>
<p>
Task is a task runner / build tool that aims to be simpler and easier to use than, for example, <a href="https://www.gnu.org/software/make/">GNU Make<a>.
A fast, cross-platform build tool inspired by Make, designed for modern workflows.
</p>
<p>
@@ -22,6 +22,11 @@
<img src="website/src/public/img/devowl.io.svg" height="100px" width="200px" title="devowl.io" />
</a>
</td>
<td align="center" valign="middle">
<a target="_blank" href="https://goodx.international/">
<img src="website/src/public/img/goodx.svg" height="80px" width="200px" title="GoodX" />
</a>
</td>
<td align="center" valign="middle">
<a target="_blank" href="https://magic.dev/">
<img src="website/src/public/img/magic.png" height="100px" width="200px" title="Magic" />

View File

@@ -114,6 +114,9 @@ func (c *Compiler) getVariables(t *ast.Task, call *Call, evaluateShVars bool) (*
return nil, err
}
}
// Resolve any outstanding 'Ref' values in global vars (esp. globals from imported Taskfiles).
c.TaskfileVars = templater.ReplaceVars(c.TaskfileVars, &templater.Cache{Vars: result})
if t != nil {
for k, v := range t.IncludeVars.All() {
if err := rangeFunc(k, v); err != nil {

View File

@@ -8,7 +8,7 @@ import (
"strings"
"github.com/fatih/color"
"go.yaml.in/yaml/v4"
"go.yaml.in/yaml/v3"
)
type (
@@ -50,10 +50,10 @@ func (err *TaskfileDecodeError) Error() string {
if len(te.Errors) > 1 {
fmt.Fprintln(buf, color.RedString("errs:"))
for _, message := range te.Errors {
fmt.Fprintln(buf, color.RedString("- %s", message.Err.Error()))
fmt.Fprintln(buf, color.RedString("- %s", message))
}
} else {
fmt.Fprintln(buf, color.RedString("err: %s", te.Errors[0].Err.Error()))
fmt.Fprintln(buf, color.RedString("err: %s", te.Errors[0]))
}
} else {
// Otherwise print the error message normally

View File

@@ -195,9 +195,9 @@ type TaskNotAllowedVarsError struct {
func (err *TaskNotAllowedVarsError) Error() string {
var builder strings.Builder
builder.WriteString(fmt.Sprintf("task: Task %q cancelled because it is missing required variables:\n", err.TaskName))
builder.WriteString(fmt.Sprintf("task: Task %q cancelled because it is missing required variables:\n", err.TaskName)) //nolint:staticcheck
for _, s := range err.NotAllowedVars {
builder.WriteString(fmt.Sprintf(" - %s has an invalid value : '%s' (allowed values : %v)\n", s.Name, s.Value, s.Enum))
builder.WriteString(fmt.Sprintf(" - %s has an invalid value : '%s' (allowed values : %v)\n", s.Name, s.Value, s.Enum)) //nolint:staticcheck
}
return builder.String()

View File

@@ -11,14 +11,17 @@ import (
// TaskfileNotFoundError is returned when no appropriate Taskfile is found when
// searching the filesystem.
type TaskfileNotFoundError struct {
URI string
Walk bool
AskInit bool
URI string
Walk bool
AskInit bool
OwnerChange bool
}
func (err TaskfileNotFoundError) Error() string {
var walkText string
if err.Walk {
if err.OwnerChange {
walkText = " (or any of the parent directories until ownership changed)."
} else if err.Walk {
walkText = " (or any of the parent directories)."
}
if err.AskInit {

View File

@@ -927,6 +927,10 @@ func TestReference(t *testing.T) {
name: "reference using templating resolver and dynamic var",
call: "ref-resolver-sh",
},
{
name: "reference using templating resolver and global var",
call: "ref-global",
},
}
for _, test := range tests {

16
go.mod
View File

@@ -2,7 +2,7 @@ module github.com/go-task/task/v3
go 1.24.6
toolchain go1.25.6
toolchain go1.26.0
require (
charm.land/bubbles/v2 v2.0.0-rc.1
@@ -10,7 +10,7 @@ require (
charm.land/lipgloss/v2 v2.0.0-beta.3.0.20251106192539-4b304240aab7
github.com/Ladicle/tabwriter v1.0.0
github.com/Masterminds/semver/v3 v3.4.0
github.com/alecthomas/chroma/v2 v2.23.0
github.com/alecthomas/chroma/v2 v2.23.1
github.com/chainguard-dev/git-urls v1.0.2
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc
github.com/dominikbraun/graph v0.23.0
@@ -23,15 +23,15 @@ require (
github.com/hashicorp/go-getter v1.8.4
github.com/joho/godotenv v1.5.1
github.com/mitchellh/hashstructure/v2 v2.0.2
github.com/puzpuzpuz/xsync/v4 v4.3.0
github.com/puzpuzpuz/xsync/v4 v4.4.0
github.com/sajari/fuzzy v1.0.0
github.com/sebdah/goldie/v2 v2.8.0
github.com/spf13/pflag v1.0.10
github.com/stretchr/testify v1.11.1
github.com/zeebo/xxh3 v1.0.2
go.yaml.in/yaml/v4 v4.0.0-rc.3
github.com/zeebo/xxh3 v1.1.0
go.yaml.in/yaml/v3 v3.0.4
golang.org/x/sync v0.19.0
golang.org/x/term v0.39.0
golang.org/x/term v0.40.0
mvdan.cc/sh/moreinterp v0.0.0-20260120230322-19def062a997
mvdan.cc/sh/v3 v3.12.1-0.20260124232039-e74afc18e65b
)
@@ -95,7 +95,7 @@ require (
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-version v1.8.0 // indirect
github.com/klauspost/compress v1.18.2 // indirect
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
github.com/klauspost/cpuid/v2 v2.2.10 // indirect
github.com/klauspost/pgzip v1.2.6 // indirect
github.com/lucasb-eyer/go-colorful v1.3.0 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect
@@ -127,7 +127,7 @@ require (
golang.org/x/crypto v0.46.0 // indirect
golang.org/x/net v0.48.0 // indirect
golang.org/x/oauth2 v0.33.0 // indirect
golang.org/x/sys v0.40.0 // indirect
golang.org/x/sys v0.41.0 // indirect
golang.org/x/text v0.32.0 // indirect
golang.org/x/time v0.14.0 // indirect
google.golang.org/api v0.256.0 // indirect

16
go.sum
View File

@@ -42,6 +42,8 @@ github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8v
github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
github.com/alecthomas/chroma/v2 v2.23.0 h1:u/Orux1J0eLuZDeQ44froV8smumheieI0EofhbyKhhk=
github.com/alecthomas/chroma/v2 v2.23.0/go.mod h1:NqVhfBR0lte5Ouh3DcthuUCTUpDC9cxBOfyMbMQPs3o=
github.com/alecthomas/chroma/v2 v2.23.1 h1:nv2AVZdTyClGbVQkIzlDm/rnhk1E9bU9nXwmZ/Vk/iY=
github.com/alecthomas/chroma/v2 v2.23.1/go.mod h1:NqVhfBR0lte5Ouh3DcthuUCTUpDC9cxBOfyMbMQPs3o=
github.com/alecthomas/repr v0.5.2 h1:SU73FTI9D1P5UNtvseffFSGmdNci/O6RsqzeXJtP0Qs=
github.com/alecthomas/repr v0.5.2/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
@@ -185,6 +187,8 @@ github.com/klauspost/compress v1.18.2 h1:iiPHWW0YrcFgpBYhsA6D1+fqHssJscY/Tm/y2Uq
github.com/klauspost/compress v1.18.2/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE=
github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU=
github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
@@ -218,6 +222,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/puzpuzpuz/xsync/v4 v4.3.0 h1:w/bWkEJdYuRNYhHn5eXnIT8LzDM1O629X1I9MJSkD7Q=
github.com/puzpuzpuz/xsync/v4 v4.3.0/go.mod h1:VJDmTCJMBt8igNxnkQd86r+8KUeN1quSfNKu5bLYFQo=
github.com/puzpuzpuz/xsync/v4 v4.4.0 h1:vlSN6/CkEY0pY8KaB0yqo/pCLZvp9nhdbBdjipT4gWo=
github.com/puzpuzpuz/xsync/v4 v4.4.0/go.mod h1:VJDmTCJMBt8igNxnkQd86r+8KUeN1quSfNKu5bLYFQo=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
@@ -254,6 +260,8 @@ github.com/zeebo/errs v1.4.0 h1:XNdoD/RRMKP7HD0UhJnIzUy74ISdGGxURlYG8HSWSfM=
github.com/zeebo/errs v1.4.0/go.mod h1:sgbWHsvVuTPHcqJJGQ1WhI5KbWlHYz+2+2C/LSEtCw4=
github.com/zeebo/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0=
github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA=
github.com/zeebo/xxh3 v1.1.0 h1:s7DLGDK45Dyfg7++yxI0khrfwq9661w9EN78eP/UZVs=
github.com/zeebo/xxh3 v1.1.0/go.mod h1:IisAie1LELR4xhVinxWS5+zf1lA4p0MW4T+w+W07F5s=
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
go.opentelemetry.io/contrib/detectors/gcp v1.36.0 h1:F7q2tNlCaHY9nMKHR6XH9/qkp8FktLnIcy6jJNyOCQw=
@@ -274,8 +282,8 @@ go.opentelemetry.io/otel/sdk/metric v1.39.0 h1:cXMVVFVgsIf2YL6QkRF4Urbr/aMInf+2W
go.opentelemetry.io/otel/sdk/metric v1.39.0/go.mod h1:xq9HEVH7qeX69/JnwEfp6fVq5wosJsY1mt4lLfYdVew=
go.opentelemetry.io/otel/trace v1.39.0 h1:2d2vfpEDmCJ5zVYz7ijaJdOF59xLomrvj7bjt6/qCJI=
go.opentelemetry.io/otel/trace v1.39.0/go.mod h1:88w4/PnZSazkGzz/w84VHpQafiU4EtqqlVdxWy+rNOA=
go.yaml.in/yaml/v4 v4.0.0-rc.3 h1:3h1fjsh1CTAPjW7q/EMe+C8shx5d8ctzZTrLcs/j8Go=
go.yaml.in/yaml/v4 v4.0.0-rc.3/go.mod h1:aZqd9kCMsGL7AuUv/m/PvWLdg5sjJsZ4oHDEnfPPfY0=
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU=
golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0=
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 h1:nDVHiLt8aIbd/VzvPWN6kSOPE7+F/fNFDSXLVYkE/Iw=
@@ -290,8 +298,12 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY=
golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww=
golang.org/x/term v0.40.0 h1:36e4zGLqU4yhjlmxEaagx2KuYbJq3EwY8K943ZsHcvg=
golang.org/x/term v0.40.0/go.mod h1:w2P8uVp06p2iyKKuvXIm7N/y0UCRt3UfJTfZ7oOpglM=
golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU=
golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY=
golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=

62
internal/env/env.go vendored
View File

@@ -3,7 +3,9 @@ package env
import (
"fmt"
"os"
"strconv"
"strings"
"time"
"github.com/go-task/task/v3/experiments"
"github.com/go-task/task/v3/taskfile/ast"
@@ -61,3 +63,63 @@ func isTypeAllowed(v any) bool {
func GetTaskEnv(key string) string {
return os.Getenv(taskVarPrefix + key)
}
// GetTaskEnvBool returns the boolean value of a TASK_ prefixed env var.
// Returns the value and true if set and valid, or false and false if not set or invalid.
func GetTaskEnvBool(key string) (bool, bool) {
v := GetTaskEnv(key)
if v == "" {
return false, false
}
b, err := strconv.ParseBool(v)
return b, err == nil
}
// GetTaskEnvInt returns the integer value of a TASK_ prefixed env var.
// Returns the value and true if set and valid, or 0 and false if not set or invalid.
func GetTaskEnvInt(key string) (int, bool) {
v := GetTaskEnv(key)
if v == "" {
return 0, false
}
i, err := strconv.Atoi(v)
return i, err == nil
}
// GetTaskEnvDuration returns the duration value of a TASK_ prefixed env var.
// Returns the value and true if set and valid, or 0 and false if not set or invalid.
func GetTaskEnvDuration(key string) (time.Duration, bool) {
v := GetTaskEnv(key)
if v == "" {
return 0, false
}
d, err := time.ParseDuration(v)
return d, err == nil
}
// GetTaskEnvString returns the string value of a TASK_ prefixed env var.
// Returns the value and true if set (non-empty), or empty string and false if not set.
func GetTaskEnvString(key string) (string, bool) {
v := GetTaskEnv(key)
return v, v != ""
}
// GetTaskEnvStringSlice returns a comma-separated list from a TASK_ prefixed env var.
// Returns the slice and true if set (non-empty), or nil and false if not set.
func GetTaskEnvStringSlice(key string) ([]string, bool) {
v := GetTaskEnv(key)
if v == "" {
return nil, false
}
parts := strings.Split(v, ",")
result := make([]string, 0, len(parts))
for _, p := range parts {
if trimmed := strings.TrimSpace(p); trimmed != "" {
result = append(result, trimmed)
}
}
if len(result) == 0 {
return nil, false
}
return result, true
}

View File

@@ -130,15 +130,15 @@ func init() {
pflag.BoolVar(&Status, "status", false, "Exits with non-zero exit code if any of the given tasks is not up-to-date.")
pflag.BoolVar(&NoStatus, "no-status", false, "Ignore status when listing tasks as JSON")
pflag.BoolVar(&Nested, "nested", false, "Nest namespaces when listing tasks as JSON")
pflag.BoolVar(&Insecure, "insecure", getConfig(config, func() *bool { return config.Remote.Insecure }, false), "Forces Task to download Taskfiles over insecure connections.")
pflag.BoolVar(&Insecure, "insecure", getConfig(config, "REMOTE_INSECURE", func() *bool { return config.Remote.Insecure }, false), "Forces Task to download Taskfiles over insecure connections.")
pflag.BoolVarP(&Watch, "watch", "w", false, "Enables watch of the given task.")
pflag.BoolVarP(&Verbose, "verbose", "v", getConfig(config, func() *bool { return config.Verbose }, false), "Enables verbose mode.")
pflag.BoolVarP(&Silent, "silent", "s", false, "Disables echoing.")
pflag.BoolVar(&DisableFuzzy, "disable-fuzzy", getConfig(config, func() *bool { return config.DisableFuzzy }, false), "Disables fuzzy matching for task names.")
pflag.BoolVarP(&AssumeYes, "yes", "y", false, "Assume \"yes\" as answer to all prompts.")
pflag.BoolVar(&Interactive, "interactive", getConfig(config, func() *bool { return config.Interactive }, false), "Prompt for missing required variables.")
pflag.BoolVarP(&Verbose, "verbose", "v", getConfig(config, "VERBOSE", func() *bool { return config.Verbose }, false), "Enables verbose mode.")
pflag.BoolVarP(&Silent, "silent", "s", getConfig(config, "SILENT", func() *bool { return config.Silent }, false), "Disables echoing.")
pflag.BoolVar(&DisableFuzzy, "disable-fuzzy", getConfig(config, "DISABLE_FUZZY", func() *bool { return config.DisableFuzzy }, false), "Disables fuzzy matching for task names.")
pflag.BoolVarP(&AssumeYes, "yes", "y", getConfig(config, "ASSUME_YES", func() *bool { return nil }, false), "Assume \"yes\" as answer to all prompts.")
pflag.BoolVar(&Interactive, "interactive", getConfig(config, "INTERACTIVE", func() *bool { return config.Interactive }, false), "Prompt for missing required variables.")
pflag.BoolVarP(&Parallel, "parallel", "p", false, "Executes tasks provided on command line in parallel.")
pflag.BoolVarP(&Dry, "dry", "n", false, "Compiles and prints tasks in the order that they would be run, without executing them.")
pflag.BoolVarP(&Dry, "dry", "n", getConfig(config, "DRY", func() *bool { return nil }, false), "Compiles and prints tasks in the order that they would be run, without executing them.")
pflag.BoolVar(&Summary, "summary", false, "Show summary about a task.")
pflag.BoolVarP(&ExitCode, "exit-code", "x", false, "Pass-through the exit code of the task command.")
pflag.StringVarP(&Dir, "dir", "d", "", "Sets the directory in which Task will execute and look for a Taskfile.")
@@ -147,10 +147,10 @@ func init() {
pflag.StringVar(&Output.Group.Begin, "output-group-begin", "", "Message template to print before a task's grouped output.")
pflag.StringVar(&Output.Group.End, "output-group-end", "", "Message template to print after a task's grouped output.")
pflag.BoolVar(&Output.Group.ErrorOnly, "output-group-error-only", false, "Swallow output from successful tasks.")
pflag.BoolVarP(&Color, "color", "c", getConfig(config, func() *bool { return config.Color }, true), "Colored output. Enabled by default. Set flag to false or use NO_COLOR=1 to disable.")
pflag.IntVarP(&Concurrency, "concurrency", "C", getConfig(config, func() *int { return config.Concurrency }, 0), "Limit number of tasks to run concurrently.")
pflag.BoolVarP(&Color, "color", "c", getConfig(config, "COLOR", func() *bool { return config.Color }, true), "Colored output. Enabled by default. Set flag to false or use NO_COLOR=1 to disable.")
pflag.IntVarP(&Concurrency, "concurrency", "C", getConfig(config, "CONCURRENCY", func() *int { return config.Concurrency }, 0), "Limit number of tasks to run concurrently.")
pflag.DurationVarP(&Interval, "interval", "I", 0, "Interval to watch for changes.")
pflag.BoolVarP(&Failfast, "failfast", "F", getConfig(config, func() *bool { return &config.Failfast }, false), "When running tasks in parallel, stop all tasks if one fails.")
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.")
@@ -165,21 +165,21 @@ func init() {
// 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, func() *bool { return config.Remote.Offline }, false), "Forces Task to only use local or cached Taskfiles.")
pflag.StringSliceVar(&TrustedHosts, "trusted-hosts", getConfig(config, func() *[]string { return &config.Remote.TrustedHosts }, nil), "List of trusted hosts for remote Taskfiles (comma-separated).")
pflag.DurationVar(&Timeout, "timeout", getConfig(config, func() *time.Duration { return config.Remote.Timeout }, time.Second*10), "Timeout for downloading remote Taskfiles.")
pflag.BoolVar(&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, func() *time.Duration { return config.Remote.CacheExpiry }, 0), "Expiry duration for cached remote Taskfiles.")
pflag.StringVar(&RemoteCacheDir, "remote-cache-dir", getConfig(config, func() *string { return config.Remote.CacheDir }, env.GetTaskEnv("REMOTE_DIR")), "Directory to cache remote Taskfiles.")
pflag.StringVar(&CACert, "cacert", getConfig(config, func() *string { return config.Remote.CACert }, ""), "Path to a custom CA certificate for HTTPS connections.")
pflag.StringVar(&Cert, "cert", getConfig(config, func() *string { return config.Remote.Cert }, ""), "Path to a client certificate for HTTPS connections.")
pflag.StringVar(&CertKey, "cert-key", getConfig(config, func() *string { return config.Remote.CertKey }, ""), "Path to a client certificate key for HTTPS connections.")
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
// Priority: CLI flag > taskrc config > NO_COLOR > FORCE_COLOR/CI > default
colorExplicitlySet := pflag.Lookup("color").Changed || (config != nil && config.Color != nil)
// Priority: CLI flag > TASK_COLOR env > taskrc config > NO_COLOR > FORCE_COLOR/CI > default
colorExplicitlySet := pflag.Lookup("color").Changed || env.GetTaskEnv("COLOR") != "" || (config != nil && config.Color != nil)
if !colorExplicitlySet {
if os.Getenv("NO_COLOR") != "" {
Color = false
@@ -311,15 +311,45 @@ func (o *flagsOption) ApplyToExecutor(e *task.Executor) {
)
}
// getConfig extracts a config value directly from a pointer field with a fallback default
func getConfig[T any](config *taskrcast.TaskRC, fieldFunc func() *T, fallback T) T {
if config == nil {
return fallback
// getConfig extracts a config value with priority: env var > taskrc config > fallback
func getConfig[T any](config *taskrcast.TaskRC, envKey string, fieldFunc func() *T, fallback T) T {
if envKey != "" {
if val, ok := getEnvAs[T](envKey); ok {
return val
}
}
field := fieldFunc()
if field != nil {
return *field
if config != nil {
if field := fieldFunc(); field != nil {
return *field
}
}
return fallback
}
// getEnvAs parses a TASK_ prefixed env var as type T
func getEnvAs[T any](envKey string) (T, bool) {
var zero T
switch any(zero).(type) {
case bool:
if val, ok := env.GetTaskEnvBool(envKey); ok {
return any(val).(T), true
}
case int:
if val, ok := env.GetTaskEnvInt(envKey); ok {
return any(val).(T), true
}
case time.Duration:
if val, ok := env.GetTaskEnvDuration(envKey); ok {
return any(val).(T), true
}
case string:
if val, ok := env.GetTaskEnvString(envKey); ok {
return any(val).(T), true
}
case []string:
if val, ok := env.GetTaskEnvStringSlice(envKey); ok {
return any(val).(T), true
}
}
return zero, false
}

View File

@@ -108,10 +108,10 @@ func SearchAll(entrypoint, dir string, possibleFilenames []string) ([]string, er
}
}
paths, err := SearchNPathRecursively(dir, possibleFilenames, -1)
if err != nil {
return nil, err
}
return append(entrypoints, paths...), nil
// The call to SearchNPathRecursively is ambiguous and may return
// os.ErrPermission if its search ends, however it may have still
// returned valid paths. Caller may choose to ignore that error.
return append(entrypoints, paths...), err
}
// SearchPath will check if a file at the given path exists or not. If it does,
@@ -188,9 +188,12 @@ func SearchNPathRecursively(path string, possibleFilenames []string, n int) ([]s
return nil, err
}
// Error if we reached the root directory and still haven't found a file
// OR if the user id of the directory changes
if path == parentPath || (parentOwner != owner) {
// If the user id of the directory changes indicate a permission error, otherwise
// the calling code will infer an error condition based on the accumulated
// contents of paths.
if parentOwner != owner {
return paths, os.ErrPermission
} else if path == parentPath {
return paths, nil
}

View File

@@ -231,7 +231,7 @@ func formatMap(m map[string]any, indent int) string {
spaces := strings.Repeat(" ", indent)
for k, v := range m {
result.WriteString(fmt.Sprintf("%s%s: %v\n", spaces, k, v))
result.WriteString(fmt.Sprintf("%s%s: %v\n", spaces, k, v)) //nolint:staticcheck
}
return result.String()

View File

@@ -9,7 +9,7 @@ import (
"github.com/davecgh/go-spew/spew"
"github.com/google/uuid"
"go.yaml.in/yaml/v4"
"go.yaml.in/yaml/v3"
"mvdan.cc/sh/v3/shell"
"mvdan.cc/sh/v3/syntax"

View File

@@ -16,7 +16,6 @@ import (
"github.com/go-task/task/v3/internal/env"
"github.com/go-task/task/v3/internal/execext"
"github.com/go-task/task/v3/internal/filepathext"
"github.com/go-task/task/v3/internal/fsext"
"github.com/go-task/task/v3/internal/logger"
"github.com/go-task/task/v3/internal/output"
"github.com/go-task/task/v3/internal/version"
@@ -60,12 +59,10 @@ func (e *Executor) getRootNode() (taskfile.Node, error) {
taskfile.WithCert(e.Cert),
taskfile.WithCertKey(e.CertKey),
)
if os.IsNotExist(err) {
return nil, errors.TaskfileNotFoundError{
URI: fsext.DefaultDir(e.Entrypoint, e.Dir),
Walk: true,
AskInit: true,
}
var taskNotFoundError errors.TaskfileNotFoundError
if errors.As(err, &taskNotFoundError) {
taskNotFoundError.AskInit = true
return nil, taskNotFoundError
}
if err != nil {
return nil, err

View File

@@ -1,7 +1,7 @@
package ast
import (
"go.yaml.in/yaml/v4"
"go.yaml.in/yaml/v3"
"github.com/go-task/task/v3/errors"
"github.com/go-task/task/v3/internal/deepcopy"

View File

@@ -1,7 +1,7 @@
package ast
import (
"go.yaml.in/yaml/v4"
"go.yaml.in/yaml/v3"
"github.com/go-task/task/v3/errors"
)

View File

@@ -1,7 +1,7 @@
package ast
import (
"go.yaml.in/yaml/v4"
"go.yaml.in/yaml/v3"
"github.com/go-task/task/v3/errors"
)

View File

@@ -1,7 +1,7 @@
package ast
import (
"go.yaml.in/yaml/v4"
"go.yaml.in/yaml/v3"
"github.com/go-task/task/v3/errors"
"github.com/go-task/task/v3/internal/deepcopy"

View File

@@ -1,7 +1,7 @@
package ast
import (
"go.yaml.in/yaml/v4"
"go.yaml.in/yaml/v3"
"github.com/go-task/task/v3/errors"
)

View File

@@ -5,7 +5,7 @@ import (
"sync"
"github.com/elliotchance/orderedmap/v3"
"go.yaml.in/yaml/v4"
"go.yaml.in/yaml/v3"
"github.com/go-task/task/v3/errors"
"github.com/go-task/task/v3/internal/deepcopy"

View File

@@ -4,7 +4,7 @@ import (
"iter"
"github.com/elliotchance/orderedmap/v3"
"go.yaml.in/yaml/v4"
"go.yaml.in/yaml/v3"
"github.com/go-task/task/v3/errors"
"github.com/go-task/task/v3/internal/deepcopy"

View File

@@ -1,7 +1,7 @@
package ast
import (
"go.yaml.in/yaml/v4"
"go.yaml.in/yaml/v3"
"github.com/go-task/task/v3/errors"
)

View File

@@ -4,7 +4,7 @@ import (
"fmt"
"strings"
"go.yaml.in/yaml/v4"
"go.yaml.in/yaml/v3"
"github.com/go-task/task/v3/errors"
"github.com/go-task/task/v3/internal/goext"

View File

@@ -3,7 +3,7 @@ package ast
import (
"fmt"
"go.yaml.in/yaml/v4"
"go.yaml.in/yaml/v3"
"github.com/go-task/task/v3/errors"
)

View File

@@ -5,7 +5,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.yaml.in/yaml/v4"
"go.yaml.in/yaml/v3"
"github.com/go-task/task/v3/taskfile/ast"
)

View File

@@ -1,7 +1,7 @@
package ast
import (
"go.yaml.in/yaml/v4"
"go.yaml.in/yaml/v3"
"github.com/go-task/task/v3/errors"
)

View File

@@ -1,7 +1,7 @@
package ast
import (
"go.yaml.in/yaml/v4"
"go.yaml.in/yaml/v3"
"github.com/go-task/task/v3/errors"
"github.com/go-task/task/v3/internal/deepcopy"

View File

@@ -5,7 +5,7 @@ import (
"regexp"
"strings"
"go.yaml.in/yaml/v4"
"go.yaml.in/yaml/v3"
"github.com/go-task/task/v3/errors"
"github.com/go-task/task/v3/internal/deepcopy"
@@ -242,6 +242,7 @@ func (t *Task) DeepCopy() *Task {
Requires: t.Requires.DeepCopy(),
Namespace: t.Namespace,
FullName: t.FullName,
Watch: t.Watch,
Failfast: t.Failfast,
}
return c

View File

@@ -5,7 +5,7 @@ import (
"time"
"github.com/Masterminds/semver/v3"
"go.yaml.in/yaml/v4"
"go.yaml.in/yaml/v3"
"github.com/go-task/task/v3/errors"
)

View File

@@ -5,7 +5,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.yaml.in/yaml/v4"
"go.yaml.in/yaml/v3"
"github.com/go-task/task/v3/taskfile/ast"
)

View File

@@ -8,7 +8,7 @@ import (
"sync"
"github.com/elliotchance/orderedmap/v3"
"go.yaml.in/yaml/v4"
"go.yaml.in/yaml/v3"
"github.com/go-task/task/v3/errors"
"github.com/go-task/task/v3/internal/filepathext"

View File

@@ -1,7 +1,7 @@
package ast
import (
"go.yaml.in/yaml/v4"
"go.yaml.in/yaml/v3"
"github.com/go-task/task/v3/errors"
)

View File

@@ -5,7 +5,7 @@ import (
"sync"
"github.com/elliotchance/orderedmap/v3"
"go.yaml.in/yaml/v4"
"go.yaml.in/yaml/v3"
"github.com/go-task/task/v3/errors"
"github.com/go-task/task/v3/internal/deepcopy"

View File

@@ -22,7 +22,13 @@ func NewFileNode(entrypoint, dir string, opts ...NodeOption) (*FileNode, error)
resolvedEntrypoint, err := fsext.Search(entrypoint, dir, DefaultTaskfiles)
if err != nil {
if errors.Is(err, os.ErrNotExist) {
return nil, errors.TaskfileNotFoundError{URI: entrypoint, Walk: false}
if entrypoint == "" {
return nil, errors.TaskfileNotFoundError{URI: entrypoint, Walk: true}
} else {
return nil, errors.TaskfileNotFoundError{URI: entrypoint, Walk: false}
}
} else if errors.Is(err, os.ErrPermission) {
return nil, errors.TaskfileNotFoundError{URI: entrypoint, Walk: true, OwnerChange: true}
}
return nil, err
}

View File

@@ -5,6 +5,7 @@ import (
"fmt"
"net/url"
"os"
"path"
"path/filepath"
"strings"
"sync"
@@ -127,19 +128,19 @@ func (node *GitNode) getOrCloneRepo(ctx context.Context) (string, error) {
repoMutex.Lock()
defer repoMutex.Unlock()
// Check if context was cancelled while waiting for lock
if err := ctx.Err(); err != nil {
return "", fmt.Errorf("context cancelled while waiting for repository lock: %w", err)
}
cacheDir := filepath.Join(os.TempDir(), "task-git-repos", cacheKey)
// check if repo is already cached (under the lock)
// Check cache FIRST - if already cloned, no network needed, timeout irrelevant
gitDir := filepath.Join(cacheDir, ".git")
if _, err := os.Stat(gitDir); err == nil {
return cacheDir, nil
}
// Only check context if we need to clone (requires network)
if err := ctx.Err(); err != nil {
return "", fmt.Errorf("context cancelled while waiting for repository lock: %w", err)
}
getterURL := node.buildURL()
client := &getter.Client{
@@ -191,8 +192,8 @@ func (node *GitNode) ResolveEntrypoint(entrypoint string) (string, error) {
return entrypoint, nil
}
dir, _ := filepath.Split(node.path)
resolvedEntrypoint := fmt.Sprintf("%s//%s", node.url, filepath.Join(dir, entrypoint))
dir, _ := path.Split(node.path)
resolvedEntrypoint := fmt.Sprintf("%s//%s", node.url, path.Join(dir, entrypoint))
if node.ref != "" {
return fmt.Sprintf("%s?ref=%s", resolvedEntrypoint, node.ref), nil
}

View File

@@ -9,7 +9,7 @@ import (
"time"
"github.com/dominikbraun/graph"
"go.yaml.in/yaml/v4"
"go.yaml.in/yaml/v3"
"golang.org/x/sync/errgroup"
"github.com/go-task/task/v3/errors"

View File

@@ -12,6 +12,7 @@ import (
type TaskRC struct {
Version *semver.Version `yaml:"version"`
Verbose *bool `yaml:"verbose"`
Silent *bool `yaml:"silent"`
Color *bool `yaml:"color"`
DisableFuzzy *bool `yaml:"disable-fuzzy"`
Concurrency *int `yaml:"concurrency"`
@@ -63,6 +64,7 @@ func (t *TaskRC) Merge(other *TaskRC) {
t.Remote.CertKey = cmp.Or(other.Remote.CertKey, t.Remote.CertKey)
t.Verbose = cmp.Or(other.Verbose, t.Verbose)
t.Silent = cmp.Or(other.Silent, t.Silent)
t.Color = cmp.Or(other.Color, t.Color)
t.DisableFuzzy = cmp.Or(other.DisableFuzzy, t.DisableFuzzy)
t.Concurrency = cmp.Or(other.Concurrency, t.Concurrency)

View File

@@ -3,7 +3,7 @@ package taskrc
import (
"os"
"go.yaml.in/yaml/v4"
"go.yaml.in/yaml/v3"
"github.com/go-task/task/v3/taskrc/ast"
)

View File

@@ -6,6 +6,7 @@ import (
"slices"
"strings"
"github.com/go-task/task/v3/errors"
"github.com/go-task/task/v3/internal/fsext"
"github.com/go-task/task/v3/taskrc/ast"
)
@@ -62,6 +63,9 @@ func GetConfig(dir string) (*ast.TaskRC, error) {
return config, err
}
entrypoints, err := fsext.SearchAll("", absDir, defaultTaskRCs)
if errors.Is(err, os.ErrPermission) {
err = nil
}
if err != nil {
return config, err
}

View File

@@ -2,6 +2,9 @@ version: '3'
vars:
GLOBAL_VAR: [1, 2, 2, 2, 3, 3, 4, 5]
GLOBAL_FOO:
ref: .GLOBAL_BAR
GLOBAL_BAR: bar
tasks:
default:
@@ -9,6 +12,7 @@ tasks:
- task: ref-dep
- task: ref-resolver
- task: ref-resolver-sh
- task: ref-global
ref-cmd:
vars:
@@ -72,3 +76,13 @@ tasks:
{{- else}} and {{$child.name -}}
{{- end -}}
{{- end -}}"
ref-global:
vars:
TASK_FUBAR:
ref: .GLOBAL_FOO
cmds:
- echo "GLOBAL_FOO={{.GLOBAL_FOO}}"
- echo "GLOBAL_BAR={{.GLOBAL_BAR}}"
- echo "TASK_FUBAR={{.TASK_FUBAR}}"
silent: true

View File

@@ -0,0 +1,3 @@
GLOBAL_FOO=bar
GLOBAL_BAR=bar
TASK_FUBAR=bar

View File

@@ -90,12 +90,16 @@ export default defineConfig({
head.push(['link', { rel: 'canonical', href: canonicalUrl }])
// Dynamic Open Graph and Twitter meta tags
const pageTitle = pageData.frontmatter.title || pageData.title || taskName
const isHome = pageData.relativePath === 'index.md';
var pageTitle = pageData.frontmatter.title || pageData.title || taskName;
if (!isHome) {
pageTitle = `${pageTitle} | ${taskName}`;
}
const pageDescription = pageData.frontmatter.description || pageData.description || taskDescription
head.push(['meta', { property: 'og:title', content: `${pageTitle} | Task` }])
head.push(['meta', { property: 'og:title', content: pageTitle }])
head.push(['meta', { property: 'og:description', content: pageDescription }])
head.push(['meta', { property: 'og:url', content: canonicalUrl }])
head.push(['meta', { name: 'twitter:title', content: `${pageTitle} | Task` }])
head.push(['meta', { name: 'twitter:title', content: pageTitle }])
head.push(['meta', { name: 'twitter:description', content: pageDescription }])
// Noindex pour 404
@@ -370,6 +374,11 @@ export default defineConfig({
{ icon: 'mastodon', link: 'https://fosstodon.org/@task' }
],
editLink: {
text: 'Edit this page on GitHub',
pattern: 'https://github.com/go-task/task/edit/main/website/src/:path'
},
footer: {
message:
'Built with <a target="_blank" href="https://www.netlify.com">Netlify</a>'

View File

@@ -3,4 +3,4 @@ export const taskDescription =
'A fast, cross-platform build tool inspired by Make, designed for modern workflows.';
export const ogUrl = 'https://taskfile.dev/';
export const ogImage = 'https://taskfile.dev/img/logo.png';
export const ogImage = 'https://taskfile.dev/img/og_image.png';

View File

@@ -8,6 +8,11 @@ export const sponsors = [
url: 'https://devowl.io/',
img: '/img/devowl.io.svg'
},
{
name: 'GoodX',
url: 'https://goodx.international/',
img: '/img/goodx.svg'
},
{
name: 'Magic',
url: 'https://magic.dev/',

View File

@@ -23,5 +23,5 @@
"vitepress-plugin-llms": "^1.9.1",
"vue": "^3.5.18"
},
"packageManager": "pnpm@10.28.1+sha512.7d7dbbca9e99447b7c3bf7a73286afaaf6be99251eb9498baefa7d406892f67b879adb3a1d7e687fc4ccc1a388c7175fbaae567a26ab44d1067b54fcb0d6a316"
"packageManager": "pnpm@10.30.0+sha512.2b5753de015d480eeb88f5b5b61e0051f05b4301808a82ec8b840c9d2adf7748eb352c83f5c1593ca703ff1017295bc3fdd3119abb9686efc96b9fcb18200937"
}

2483
website/pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -3,6 +3,7 @@ title: Any Variables
author: pd93
date: 2024-05-09
outline: deep
editLink: false
---
# Any Variables

View File

@@ -4,9 +4,10 @@ description: Introduction of the `if:` control and required variable prompts.
author: vmaerten
date: 2026-01-24
outline: deep
editLink: false
---
# New `if:` control and interactivity support
# New `if:` Control and Variable Prompt
<AuthorCard :author="$frontmatter.author" />

View File

@@ -1,6 +1,7 @@
---
title: Blog
description: Latest news and updates from the Task team
editLink: false
---
<BlogPost

View File

@@ -5,6 +5,7 @@ description:
author: pd93
date: 2024-05-09
outline: deep
editLink: false
---
# Introducing Experiments

View File

@@ -4,6 +4,7 @@ description: The journey of enhancing Windows support in Task.
author: andreynering
date: 2025-09-15
outline: deep
editLink: false
---
# Announcing Built-in Core Utilities for Windows

View File

@@ -1,6 +1,7 @@
---
title: Changelog
outline: deep
editLink: false
---
# Changelog
@@ -1479,4 +1480,4 @@ document, since it describes in depth what changed for this version.
- Add LICENSE file
:::
:::

View File

@@ -355,6 +355,8 @@ remote:
- **Type**: `boolean`
- **Default**: `false`
- **Description**: Allow insecure connections when fetching remote Taskfiles
- **CLI equivalent**: `--insecure`
- **Environment variable**: `TASK_REMOTE_INSECURE`
```yaml
remote:
@@ -366,6 +368,8 @@ remote:
- **Type**: `boolean`
- **Default**: `false`
- **Description**: Work in offline mode, preventing remote Taskfile fetching
- **CLI equivalent**: `--offline`
- **Environment variable**: `TASK_REMOTE_OFFLINE`
```yaml
remote:
@@ -378,6 +382,8 @@ remote:
- **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:
@@ -391,6 +397,8 @@ remote:
- **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:
@@ -404,7 +412,7 @@ remote:
- **Description**: Directory where remote Taskfiles are cached. Can be an
absolute path (e.g., `/var/cache/task`) or relative to the Taskfile directory.
- **CLI equivalent**: `--remote-cache-dir`
- **Environment variable**: `TASK_REMOTE_DIR` (lowest priority)
- **Environment variable**: `TASK_REMOTE_CACHE_DIR`
```yaml
remote:
@@ -418,6 +426,7 @@ remote:
- **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:

View File

@@ -45,10 +45,21 @@ Then you can install Task with:
apt install task
```
:::info Package Repository Hosting
[![Hosted By: Cloudsmith](https://img.shields.io/badge/OSS%20hosting%20by-cloudsmith-blue?logo=cloudsmith&style=for-the-badge)](https://cloudsmith.com)
Package repository hosting for deb/rpm is graciously provided by [Cloudsmith](https://cloudsmith.com).
Cloudsmith is the only fully hosted, cloud-native, universal package management solution, that
enables your organization to create, store and share packages in any format, to any place, with total
confidence.
:::
### [Homebrew](https://brew.sh) ![macOS](https://img.shields.io/badge/MacOS-000000?logo=apple&logoColor=F0F0F0) ![Linux](https://img.shields.io/badge/Linux-FCC624?logo=linux&logoColor=black) {#homebrew}
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
brew install go-task/tap/go-task

View File

@@ -12,9 +12,9 @@ outline: deep
Task has an
[official extension for Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=task.vscode-task).
The code for this project can be found
[here](https://github.com/go-task/vscode-task). To use this extension, you must
have Task v3.23.0+ installed on your system.
The code for this project can be found in
[our GitHub repository](https://github.com/go-task/vscode-task). To use this
extension, you must have Task v3.45.3+ installed on your system.
This extension provides the following features (and more):
@@ -30,6 +30,19 @@ To get autocompletion and validation for your Taskfile, see the
![Task for Visual Studio Code](https://github.com/go-task/vscode-task/blob/main/res/preview.png?raw=true)
### Configuration namespace change
In v1.0.0 of the extension, the configuration namespace was changed from `task`
to `taskfile` in order to fix
[an issue](https://github.com/go-task/vscode-task/issues/56).
![Configuration namespace change warning](../public/img/config-namespace-change.png)
If you receive a warning like the one above, you will need to update your
settings to use the new `taskfile` namespace instead:
![Configuration namespace diff](../public/img/config-namespace-diff.png)
## Schema
This was initially created by @KROSF in

View File

@@ -10,8 +10,8 @@ outline: deep
Task has multiple ways of being configured. These methods are parsed, in
sequence, in the following order with the highest priority last:
- [Environment variables](./environment.md)
- [Configuration files](./config.md)
- [Environment variables](./environment.md)
- _Command-line flags_
In this document, we will look at the last of the three options, command-line
@@ -72,6 +72,14 @@ task --init
task -i
```
::: tip
Combine `--list` or `--list-all` with `--silent` (`-ls` or `-as` for shortants)
to list only the task names in each line. Useful for scripting with `grep` or
similar.
:::
## Options
### General
@@ -96,6 +104,9 @@ task --version
Enable verbose mode for detailed output.
- **Config equivalent**: [`verbose`](./config.md#verbose)
- **Environment variable**: [`TASK_VERBOSE`](./environment.md#task-verbose)
```bash
task build --verbose
```
@@ -104,13 +115,20 @@ task build --verbose
Disable command echoing.
- **Config equivalent**: [`silent`](./config.md#silent)
- **Environment variable**: [`TASK_SILENT`](./environment.md#task-silent)
```bash
task deploy --silent
```
#### `--disable-fuzzy`
Disable fuzzy matching for task names. When enabled, Task will not suggest similar task names when you mistype a task name.
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)
```bash
task buidl --disable-fuzzy
@@ -124,6 +142,9 @@ task buidl --disable-fuzzy
Stop executing dependencies as soon as one of them fails.
- **Config equivalent**: [`failfast`](./config.md#failfast)
- **Environment variable**: [`TASK_FAILFAST`](./environment.md#task-failfast)
```bash
task build --failfast
```
@@ -140,6 +161,8 @@ task build --force
Compile and print tasks without executing them.
- **Environment variable**: [`TASK_DRY`](./environment.md#task-dry)
```bash
task deploy --dry
```
@@ -156,6 +179,9 @@ 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)
```bash
task test --concurrency 4
```
@@ -232,6 +258,9 @@ task test --output group --output-group-error-only
Control colored output. Enabled by default.
- **Config equivalent**: [`color`](./config.md#color)
- **Environment variable**: [`TASK_COLOR`](./environment.md#task-color)
```bash
task build --color=false
# or use environment variable
@@ -266,7 +295,12 @@ task --list --json
#### `--sort <mode>`
Change task listing order. Available modes: `default`, `alphanumeric`, `none`.
Change task listing order. Available modes:
- `default` - Sorts tasks alphabetically by name, but ensures that root tasks
(tasks without a namespace) are listed before namespaced tasks.
- `alphanumeric` - Sort tasks alphabetically by name.
- `none` - No sorting. Uses the order as defined in the Taskfile.
```bash
task --list --sort alphanumeric
@@ -297,6 +331,8 @@ task build --watch --interval 1s
Automatically answer "yes" to all prompts.
- **Environment variable**: [`TASK_ASSUME_YES`](./environment.md#task-assume-yes)
```bash
task deploy --yes
```
@@ -306,9 +342,11 @@ task deploy --yes
Enable interactive prompts for missing required variables. When a required
variable is not provided, Task will prompt for input instead of failing.
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.
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)
```bash
task deploy --interactive

View File

@@ -10,11 +10,11 @@ outline: deep
Task has multiple ways of being configured. These methods are parsed, in
sequence, in the following order with the highest priority last:
- [Environment variables](./environment.md)
- _Configuration files_
- [Environment variables](./environment.md)
- [Command-line flags](./cli.md)
In this document, we will look at the second of the three options, configuration
In this document, we will look at the first of the three options, configuration
files.
## File Precedence
@@ -86,17 +86,31 @@ experiments:
- **Default**: `false`
- **Description**: Enable verbose output for all tasks
- **CLI equivalent**: [`-v, --verbose`](./cli.md#-v---verbose)
- **Environment variable**: [`TASK_VERBOSE`](./environment.md#task-verbose)
```yaml
verbose: true
```
### `silent`
- **Type**: `boolean`
- **Default**: `false`
- **Description**: Disables echoing of commands
- **CLI equivalent**: [`-s, --silent`](./cli.md#-s---silent)
- **Environment variable**: [`TASK_SILENT`](./environment.md#task-silent)
```yaml
silent: true
```
### `color`
- **Type**: `boolean`
- **Default**: `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)
```yaml
color: false
@@ -108,6 +122,7 @@ color: false
- **Default**: `false`
- **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)
```yaml
disable-fuzzy: true
@@ -119,6 +134,7 @@ 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)
```yaml
concurrency: 4
@@ -129,7 +145,8 @@ concurrency: 4
- **Type**: `boolean`
- **Default**: `false`
- **Description**: Stop executing dependencies as soon as one of them fail
- **CLI equivalent**: [`-F, --failfast`](./cli.md#f-failfast)
- **CLI equivalent**: [`-F, --failfast`](./cli.md#-f---failfast)
- **Environment variable**: [`TASK_FAILFAST`](./environment.md#task-failfast)
```yaml
failfast: true
@@ -156,6 +173,7 @@ Here's a complete example of a `.taskrc.yml` file with all available options:
```yaml
# Global settings
verbose: true
silent: false
color: true
disable-fuzzy: false
concurrency: 2

View File

@@ -9,16 +9,78 @@ outline: deep
Task has multiple ways of being configured. These methods are parsed, in
sequence, in the following order with the highest priority last:
- _Environment variables_
- [Configuration files](./config.md)
- _Environment variables_
- [Command-line flags](./cli.md)
In this document, we will look at the first of the three options, environment
In this document, we will look at the second of the three options, environment
variables. All Task-specific variables are prefixed with `TASK_` and override
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.
### `TASK_VERBOSE`
- **Type**: `boolean` (`true`, `false`, `1`, `0`)
- **Default**: `false`
- **Description**: Enable verbose output for all tasks
- **Config equivalent**: [`verbose`](./config.md#verbose)
### `TASK_SILENT`
- **Type**: `boolean` (`true`, `false`, `1`, `0`)
- **Default**: `false`
- **Description**: Disables echoing of commands
- **Config equivalent**: [`silent`](./config.md#silent)
### `TASK_COLOR`
- **Type**: `boolean` (`true`, `false`, `1`, `0`)
- **Default**: `true`
- **Description**: Enable colored output
- **Config equivalent**: [`color`](./config.md#color)
### `TASK_DISABLE_FUZZY`
- **Type**: `boolean` (`true`, `false`, `1`, `0`)
- **Default**: `false`
- **Description**: Disable fuzzy matching for task names
- **Config equivalent**: [`disable-fuzzy`](./config.md#disable-fuzzy)
### `TASK_CONCURRENCY`
- **Type**: `integer`
- **Description**: Limit number of tasks to run concurrently
- **Config equivalent**: [`concurrency`](./config.md#concurrency)
### `TASK_FAILFAST`
- **Type**: `boolean` (`true`, `false`, `1`, `0`)
- **Default**: `false`
- **Description**: When running tasks in parallel, stop all tasks if one fails
- **Config equivalent**: [`failfast`](./config.md#failfast)
### `TASK_DRY`
- **Type**: `boolean` (`true`, `false`, `1`, `0`)
- **Default**: `false`
- **Description**: Compiles and prints tasks in the order that they would be run, without executing them
### `TASK_ASSUME_YES`
- **Type**: `boolean` (`true`, `false`, `1`, `0`)
- **Default**: `false`
- **Description**: Assume "yes" as answer to all prompts
### `TASK_INTERACTIVE`
- **Type**: `boolean` (`true`, `false`, `1`, `0`)
- **Default**: `false`
- **Description**: Prompt for missing required variables
### `TASK_TEMP_DIR`
Defines the location of Task's temporary directory which is used for storing
@@ -34,18 +96,6 @@ 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.
### `TASK_REMOTE_DIR`
Defines the location of Task's remote temporary directory which is used for
caching remote files. Can be relative like `tmp/task` or absolute like
`/tmp/.task` or `~/.task`. Relative paths are relative to the root Taskfile, not
the working directory. Defaults to: `./.task`.
### `TASK_OFFLINE`
Set the `--offline` flag through the environment variable. Only for remote
experiment. CLI flag `--offline` takes precedence over the env variable.
### `FORCE_COLOR`
Force color output usage.

View File

@@ -637,7 +637,7 @@ tasks:
- go build -ldflags="-s -w" ./...
```
### `dir`
#### `dir`
- **Type**: `string`
- **Description**: The directory in which this task should run

View File

@@ -23,7 +23,7 @@ defined in the above GitHub Actions.
## Homebrew
Goreleaser will automatically push a new commit to the
[Formula/go-task.rb][gotaskrb] file in the [Homebrew tap][homebrewtap]
[Casks/go-task.rb][gotaskrb] file in the [Homebrew tap][homebrewtap]
repository to release the new version.
## npm
@@ -66,7 +66,7 @@ If you think its Task version is outdated, open an issue to let us know.
[goreleaser]: https://goreleaser.com/
[homebrewtap]: https://github.com/go-task/homebrew-tap
[gotaskrb]: https://github.com/go-task/homebrew-tap/blob/main/Formula/go-task.rb
[gotaskrb]: https://github.com/go-task/homebrew-tap/blob/main/Casks/go-task.rb
[packagejson]: https://github.com/go-task/task/blob/main/package.json#L3
[snappackage]: https://github.com/go-task/snap
[snapcraftyaml]:

View File

@@ -2,6 +2,7 @@
title: Donate
layout: doc
outline: false
editLink: false
---
# :raised_hands: Support Task

View File

@@ -1,4 +1,5 @@
---
title: "Task: The Modern Task Runner"
layout: home
hero:
name: Task

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

View File

@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg id="Layer_2" data-name="Layer 2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 809.71 363.16">
<defs>
<style>
.cls-1 {
fill: #4d4d4e;
}
.cls-2 {
fill-rule: evenodd;
}
.cls-2, .cls-3 {
fill: #0580c3;
}
</style>
</defs>
<g id="Layer_1-2" data-name="Layer 1">
<g id="International_logo" data-name="International logo">
<g id="International_logo-2" data-name="International logo">
<g>
<path class="cls-3" d="M79.14,271.86c-14.64,0-27.95-2.94-39.93-8.81-11.99-5.87-21.52-14.76-28.59-26.66-7.08-11.9-10.62-26.78-10.62-44.64,0-13.19,2.09-24.89,6.27-35.1,4.18-10.22,9.89-18.86,17.13-25.94,7.24-7.08,15.56-12.42,24.97-16.04,9.41-3.62,19.34-5.43,29.8-5.43,11.58,0,21.63,2.05,30.16,6.15,8.52,4.1,15.52,8.97,20.99,14.6l-21.72,26.54c-3.86-3.38-7.92-6.15-12.18-8.33-4.26-2.17-9.53-3.25-15.81-3.25-10.62,0-19.46,3.98-26.54,11.94-7.08,7.96-10.62,19.11-10.62,33.42s3.33,25.94,10.01,33.9c6.67,7.96,17.01,11.94,31,11.94,2.25,0,4.46-.24,6.64-.72,2.17-.48,3.98-1.21,5.43-2.17v-21.71h-23.16v-33.78h59.84v74.8c-5.47,5.31-12.91,9.85-22.32,13.63-9.41,3.78-19.66,5.67-30.76,5.67Z"/>
<path class="cls-3" d="M209.2,271.86c-10.3,0-19.99-2.5-29.08-7.48-9.09-4.98-16.49-12.19-22.2-21.6-5.71-9.41-8.56-20.79-8.56-34.14s2.85-24.73,8.56-34.14c5.71-9.41,13.11-16.61,22.2-21.6,9.09-4.98,18.78-7.48,29.08-7.48s19.99,2.5,29.07,7.48c9.09,4.99,16.49,12.19,22.2,21.6,5.71,9.41,8.57,20.79,8.57,34.14s-2.86,24.73-8.57,34.14c-5.71,9.41-13.11,16.61-22.2,21.6-9.09,4.98-18.78,7.48-29.07,7.48ZM209.2,238.56c6.27,0,10.73-2.69,13.39-8.08,2.65-5.39,3.98-12.67,3.98-21.83s-1.33-16.45-3.98-21.84c-2.65-5.39-7.12-8.08-13.39-8.08s-10.74,2.7-13.39,8.08c-2.65,5.39-3.98,12.67-3.98,21.84s1.33,16.45,3.98,21.83c2.65,5.39,7.12,8.08,13.39,8.08Z"/>
<path class="cls-3" d="M340.7,271.86c-10.3,0-19.99-2.5-29.08-7.48-9.09-4.98-16.49-12.19-22.2-21.6-5.71-9.41-8.56-20.79-8.56-34.14s2.85-24.73,8.56-34.14c5.71-9.41,13.11-16.61,22.2-21.6,9.09-4.98,18.78-7.48,29.08-7.48s19.99,2.5,29.07,7.48c9.09,4.99,16.49,12.19,22.2,21.6,5.71,9.41,8.57,20.79,8.57,34.14s-2.86,24.73-8.57,34.14c-5.71,9.41-13.11,16.61-22.2,21.6-9.09,4.98-18.78,7.48-29.07,7.48ZM340.7,238.56c6.27,0,10.73-2.69,13.39-8.08,2.65-5.39,3.98-12.67,3.98-21.83s-1.33-16.45-3.98-21.84c-2.65-5.39-7.12-8.08-13.39-8.08s-10.74,2.7-13.39,8.08c-2.65,5.39-3.98,12.67-3.98,21.84s1.33,16.45,3.98,21.83c2.65,5.39,7.12,8.08,13.39,8.08Z"/>
<path class="cls-3" d="M462.55,271.86c-14.96,0-26.91-5.67-35.83-17.01-8.92-11.34-13.39-26.74-13.39-46.2,0-13.19,2.37-24.49,7.12-33.9,4.74-9.41,10.9-16.65,18.46-21.71,7.56-5.07,15.44-7.6,23.65-7.6,6.59,0,12.02,1.09,16.29,3.26,4.26,2.17,8.16,5.11,11.7,8.81l-1.45-17.37v-39.09h41.5v167.93h-33.78l-2.9-11.1h-.96c-4.02,4.02-8.77,7.36-14.24,10.02-5.47,2.65-10.86,3.98-16.16,3.98ZM473.65,238.08c3.22,0,6.07-.61,8.56-1.81,2.49-1.21,4.78-3.5,6.88-6.87v-44.4c-2.41-2.25-5.07-3.78-7.96-4.58-2.89-.8-5.71-1.21-8.44-1.21-4.34,0-8.24,2.17-11.7,6.51-3.46,4.35-5.19,11.83-5.19,22.44s1.61,18.46,4.83,23.04c3.22,4.58,7.56,6.88,13.03,6.88Z"/>
<path class="cls-2" d="M584.19,32.22c-14.21,12.99-18.69,16.8-27.15,28.46.21,65.05,23.73,121.48,60.5,167.9-4.91,9.5-39.25,73.17-45.59,45.05-.7-5.94-3.63-21.69.55-42.73,3.85-19.37,7.26-25.27,5.59-26-1.8-.79-7.28,14.73-9.16,34.18-2.28,23.59-4.26,32.83-5.32,39.44-6.27,43.92-24.53,68.97-29.23,82.98-.37,1.11.33,1.51.8,1.61,1.09.23,2.36-.33,3.46-1.82,15.5-21.08,57.6-80.44,89.72-125.2,28.35,22.13,57.88,36.09,87.12,47.47,25.61,10.21,53.58,17.27,72.3,14.88,1.07-.14,1.98-2.67,1.24-2.92-79.16-26.76-140.62-88.41-140.62-88.24,51.5-72.07,94.01-128.26,110.82-139.89,14.2-11.59,27.97-22.19,30.12-30.91,4.8-15.45,5.94-34.81,3.29-36.2-3.48-1.83-12.74,5.78-20.27,14.63-38.35,59.87-88.42,122.73-133.25,183.69-.01.02-12.4-9.58-28.38-45.1-11.5-25.54-19.84-69.6-23.65-119.86-.14-1.88-2.03-2.6-2.88-1.42"/>
</g>
<g>
<path class="cls-1" d="M98.55,353.46c-3.64,0-7.02-.7-10.13-2.1-3.11-1.4-5.81-3.26-8.07-5.58l3.96-4.59c1.84,1.95,4.02,3.52,6.53,4.71,2.5,1.19,5.11,1.78,7.8,1.78,3.43,0,6.09-.78,7.99-2.33,1.9-1.56,2.85-3.6,2.85-6.13,0-1.79-.38-3.22-1.15-4.27-.76-1.05-1.79-1.95-3.09-2.69-1.29-.74-2.76-1.48-4.39-2.21l-7.44-3.24c-1.64-.69-3.26-1.58-4.87-2.69-1.61-1.11-2.95-2.53-4.04-4.27-1.08-1.74-1.62-3.88-1.62-6.41s.7-5,2.1-7.08c1.4-2.08,3.33-3.72,5.82-4.91,2.48-1.19,5.28-1.78,8.39-1.78s5.99.59,8.63,1.78c2.64,1.19,4.88,2.73,6.73,4.63l-3.56,4.27c-1.58-1.53-3.33-2.73-5.26-3.6-1.92-.87-4.1-1.31-6.53-1.31-2.9,0-5.24.69-7,2.06s-2.65,3.22-2.65,5.54c0,1.64.44,2.99,1.31,4.08.87,1.08,1.97,1.97,3.28,2.65,1.32.69,2.66,1.32,4.03,1.9l7.36,3.17c2.01.85,3.81,1.86,5.42,3.05,1.61,1.19,2.89,2.64,3.84,4.35.95,1.71,1.43,3.87,1.43,6.45,0,2.74-.71,5.24-2.14,7.48-1.42,2.24-3.45,4.02-6.09,5.34-2.64,1.32-5.77,1.98-9.42,1.98Z"/>
<path class="cls-1" d="M157.43,353.46c-4.33,0-8.16-1.11-11.51-3.32-3.35-2.21-5.96-5.35-7.83-9.42-1.87-4.06-2.81-8.86-2.81-14.4s.94-10.3,2.81-14.28c1.87-3.98,4.48-7.04,7.83-9.18,3.35-2.14,7.19-3.21,11.51-3.21s8.23,1.07,11.55,3.21c3.32,2.14,5.94,5.2,7.84,9.18,1.9,3.98,2.85,8.74,2.85,14.28s-.95,10.34-2.85,14.4c-1.9,4.06-4.51,7.2-7.84,9.42-3.32,2.22-7.17,3.32-11.55,3.32ZM157.43,347.68c3.11,0,5.82-.88,8.11-2.65,2.3-1.77,4.08-4.25,5.34-7.44,1.26-3.19,1.9-6.95,1.9-11.28,0-6.44-1.4-11.53-4.2-15.27-2.8-3.74-6.52-5.62-11.16-5.62s-8.36,1.87-11.16,5.62c-2.8,3.75-4.2,8.84-4.2,15.27,0,4.33.63,8.09,1.9,11.28,1.26,3.19,3.06,5.67,5.38,7.44,2.32,1.77,5.01,2.65,8.07,2.65Z"/>
<path class="cls-1" d="M202.69,352.51v-51.91h29.91v5.54h-23.34v17.57h19.79v5.54h-19.79v23.27h-6.57Z"/>
<path class="cls-1" d="M264.41,352.51v-46.37h-15.67v-5.54h37.98v5.54h-15.67v46.37h-6.65Z"/>
<path class="cls-1" d="M313.64,352.51l-11-51.91h6.8l5.46,28.25c.48,2.8.98,5.59,1.51,8.39.53,2.8,1.03,5.59,1.5,8.39h.32c.58-2.8,1.19-5.61,1.82-8.43.63-2.82,1.24-5.61,1.82-8.35l7.2-28.25h6.02l7.2,28.25c.63,2.74,1.26,5.53,1.9,8.35.63,2.82,1.27,5.63,1.9,8.43h.32c.48-2.8.95-5.61,1.43-8.43.47-2.82.98-5.61,1.5-8.35l5.46-28.25h6.33l-10.76,51.91h-7.91l-7.83-31.26c-.48-2-.91-3.97-1.31-5.9-.4-1.92-.8-3.89-1.23-5.9h-.32c-.37,2.01-.79,3.97-1.26,5.9-.48,1.93-.92,3.89-1.34,5.9l-7.68,31.26h-7.83Z"/>
<path class="cls-1" d="M375.12,352.51l17.57-51.91h7.44l17.57,51.91h-7.04l-4.91-15.83h-18.91l-4.98,15.83h-6.73ZM390.95,323.47l-2.45,7.91h15.59l-2.45-7.91c-.95-2.9-1.85-5.79-2.69-8.67-.85-2.88-1.69-5.82-2.54-8.82h-.32c-.79,3.01-1.61,5.95-2.45,8.82-.85,2.88-1.74,5.76-2.69,8.67Z"/>
<path class="cls-1" d="M436.93,352.51v-51.91h16.22c3.53,0,6.67.46,9.42,1.39,2.74.92,4.89,2.45,6.45,4.59,1.56,2.14,2.33,5,2.33,8.58,0,4.01-1.05,7.24-3.16,9.7-2.11,2.45-4.96,4.13-8.55,5.02l13.22,22.63h-7.44l-12.51-21.92h-9.42v21.92h-6.57ZM443.49,325.21h8.71c4.06,0,7.17-.83,9.34-2.49,2.16-1.66,3.25-4.18,3.25-7.56s-1.08-5.83-3.25-7.2c-2.16-1.37-5.28-2.06-9.34-2.06h-8.71v19.31Z"/>
<path class="cls-1" d="M493.82,352.51v-51.91h29.91v5.54h-23.34v16.3h19.71v5.62h-19.71v18.83h24.14v5.62h-30.7Z"/>
</g>
</g>
<g>
<path class="cls-3" d="M795.78,300.14v-8.62h-2.91v-1.03h7.06v1.03h-2.91v8.62h-1.24Z"/>
<path class="cls-3" d="M801.66,300.14v-9.66h1.47l1.85,5.15c.12.33.23.67.35,1.01.11.34.23.67.35,1.01h.06c.12-.33.23-.67.33-1.01.1-.34.21-.67.33-1.01l1.83-5.15h1.49v9.66h-1.15v-5.31c0-.43.02-.91.06-1.44.04-.52.07-1,.1-1.42h-.06l-.77,2.19-1.83,5h-.81l-1.83-5-.77-2.19h-.06c.03.42.06.9.1,1.42.03.53.05,1,.05,1.44v5.31h-1.1Z"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

View File

@@ -61,6 +61,11 @@
"type": "boolean",
"description": "Enable verbose output"
},
"silent": {
"type": "boolean",
"description": "Disables echoing",
"default": false
},
"color": {
"type": "boolean",
"description": "Enable colored output"