Compare commits

...

42 Commits

Author SHA1 Message Date
Andrey Nering
f8545d4c61 v3.4.2 2021-04-23 18:11:31 -03:00
Oleg Butuzov
9b42ef5d46 "file does not exist" improving for watchers
Adds additional (initial missing) context to the go generic
`os.ErrNotExist` error, in addition to other errors that (possibly)
can be returned by `zglob.Glob`

Closes #472
2021-04-23 18:03:49 -03:00
Andrey Nering
05ddfc0495 Merge pull request #476 from Pix4D/fix-os-kill
signals: do not try to catch uncatchable signals
2021-04-23 17:45:56 -03:00
Andrey Nering
53b2cebb66 Updated the version output to use Go module build information if avalable. Enabled GoReleaser module proxying for verifiable builds.
Co-authored-by: Jamie Edge <JamieEdge@users.noreply.github.com>
Co-authored-by: Carlos Alexandro Becker <caarlos0@gmail.com>
2021-04-23 17:35:15 -03:00
Marco Molteni
837fb71a24 signals: do not try to catch uncatchable signals
os.Kill is SIGKILL (kill -9), cannot be intercepted.
(see https://github.com/golang/go/issues/13080)
2021-04-20 14:57:23 +02:00
Marco Molteni
2e13cf5f74 gitignore more editors 2021-04-20 14:54:24 +02:00
Andrey Nering
0ae1681d9c CHANGELOG: Fix typos 2021-04-17 17:57:08 -03:00
Andrey Nering
ebb66ba8fb v3.4.1 2021-04-17 17:48:36 -03:00
Andrey Nering
e79354a039 Revert "Updated the version output to use Go module build information if available. Enabled GoReleaser module proxying for verifiable builds."
This reverts commit 2a3f049336.
2021-04-17 17:47:24 -03:00
Andrey Nering
a57beb1de4 Website: Remove GitHub logo
The website that hosted the SVG file is offline for a while.
2021-04-17 17:34:00 -03:00
Andrey Nering
1648c44ee2 Website: Use dark theme 2021-04-17 17:34:00 -03:00
Andrey Nering
efe47a149e Website: Remove "Examples" page 2021-04-17 17:33:52 -03:00
Andrey Nering
2d66a2f0f3 Improve YAML parse error reporting
Fixes #467
2021-04-17 17:12:39 -03:00
Andrey Nering
43a1f1314e Website: Add a "Community" page 2021-04-17 11:59:24 -03:00
Andrey Nering
4f4b282d7c Merge pull request #471 from go-task/dependabot/go_modules/github.com/stretchr/testify-1.7.0
Bump github.com/stretchr/testify from 1.5.1 to 1.7.0
2021-04-17 10:53:03 -03:00
dependabot[bot]
d3d4da18e5 Bump github.com/stretchr/testify from 1.5.1 to 1.7.0
Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.5.1 to 1.7.0.
- [Release notes](https://github.com/stretchr/testify/releases)
- [Commits](https://github.com/stretchr/testify/compare/v1.5.1...v1.7.0)

Signed-off-by: dependabot[bot] <support@github.com>
2021-04-17 13:51:37 +00:00
Andrey Nering
b8da583986 Merge pull request #470 from go-task/dependabot/go_modules/github.com/fatih/color-1.10.0
Bump github.com/fatih/color from 1.7.0 to 1.10.0
2021-04-17 10:51:01 -03:00
Andrey Nering
73f6b42715 Merge pull request #469 from go-task/dependabot/go_modules/github.com/radovskyb/watcher-1.0.7
Bump github.com/radovskyb/watcher from 1.0.5 to 1.0.7
2021-04-17 10:50:21 -03:00
dependabot[bot]
0e2a4efdaa Bump github.com/radovskyb/watcher from 1.0.5 to 1.0.7
Bumps [github.com/radovskyb/watcher](https://github.com/radovskyb/watcher) from 1.0.5 to 1.0.7.
- [Release notes](https://github.com/radovskyb/watcher/releases)
- [Commits](https://github.com/radovskyb/watcher/compare/1.0.5...v1.0.7)

Signed-off-by: dependabot[bot] <support@github.com>
2021-04-17 13:47:39 +00:00
dependabot[bot]
6798e16aaf Bump github.com/fatih/color from 1.7.0 to 1.10.0
Bumps [github.com/fatih/color](https://github.com/fatih/color) from 1.7.0 to 1.10.0.
- [Release notes](https://github.com/fatih/color/releases)
- [Commits](https://github.com/fatih/color/compare/v1.7.0...v1.10.0)

Signed-off-by: dependabot[bot] <support@github.com>
2021-04-17 13:47:38 +00:00
Andrey Nering
c9cc64ecfc Merge pull request #468 from go-task/dependabot/go_modules/github.com/mattn/go-zglob-0.0.3
Bump github.com/mattn/go-zglob from 0.0.1 to 0.0.3
2021-04-17 10:46:42 -03:00
dependabot[bot]
761f9045ac Bump github.com/mattn/go-zglob from 0.0.1 to 0.0.3
Bumps [github.com/mattn/go-zglob](https://github.com/mattn/go-zglob) from 0.0.1 to 0.0.3.
- [Release notes](https://github.com/mattn/go-zglob/releases)
- [Commits](https://github.com/mattn/go-zglob/compare/v0.0.1...v0.0.3)

Signed-off-by: dependabot[bot] <support@github.com>
2021-04-17 13:43:00 +00:00
Andrey Nering
dfae979287 Add .github/dependabot.yml 2021-04-17 10:42:18 -03:00
George Pollard
fe917affd2 Include task name in log output 2021-04-04 16:16:22 -03:00
Andrey Nering
d44207dd7f Merge pull request #463 from JamieEdge/update-install-docs
Update Go modules installation documentation for Go 1.16
2021-04-04 15:48:19 -03:00
Andrey Nering
ec8b1403bd Use early return and add CHANGELOG for #462 2021-04-04 15:40:34 -03:00
Jamie Edge
6f3d108c1e Updated the install script documentation. 2021-04-04 17:31:41 +01:00
Jamie Edge
c34ee9c1f9 Updated the Go modules installation documentation for Go 1.16. 2021-04-04 17:30:42 +01:00
Jamie Edge
2a3f049336 Updated the version output to use Go module build information if available. Enabled GoReleaser module proxying for verifiable builds. 2021-04-04 12:57:58 +01:00
Andrey Nering
0c91011e88 Merge pull request #460 from patrick-mota/patch-1
Fix typo default installation
2021-03-28 11:10:38 -03:00
Andrey Nering
8bcd8719aa Docs: Add GO111MODULE=on to go get command 2021-03-28 10:45:36 -03:00
Ganon
29a8af509b Fix typo default installation 2021-03-26 13:19:45 +01:00
Andrey Nering
d3cd9f17f9 Documentation: Update link 2021-03-20 13:30:38 -03:00
Andrey Nering
b9aea8c5ec v3.3.0 2021-03-20 13:21:00 -03:00
Andrey Nering
897619a961 Upgrade github.com/spf13/pflag to v1.0.5 2021-03-20 12:00:39 -03:00
Andrey Nering
e6c4706b73 Add support for delegating CLI arguments with "--" and a special CLI_ARGS variable
Closes #327
2021-03-20 11:58:45 -03:00
Andrey Nering
8994c50d34 Upgrade mvdan.cc/sh to v3.2.4 2021-03-20 10:38:13 -03:00
Andrey Nering
55b62e47eb Upgrade mvdan.cc/sh to v3.2.2 2021-03-07 15:32:22 -03:00
Ross Hammermeister
c6ecf70377 Adding a --concurrency (-C) flag 2021-03-07 09:49:57 -03:00
Andrey Nering
f0cd7d27fb Taskfile: Set CGO_ENABLED=0 globally
We want that also for running tests, and not only for building it.
2021-03-07 09:30:33 -03:00
Andrey Nering
f923bb499b CHANGELOG: Fix wrong year in release date 2021-02-16 17:53:28 -03:00
Andrey Nering
aa3a29fed2 CHANGELOG: Add missing release dates 2021-02-16 17:52:32 -03:00
27 changed files with 390 additions and 178 deletions

10
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,10 @@
version: 2
updates:
- package-ecosystem: gomod
directory: /
schedule:
interval: weekly
day: saturday
time: '08:00'
timezone: America/Sao_Paulo

3
.gitignore vendored
View File

@@ -19,8 +19,9 @@ dist/
.DS_Store .DS_Store
# intellij idea/goland # editors
.idea/ .idea/
.vscode/
# exuberant ctags # exuberant ctags
tags tags

View File

@@ -1,6 +1,6 @@
build: build:
binary: task binary: task
main: cmd/task/task.go main: cmd/task
goos: goos:
- windows - windows
- darwin - darwin
@@ -17,6 +17,11 @@ build:
goarch: 386 goarch: 386
env: env:
- CGO_ENABLED=0 - CGO_ENABLED=0
ldflags:
- -s -w # Don't set main.version.
gomod:
proxy: true
archives: archives:
- name_template: "{{.Binary}}_{{.Os}}_{{.Arch}}" - name_template: "{{.Binary}}_{{.Os}}_{{.Arch}}"

View File

@@ -1,6 +1,36 @@
# Changelog # Changelog
## v3.2.2 ## v3.4.2 - 2021-04-23
- On watch, report which file failed to read
([#472](https://github.com/go-task/task/pull/472)).
- Do not try to catch SIGKILL signal, which are not actually possible
([#476](https://github.com/go-task/task/pull/476)).
- Improve version reporting when building Task from source using Go Modules
([#462](https://github.com/go-task/task/pull/462), [#473](https://github.com/go-task/task/pull/473)).
## v3.4.1 - 2021-04-17
- Improve error reporting when parsing YAML: in some situations where you
would just see an generic error, you'll now see the actual error with
more detail: the YAML line the failed to parse, for example
([#467](https://github.com/go-task/task/issues/467)).
- A JSON Schema was published [here](https://json.schemastore.org/taskfile.json)
and is automatically being used by some editors like Visual Studio Code
([#135](https://github.com/go-task/task/issues/135)).
- Print task name before the command in the log output
([#398](https://github.com/go-task/task/pull/398)).
## v3.3.0 - 2021-03-20
- Add support for delegating CLI arguments to commands with `--` and a
special `CLI_ARGS` variable
([#327](https://github.com/go-task/task/issues/327)).
- Add a `--concurrency` (alias `-C`) flag, to limit the number of tasks that
run concurrently. This is useful for heavy workloads.
([#345](https://github.com/go-task/task/pull/345)).
## v3.2.2 - 2021-01-12
- Improve performance of `--list` and `--summary` by skipping running shell - Improve performance of `--list` and `--summary` by skipping running shell
variables for these flags variables for these flags
@@ -13,14 +43,14 @@
- The install script is now working for ARM platforms - The install script is now working for ARM platforms
([#428](https://github.com/go-task/task/pull/428)). ([#428](https://github.com/go-task/task/pull/428)).
## v3.2.1 ## v3.2.1 - 2021-01-09
- Fixed some bugs and regressions regarding dynamic variables and directories - Fixed some bugs and regressions regarding dynamic variables and directories
([#426](https://github.com/go-task/task/issues/426)). ([#426](https://github.com/go-task/task/issues/426)).
- The [slim-sprig](https://github.com/go-task/slim-sprig) package was updated - The [slim-sprig](https://github.com/go-task/slim-sprig) package was updated
with the upstream [sprig](https://github.com/Masterminds/sprig). with the upstream [sprig](https://github.com/Masterminds/sprig).
## v3.2.0 ## v3.2.0 - 2021-01-07
- Fix the `.task` directory being created in the task directory instead of the - Fix the `.task` directory being created in the task directory instead of the
Taskfile directory Taskfile directory
@@ -33,7 +63,7 @@
should be more stable now should be more stable now
([#423](https://github.com/go-task/task/pull/423), [#365](https://github.com/go-task/task/issues/365)). ([#423](https://github.com/go-task/task/pull/423), [#365](https://github.com/go-task/task/issues/365)).
## v3.1.0 ## v3.1.0 - 2021-01-03
- Fix a bug when the checksum up-to-date resolution is used by a task - Fix a bug when the checksum up-to-date resolution is used by a task
with a custom `label:` attribute with a custom `label:` attribute
@@ -49,7 +79,7 @@
sentence was in the last line sentence was in the last line
([#403](https://github.com/go-task/task/issues/403)). ([#403](https://github.com/go-task/task/issues/403)).
## v3.0.1 ## v3.0.1 - 2020-12-26
- Allow use as a library by moving the required packages out of the `internal` - Allow use as a library by moving the required packages out of the `internal`
directory directory
@@ -59,7 +89,7 @@
- Fix panic when you have empty tasks in your Taskfile - Fix panic when you have empty tasks in your Taskfile
([#338](https://github.com/go-task/task/issues/338), [#362](https://github.com/go-task/task/pull/362)). ([#338](https://github.com/go-task/task/issues/338), [#362](https://github.com/go-task/task/pull/362)).
## v3.0.0 ## v3.0.0 - 2020-08-16
- On `v3`, all CLI variables will be considered global variables - On `v3`, all CLI variables will be considered global variables
([#336](https://github.com/go-task/task/issues/336), [#341](https://github.com/go-task/task/pull/341)) ([#336](https://github.com/go-task/task/issues/336), [#341](https://github.com/go-task/task/pull/341))
@@ -102,7 +132,7 @@
commands are green, errors are red, etc commands are green, errors are red, etc
([#207](https://github.com/go-task/task/pull/207)). ([#207](https://github.com/go-task/task/pull/207)).
## v2.8.1 - 2019-05-20 ## v2.8.1 - 2020-05-20
- Fix error code for the `--help` flag - Fix error code for the `--help` flag
([#300](https://github.com/go-task/task/issues/300), [#330](https://github.com/go-task/task/pull/330)). ([#300](https://github.com/go-task/task/issues/300), [#330](https://github.com/go-task/task/pull/330)).

View File

@@ -12,6 +12,9 @@ vars:
GO_PACKAGES: GO_PACKAGES:
sh: go list ./... sh: go list ./...
env:
CGO_ENABLED: '0'
tasks: tasks:
default: default:
cmds: cmds:
@@ -21,8 +24,6 @@ tasks:
desc: Installs Task desc: Installs Task
cmds: cmds:
- go install -v -ldflags="-w -s -X main.version={{.GIT_COMMIT}}" ./cmd/task - go install -v -ldflags="-w -s -X main.version={{.GIT_COMMIT}}" ./cmd/task
env:
CGO_ENABLED: '0'
mod: mod:
desc: Downloads and tidy Go modules desc: Downloads and tidy Go modules

View File

@@ -9,7 +9,7 @@ import (
// ParseV3 parses command line argument: tasks and global variables // ParseV3 parses command line argument: tasks and global variables
func ParseV3(args ...string) ([]taskfile.Call, *taskfile.Vars) { func ParseV3(args ...string) ([]taskfile.Call, *taskfile.Vars) {
var calls []taskfile.Call var calls []taskfile.Call
var globals *taskfile.Vars var globals = &taskfile.Vars{}
for _, arg := range args { for _, arg := range args {
if !strings.Contains(arg, "=") { if !strings.Contains(arg, "=") {
@@ -17,9 +17,6 @@ func ParseV3(args ...string) ([]taskfile.Call, *taskfile.Vars) {
continue continue
} }
if globals == nil {
globals = &taskfile.Vars{}
}
name, value := splitVar(arg) name, value := splitVar(arg)
globals.Set(name, taskfile.Var{Static: value}) globals.Set(name, taskfile.Var{Static: value})
} }
@@ -34,7 +31,7 @@ func ParseV3(args ...string) ([]taskfile.Call, *taskfile.Vars) {
// ParseV2 parses command line argument: tasks and vars of each task // ParseV2 parses command line argument: tasks and vars of each task
func ParseV2(args ...string) ([]taskfile.Call, *taskfile.Vars) { func ParseV2(args ...string) ([]taskfile.Call, *taskfile.Vars) {
var calls []taskfile.Call var calls []taskfile.Call
var globals *taskfile.Vars var globals = &taskfile.Vars{}
for _, arg := range args { for _, arg := range args {
if !strings.Contains(arg, "=") { if !strings.Contains(arg, "=") {
@@ -43,9 +40,6 @@ func ParseV2(args ...string) ([]taskfile.Call, *taskfile.Vars) {
} }
if len(calls) < 1 { if len(calls) < 1 {
if globals == nil {
globals = &taskfile.Vars{}
}
name, value := splitVar(arg) name, value := splitVar(arg)
globals.Set(name, taskfile.Var{Static: value}) globals.Set(name, taskfile.Var{Static: value})
} else { } else {

View File

@@ -96,7 +96,9 @@ func TestArgsV3(t *testing.T) {
t.Run(fmt.Sprintf("TestArgs%d", i+1), func(t *testing.T) { t.Run(fmt.Sprintf("TestArgs%d", i+1), func(t *testing.T) {
calls, globals := args.ParseV3(test.Args...) calls, globals := args.ParseV3(test.Args...)
assert.Equal(t, test.ExpectedCalls, calls) assert.Equal(t, test.ExpectedCalls, calls)
assert.Equal(t, test.ExpectedGlobals, globals) if test.ExpectedGlobals.Len() > 0 || globals.Len() > 0 {
assert.Equal(t, test.ExpectedGlobals, globals)
}
}) })
} }
} }
@@ -198,7 +200,10 @@ func TestArgsV2(t *testing.T) {
t.Run(fmt.Sprintf("TestArgs%d", i+1), func(t *testing.T) { t.Run(fmt.Sprintf("TestArgs%d", i+1), func(t *testing.T) {
calls, globals := args.ParseV2(test.Args...) calls, globals := args.ParseV2(test.Args...)
assert.Equal(t, test.ExpectedCalls, calls) assert.Equal(t, test.ExpectedCalls, calls)
assert.Equal(t, test.ExpectedGlobals, globals) if test.ExpectedGlobals.Len() > 0 || globals.Len() > 0 {
assert.Equal(t, test.ExpectedGlobals, globals)
}
}) })
} }
} }

View File

@@ -7,6 +7,8 @@ import (
"os" "os"
"os/signal" "os/signal"
"path/filepath" "path/filepath"
"runtime/debug"
"strings"
"syscall" "syscall"
"github.com/spf13/pflag" "github.com/spf13/pflag"
@@ -18,7 +20,7 @@ import (
) )
var ( var (
version = "master" version = ""
) )
const usage = `Usage: task [-ilfwvsd] [--init] [--list] [--force] [--watch] [--verbose] [--silent] [--dir] [--taskfile] [--dry] [--summary] [task...] const usage = `Usage: task [-ilfwvsd] [--init] [--list] [--force] [--watch] [--verbose] [--silent] [--dir] [--taskfile] [--dry] [--summary] [task...]
@@ -65,6 +67,7 @@ func main() {
dry bool dry bool
summary bool summary bool
parallel bool parallel bool
concurrency int
dir string dir string
entrypoint string entrypoint string
output string output string
@@ -87,10 +90,11 @@ func main() {
pflag.StringVarP(&entrypoint, "taskfile", "t", "", `choose which Taskfile to run. Defaults to "Taskfile.yml"`) pflag.StringVarP(&entrypoint, "taskfile", "t", "", `choose which Taskfile to run. Defaults to "Taskfile.yml"`)
pflag.StringVarP(&output, "output", "o", "", "sets output style: [interleaved|group|prefixed]") pflag.StringVarP(&output, "output", "o", "", "sets output style: [interleaved|group|prefixed]")
pflag.BoolVarP(&color, "color", "c", true, "colored output") pflag.BoolVarP(&color, "color", "c", true, "colored output")
pflag.IntVarP(&concurrency, "concurrency", "C", 0, "limit number tasks to run concurrently")
pflag.Parse() pflag.Parse()
if versionFlag { if versionFlag {
fmt.Printf("Task version: %s\n", version) fmt.Printf("Task version: %s\n", getVersion())
return return
} }
@@ -122,16 +126,17 @@ func main() {
} }
e := task.Executor{ e := task.Executor{
Force: force, Force: force,
Watch: watch, Watch: watch,
Verbose: verbose, Verbose: verbose,
Silent: silent, Silent: silent,
Dir: dir, Dir: dir,
Dry: dry, Dry: dry,
Entrypoint: entrypoint, Entrypoint: entrypoint,
Summary: summary, Summary: summary,
Parallel: parallel, Parallel: parallel,
Color: color, Color: color,
Concurrency: concurrency,
Stdin: os.Stdin, Stdin: os.Stdin,
Stdout: os.Stdout, Stdout: os.Stdout,
@@ -154,14 +159,18 @@ func main() {
} }
var ( var (
calls []taskfile.Call calls []taskfile.Call
globals *taskfile.Vars globals *taskfile.Vars
tasksAndVars, cliArgs = getArgs()
) )
if v >= 3.0 { if v >= 3.0 {
calls, globals = args.ParseV3(pflag.Args()...) calls, globals = args.ParseV3(tasksAndVars...)
} else { } else {
calls, globals = args.ParseV2(pflag.Args()...) calls, globals = args.ParseV2(tasksAndVars...)
} }
globals.Set("CLI_ARGS", taskfile.Var{Static: strings.Join(cliArgs, " ")})
e.Taskfile.Vars.Merge(globals) e.Taskfile.Vars.Merge(globals)
ctx := context.Background() ctx := context.Background()
@@ -182,9 +191,25 @@ func main() {
} }
} }
func getArgs() (tasksAndVars, cliArgs []string) {
var (
args = pflag.Args()
doubleDashPos = pflag.CommandLine.ArgsLenAtDash()
)
if doubleDashPos != -1 {
tasksAndVars = args[:doubleDashPos]
cliArgs = args[doubleDashPos:]
} else {
tasksAndVars = args
}
return
}
func getSignalContext() context.Context { func getSignalContext() context.Context {
ch := make(chan os.Signal, 1) ch := make(chan os.Signal, 1)
signal.Notify(ch, os.Interrupt, os.Kill, syscall.SIGTERM) signal.Notify(ch, os.Interrupt, syscall.SIGTERM)
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
go func() { go func() {
sig := <-ch sig := <-ch
@@ -193,3 +218,21 @@ func getSignalContext() context.Context {
}() }()
return ctx return ctx
} }
func getVersion() string {
if version != "" {
return version
}
info, ok := debug.ReadBuildInfo()
if !ok || info.Main.Version == "" {
return "unknown"
}
version = info.Main.Version
if info.Main.Sum != "" {
version += fmt.Sprintf(" (%s)", info.Main.Sum)
}
return version
}

25
concurrency.go Normal file
View File

@@ -0,0 +1,25 @@
package task
func (e *Executor) acquireConcurrencyLimit() func() {
if e.concurrencySemaphore == nil {
return emptyFunc
}
e.concurrencySemaphore <- struct{}{}
return func() {
<-e.concurrencySemaphore
}
}
func (e *Executor) releaseConcurrencyLimit() func() {
if e.concurrencySemaphore == nil {
return emptyFunc
}
<-e.concurrencySemaphore
return func() {
e.concurrencySemaphore <- struct{}{}
}
}
func emptyFunc() {}

View File

@@ -2,7 +2,7 @@
- [Usage](usage.md) - [Usage](usage.md)
- [Styleguide](styleguide.md) - [Styleguide](styleguide.md)
- [Taskfile Versions](taskfile_versions.md) - [Taskfile Versions](taskfile_versions.md)
- [Examples](examples.md) - [Community](community.md)
- [Releasing Task](releasing_task.md) - [Releasing Task](releasing_task.md)
- [Donate](donate.md) - [Donate](donate.md)
- [![GitHub](https://icongram.jgog.in/simple/github.svg?color=808080&size=16)GitHub](https://github.com/go-task/task) - [GitHub](https://github.com/go-task/task)

44
docs/community.md Normal file
View File

@@ -0,0 +1,44 @@
# Community
Some of the work to improve the Task ecosystem is done by the community, be
it installation methods or integrations with code editor. I (the author) am
thankful for everyone that helps me to improve the overall experience.
## Editor Integrations
### JSON Schema
[@KROSF](https://github.com/KROSF) worked on a JSON Schema [into this Gist](https://gist.github.com/KROSF/c5435acf590acd632f71bb720f685895),
which later was made officially available by [@Crandel](https://github.com/Crandel)
at [https://json.schemastore.org/taskfile.json](https://json.schemastore.org/taskfile.json).
Further improvements are possible by opening pull requests changing
[this file](https://github.com/SchemaStore/schemastore/blob/master/src/schemas/json/taskfile.json).
Some code editors, like Visual Studio Code, make use of Schema Store
automatically.
### Visual Studio Code extension
Additionally, there's also some work done by
[@paulvarache](https://github.com/paulvarache) in making an Visual Studio Code
extension, which has its code [here](https://github.com/paulvarache/vscode-taskfile)
and is published [here](https://marketplace.visualstudio.com/items?itemName=paulvarache.vscode-taskfile).
## Installation methods
Some installation methods are maintained by third party:
- [GitHub Actions](https://github.com/arduino/actions/tree/master/setup-taskfile)
by [@arduino](https://github.com/arduino)
- [AUR](https://aur.archlinux.org/packages/taskfile-git)
by [@kovetskiy](https://github.com/kovetskiy)
- [Scoop](https://github.com/lukesampson/scoop-extras/blob/master/bucket/task.json)
## More
Also, thanks for all the [code contributors](https://github.com/go-task/task/graphs/contributors),
[financial contributors](https://opencollective.com/task), all those who
[reported bugs](https://github.com/go-task/task/issues?q=is%3Aissue) and
[answered questions](https://github.com/go-task/task/discussions).
If you know something that is missing in this document, please submit a
pull request.

View File

@@ -1,7 +0,0 @@
# Examples
The [go-task/examples][examples] intends to be a collection of Taskfiles for
various use cases.
(It still lacks many examples, though. Contributions are welcome).
[examples]: https://github.com/go-task/examples

View File

@@ -6,7 +6,7 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" /> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="description" content="A task runner / simpler Make alternative written in Go"> <meta name="description" content="A task runner / simpler Make alternative written in Go">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/docsify-themeable/dist/css/theme-simple.css"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/docsify-themeable@0/dist/css/theme-simple-dark.css">
<meta name="google-site-verification" content="VGAYkbdmuaciIDGkBe-eAg9yfZg0C6ostgonbGxxOa0" /> <meta name="google-site-verification" content="VGAYkbdmuaciIDGkBe-eAg9yfZg0C6ostgonbGxxOa0" />
<style> <style>
#logo { #logo {
@@ -20,6 +20,10 @@
.app-name-link img { .app-name-link img {
width: 125px; width: 125px;
} }
:root {
--base-font-size: 14px;
--theme-color: #29beb0;
}
</style> </style>
</head> </head>
<body> <body>

View File

@@ -68,12 +68,12 @@ The `task_checksums.txt` file contains the SHA-256 checksum for each file.
#### **Install Script** #### **Install Script**
We also have a [install script][installscript], which is very useful on We also have an [install script][installscript] which is very useful in
scenarios like CIs. Many thanks to [GoDownloader][godownloader] for allowing scenarios like CI. Many thanks to [GoDownloader][godownloader] for enabling the
easily generating this script. easy generation of this script.
```bash ```bash
# For Default Installion to ./bin with debug logging # For Default Installation to ./bin with debug logging
sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d
# For Installation To /usr/local/bin for userwide access with debug logging # For Installation To /usr/local/bin for userwide access with debug logging
@@ -107,29 +107,27 @@ This installation method is community owned.
First, make sure you have [Go][go] properly installed and setup. First, make sure you have [Go][go] properly installed and setup.
You can easily install it globally by running: You can easily install the latest release globally by running:
```bash ```bash
go get -u github.com/go-task/task/v3/cmd/task go install github.com/go-task/task/v3/cmd/task@latest
``` ```
Or you can install into another directory: Or you can install into another directory:
```bash ```bash
git clone https://github.com/go-task/task env GOBIN=/bin go install github.com/go-task/task/v3/cmd/task@latest
cd task ```
# Compiling binary to $GOPATH/bin If using Go 1.15 or earlier, instead use:
go install -v ./cmd/task
# Compiling it to another location. ```bash
# Use -o ./task.exe on Windows. env GO111MODULE=on go get -u github.com/go-task/task/v3/cmd/task@latest
go build -v -o ./task ./cmd/task
``` ```
> For CI environments we recommend using the [Install Script](#get-the-binary) > For CI environments we recommend using the [Install Script](#get-the-binary)
> instead, which is faster and more stable, since it'll just download the latest > instead, which is faster and more stable, since it'll just download the latest
> released binary, instead of compiling the edge (master branch) version. > released binary.
<!-- tabs:end --> <!-- tabs:end -->

View File

@@ -36,4 +36,4 @@ If you think its Task version is outdated, open an issue to let us know.
[gotaskrb]: https://github.com/go-task/homebrew-tap/blob/master/Formula/go-task.rb [gotaskrb]: https://github.com/go-task/homebrew-tap/blob/master/Formula/go-task.rb
[snappackage]: https://github.com/go-task/snap [snappackage]: https://github.com/go-task/snap
[snapcraftyaml]: https://github.com/go-task/snap/blob/master/snap/snapcraft.yaml#L2 [snapcraftyaml]: https://github.com/go-task/snap/blob/master/snap/snapcraft.yaml#L2
[snapcraftdashboard]: https://dashboard.snapcraft.io/ [snapcraftdashboard]: https://snapcraft.io/task/releases

View File

@@ -520,6 +520,27 @@ tasks:
This works for all types of variables. This works for all types of variables.
## Forwarding CLI arguments to commands
If `--` is given in the CLI, all following paramaters are added to a
special `.CLI_ARGS` variable. This is useful to forward arguments to another
command.
The below example will run `yarn install`.
```bash
$ task yarn -- install
```
```yaml
version: '3'
tasks:
yarn:
cmds:
- yarn {{.CLI_ARGS}}
```
## Go's template engine ## Go's template engine
Task parse commands as [Go's template engine][gotemplate] before executing Task parse commands as [Go's template engine][gotemplate] before executing

13
go.mod
View File

@@ -1,17 +1,16 @@
module github.com/go-task/task/v3 module github.com/go-task/task/v3
require ( require (
github.com/fatih/color v1.7.0 github.com/fatih/color v1.10.0
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0
github.com/joho/godotenv v1.3.0 github.com/joho/godotenv v1.3.0
github.com/mattn/go-colorable v0.1.2 // indirect github.com/mattn/go-zglob v0.0.3
github.com/mattn/go-zglob v0.0.1 github.com/radovskyb/watcher v1.0.7
github.com/radovskyb/watcher v1.0.5 github.com/spf13/pflag v1.0.5
github.com/spf13/pflag v1.0.3 github.com/stretchr/testify v1.7.0
github.com/stretchr/testify v1.5.1
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c
mvdan.cc/sh/v3 v3.2.1 mvdan.cc/sh/v3 v3.2.4
) )
go 1.13 go 1.13

38
go.sum
View File

@@ -6,57 +6,55 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.10.0 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU= github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE= github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-zglob v0.0.1 h1:xsEx/XUoVlI6yXjqBK062zYhRTZltCNmYPx6v+8DNaY= github.com/mattn/go-zglob v0.0.3 h1:6Ry4EYsScDyt5di4OI6xw1bYhOqfE5S33Z1OPy+d+To=
github.com/mattn/go-zglob v0.0.1/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo= github.com/mattn/go-zglob v0.0.3/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo=
github.com/pkg/diff v0.0.0-20200914180035-5b29258ca4f7/go.mod h1:zO8QMzTeZd5cpnIkz/Gn6iK0jDfGicM1nynOkkPIl28= github.com/pkg/diff v0.0.0-20200914180035-5b29258ca4f7/go.mod h1:zO8QMzTeZd5cpnIkz/Gn6iK0jDfGicM1nynOkkPIl28=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/radovskyb/watcher v1.0.5 h1:wqt7gb+HjGacvFoLTKeT44C+XVPxu7bvHvKT1IvZ7rw= github.com/radovskyb/watcher v1.0.7 h1:AYePLih6dpmS32vlHfhCeli8127LzkIgwJGcwwe8tUE=
github.com/radovskyb/watcher v1.0.5/go.mod h1:78okwvY5wPdzcb1UYnip1pvrZNIVEIh/Cm+ZuvsUYIg= github.com/radovskyb/watcher v1.0.7/go.mod h1:78okwvY5wPdzcb1UYnip1pvrZNIVEIh/Cm+ZuvsUYIg=
github.com/rogpeppe/go-internal v1.6.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.6.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 h1:SQFwaSi55rU7vdNs9Yr0Z324VNlrF+0wMqRXT4St8ck= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 h1:SQFwaSi55rU7vdNs9Yr0Z324VNlrF+0wMqRXT4St8ck=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201029080932-201ba4db2418 h1:HlFl4V6pEMziuLXyRkm5BIYq1y1GAbb02pRlWvI54OM= golang.org/x/sys v0.0.0-20201029080932-201ba4db2418 h1:HlFl4V6pEMziuLXyRkm5BIYq1y1GAbb02pRlWvI54OM=
golang.org/x/sys v0.0.0-20201029080932-201ba4db2418/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201029080932-201ba4db2418/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20191110171634-ad39bd3f0407 h1:5zh5atpUEdIc478E/ebrIaHLKcfVvG6dL/fGv7BcMoM= golang.org/x/term v0.0.0-20191110171634-ad39bd3f0407 h1:5zh5atpUEdIc478E/ebrIaHLKcfVvG6dL/fGv7BcMoM=
golang.org/x/term v0.0.0-20191110171634-ad39bd3f0407/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20191110171634-ad39bd3f0407/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
mvdan.cc/editorconfig v0.1.1-0.20200121172147-e40951bde157/go.mod h1:Ge4atmRUYqueGppvJ7JNrtqpqokoJEFxYbP0Z+WeKS8= mvdan.cc/editorconfig v0.1.1-0.20200121172147-e40951bde157/go.mod h1:Ge4atmRUYqueGppvJ7JNrtqpqokoJEFxYbP0Z+WeKS8=
mvdan.cc/sh/v3 v3.2.1 h1:uQBpiGM+rEuHse3Q+W7ajuJUeOtFVJUN/6GeX4/dUWE= mvdan.cc/sh/v3 v3.2.4 h1:+fZaWcXWRjYAvqzEKoDhDM3DkxdDUykU2iw0VMKFe9s=
mvdan.cc/sh/v3 v3.2.1/go.mod h1:fPQmabBpREM/XQ9YXSU5ZFZ/Sm+PmKP9/vkFHgYKJEI= mvdan.cc/sh/v3 v3.2.4/go.mod h1:fPQmabBpREM/XQ9YXSU5ZFZ/Sm+PmKP9/vkFHgYKJEI=

View File

@@ -63,7 +63,7 @@ func (r *Templater) ReplaceSlice(strs []string) []string {
} }
func (r *Templater) ReplaceVars(vars *taskfile.Vars) *taskfile.Vars { func (r *Templater) ReplaceVars(vars *taskfile.Vars) *taskfile.Vars {
if r.err != nil || vars == nil || len(vars.Keys) == 0 { if r.err != nil || vars.Len() == 0 {
return nil return nil
} }

43
task.go
View File

@@ -32,16 +32,17 @@ const (
type Executor struct { type Executor struct {
Taskfile *taskfile.Taskfile Taskfile *taskfile.Taskfile
Dir string Dir string
Entrypoint string Entrypoint string
Force bool Force bool
Watch bool Watch bool
Verbose bool Verbose bool
Silent bool Silent bool
Dry bool Dry bool
Summary bool Summary bool
Parallel bool Parallel bool
Color bool Color bool
Concurrency int
Stdin io.Reader Stdin io.Reader
Stdout io.Writer Stdout io.Writer
@@ -54,8 +55,9 @@ type Executor struct {
taskvars *taskfile.Vars taskvars *taskfile.Vars
taskCallCount map[string]*int32 concurrencySemaphore chan struct{}
mkdirMutexMap map[string]*sync.Mutex taskCallCount map[string]*int32
mkdirMutexMap map[string]*sync.Mutex
} }
// Run runs Task // Run runs Task
@@ -247,6 +249,10 @@ func (e *Executor) Setup() error {
e.taskCallCount[k] = new(int32) e.taskCallCount[k] = new(int32)
e.mkdirMutexMap[k] = &sync.Mutex{} e.mkdirMutexMap[k] = &sync.Mutex{}
} }
if e.Concurrency > 0 {
e.concurrencySemaphore = make(chan struct{}, e.Concurrency)
}
return nil return nil
} }
@@ -260,6 +266,9 @@ func (e *Executor) RunTask(ctx context.Context, call taskfile.Call) error {
return &MaximumTaskCallExceededError{task: call.Task} return &MaximumTaskCallExceededError{task: call.Task}
} }
release := e.acquireConcurrencyLimit()
defer release()
if err := e.runDeps(ctx, t); err != nil { if err := e.runDeps(ctx, t); err != nil {
return err return err
} }
@@ -324,6 +333,9 @@ func (e *Executor) mkdir(t *taskfile.Task) error {
func (e *Executor) runDeps(ctx context.Context, t *taskfile.Task) error { func (e *Executor) runDeps(ctx context.Context, t *taskfile.Task) error {
g, ctx := errgroup.WithContext(ctx) g, ctx := errgroup.WithContext(ctx)
reacquire := e.releaseConcurrencyLimit()
defer reacquire()
for _, d := range t.Deps { for _, d := range t.Deps {
d := d d := d
@@ -344,6 +356,9 @@ func (e *Executor) runCommand(ctx context.Context, t *taskfile.Task, call taskfi
switch { switch {
case cmd.Task != "": case cmd.Task != "":
reacquire := e.releaseConcurrencyLimit()
defer reacquire()
err := e.RunTask(ctx, taskfile.Call{Task: cmd.Task, Vars: cmd.Vars}) err := e.RunTask(ctx, taskfile.Call{Task: cmd.Task, Vars: cmd.Vars})
if err != nil { if err != nil {
return err return err
@@ -351,7 +366,7 @@ func (e *Executor) runCommand(ctx context.Context, t *taskfile.Task, call taskfi
return nil return nil
case cmd.Cmd != "": case cmd.Cmd != "":
if e.Verbose || (!cmd.Silent && !t.Silent && !e.Taskfile.Silent && !e.Silent) { if e.Verbose || (!cmd.Silent && !t.Silent && !e.Taskfile.Silent && !e.Silent) {
e.Logger.Errf(logger.Green, "task: %s", cmd.Cmd) e.Logger.Errf(logger.Green, "task: [%s] %s", t.Name(), cmd.Cmd)
} }
if e.Dry { if e.Dry {
@@ -382,7 +397,7 @@ func (e *Executor) runCommand(ctx context.Context, t *taskfile.Task, call taskfi
Stderr: stdErr, Stderr: stdErr,
}) })
if execext.IsExitError(err) && cmd.IgnoreError { if execext.IsExitError(err) && cmd.IgnoreError {
e.Logger.VerboseErrf(logger.Yellow, "task: command error ignored: %v", err) e.Logger.VerboseErrf(logger.Yellow, "task: [%s] command error ignored: %v", t.Name(), err)
return nil return nil
} }
return err return err

View File

@@ -171,6 +171,22 @@ func TestVarsInvalidTmpl(t *testing.T) {
assert.EqualError(t, e.Run(context.Background(), taskfile.Call{Task: target}), expectError, "e.Run(target)") assert.EqualError(t, e.Run(context.Background(), taskfile.Call{Task: target}), expectError, "e.Run(target)")
} }
func TestConcurrency(t *testing.T) {
const (
dir = "testdata/concurrency"
target = "default"
)
e := &task.Executor{
Dir: dir,
Stdout: ioutil.Discard,
Stderr: ioutil.Discard,
Concurrency: 1,
}
assert.NoError(t, e.Setup(), "e.Setup()")
assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: target}), "e.Run(target)")
}
func TestParams(t *testing.T) { func TestParams(t *testing.T) {
tt := fileContentTest{ tt := fileContentTest{
Dir: "testdata/params", Dir: "testdata/params",
@@ -610,7 +626,7 @@ func TestDry(t *testing.T) {
assert.NoError(t, e.Setup()) assert.NoError(t, e.Setup())
assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: "build"})) assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: "build"}))
assert.Equal(t, "task: touch file.txt", strings.TrimSpace(buff.String())) assert.Equal(t, "task: [build] touch file.txt", strings.TrimSpace(buff.String()))
if _, err := os.Stat(file); err == nil { if _, err := os.Stat(file); err == nil {
t.Errorf("File should not exist %s", file) t.Errorf("File should not exist %s", file)
} }

View File

@@ -1,7 +1,6 @@
package taskfile package taskfile
import ( import (
"errors"
"strings" "strings"
) )
@@ -20,13 +19,6 @@ type Dep struct {
Vars *Vars Vars *Vars
} }
var (
// ErrCantUnmarshalCmd is returned for invalid command YAML
ErrCantUnmarshalCmd = errors.New("task: can't unmarshal cmd value")
// ErrCantUnmarshalDep is returned for invalid dependency YAML
ErrCantUnmarshalDep = errors.New("task: can't unmarshal dep value")
)
// UnmarshalYAML implements yaml.Unmarshaler interface // UnmarshalYAML implements yaml.Unmarshaler interface
func (c *Cmd) UnmarshalYAML(unmarshal func(interface{}) error) error { func (c *Cmd) UnmarshalYAML(unmarshal func(interface{}) error) error {
var cmd string var cmd string
@@ -53,12 +45,12 @@ func (c *Cmd) UnmarshalYAML(unmarshal func(interface{}) error) error {
Task string Task string
Vars *Vars Vars *Vars
} }
if err := unmarshal(&taskCall); err == nil { if err := unmarshal(&taskCall); err != nil {
c.Task = taskCall.Task return err
c.Vars = taskCall.Vars
return nil
} }
return ErrCantUnmarshalCmd c.Task = taskCall.Task
c.Vars = taskCall.Vars
return nil
} }
// UnmarshalYAML implements yaml.Unmarshaler interface // UnmarshalYAML implements yaml.Unmarshaler interface
@@ -72,10 +64,10 @@ func (d *Dep) UnmarshalYAML(unmarshal func(interface{}) error) error {
Task string Task string
Vars *Vars Vars *Vars
} }
if err := unmarshal(&taskCall); err == nil { if err := unmarshal(&taskCall); err != nil {
d.Task = taskCall.Task return err
d.Vars = taskCall.Vars
return nil
} }
return ErrCantUnmarshalDep d.Task = taskCall.Task
d.Vars = taskCall.Vars
return nil
} }

View File

@@ -6,11 +6,6 @@ import (
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
) )
var (
// ErrCantUnmarshalIncludedTaskfile is returned for invalid var YAML.
ErrCantUnmarshalIncludedTaskfile = errors.New("task: can't unmarshal included value")
)
// IncludedTaskfile represents information about included tasksfile // IncludedTaskfile represents information about included tasksfile
type IncludedTaskfile struct { type IncludedTaskfile struct {
Taskfile string Taskfile string
@@ -98,12 +93,11 @@ func (it *IncludedTaskfile) UnmarshalYAML(unmarshal func(interface{}) error) err
Taskfile string Taskfile string
Dir string Dir string
} }
if err := unmarshal(&includedTaskfile); err == nil { if err := unmarshal(&includedTaskfile); err != nil {
it.Dir = includedTaskfile.Dir return err
it.Taskfile = includedTaskfile.Taskfile
it.AdvancedImport = true
return nil
} }
it.Dir = includedTaskfile.Dir
return ErrCantUnmarshalIncludedTaskfile it.Taskfile = includedTaskfile.Taskfile
it.AdvancedImport = true
return nil
} }

View File

@@ -1,9 +1,5 @@
package taskfile package taskfile
import (
"errors"
)
// Tasks represents a group of tasks // Tasks represents a group of tasks
type Tasks map[string]*Task type Tasks map[string]*Task
@@ -28,11 +24,6 @@ type Task struct {
IgnoreError bool IgnoreError bool
} }
var (
// ErrCantUnmarshalTask is returned for invalid task YAML
ErrCantUnmarshalTask = errors.New("task: can't unmarshal task value")
)
func (t *Task) Name() string { func (t *Task) Name() string {
if t.Label != "" { if t.Label != "" {
return t.Label return t.Label
@@ -71,26 +62,24 @@ func (t *Task) UnmarshalYAML(unmarshal func(interface{}) error) error {
Prefix string Prefix string
IgnoreError bool `yaml:"ignore_error"` IgnoreError bool `yaml:"ignore_error"`
} }
if err := unmarshal(&task); err == nil { if err := unmarshal(&task); err != nil {
t.Cmds = task.Cmds return err
t.Deps = task.Deps
t.Label = task.Label
t.Desc = task.Desc
t.Summary = task.Summary
t.Sources = task.Sources
t.Generates = task.Generates
t.Status = task.Status
t.Preconditions = task.Preconditions
t.Dir = task.Dir
t.Vars = task.Vars
t.Env = task.Env
t.Silent = task.Silent
t.Method = task.Method
t.Prefix = task.Prefix
t.IgnoreError = task.IgnoreError
return nil
} }
t.Cmds = task.Cmds
return ErrCantUnmarshalTask t.Deps = task.Deps
t.Label = task.Label
t.Desc = task.Desc
t.Summary = task.Summary
t.Sources = task.Sources
t.Generates = task.Generates
t.Status = task.Status
t.Preconditions = task.Preconditions
t.Dir = task.Dir
t.Vars = task.Vars
t.Env = task.Env
t.Silent = task.Silent
t.Method = task.Method
t.Prefix = task.Prefix
t.IgnoreError = task.IgnoreError
return nil
} }

View File

@@ -7,11 +7,6 @@ import (
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
) )
var (
// ErrCantUnmarshalVar is returned for invalid var YAML.
ErrCantUnmarshalVar = errors.New("task: can't unmarshal var value")
)
// Vars is a string[string] variables map. // Vars is a string[string] variables map.
type Vars struct { type Vars struct {
Keys []string Keys []string
@@ -75,7 +70,7 @@ func (vs *Vars) Range(yield func(key string, value Var) error) error {
// ToCacheMap converts Vars to a map containing only the static // ToCacheMap converts Vars to a map containing only the static
// variables // variables
func (vs *Vars) ToCacheMap() (m map[string]interface{}) { func (vs *Vars) ToCacheMap() (m map[string]interface{}) {
m = make(map[string]interface{}, len(vs.Keys)) m = make(map[string]interface{}, vs.Len())
vs.Range(func(k string, v Var) error { vs.Range(func(k string, v Var) error {
if v.Sh != "" { if v.Sh != "" {
// Dynamic variable is not yet resolved; trigger // Dynamic variable is not yet resolved; trigger
@@ -93,6 +88,14 @@ func (vs *Vars) ToCacheMap() (m map[string]interface{}) {
return return
} }
// Len returns the size of the map
func (vs *Vars) Len() int {
if vs == nil {
return 0
}
return len(vs.Keys)
}
// Var represents either a static or dynamic variable. // Var represents either a static or dynamic variable.
type Var struct { type Var struct {
Static string Static string
@@ -116,10 +119,9 @@ func (v *Var) UnmarshalYAML(unmarshal func(interface{}) error) error {
var sh struct { var sh struct {
Sh string Sh string
} }
if err := unmarshal(&sh); err == nil { if err := unmarshal(&sh); err != nil {
v.Sh = sh.Sh return err
return nil
} }
v.Sh = sh.Sh
return ErrCantUnmarshalVar return nil
} }

32
testdata/concurrency/Taskfile.yml vendored Normal file
View File

@@ -0,0 +1,32 @@
version: '2'
tasks:
default:
deps:
- t1
t1:
deps:
- t3
- t4
cmds:
- task: t2
- echo done 1
t2:
deps:
- t5
- t6
cmds:
- echo done 2
t3:
cmds:
- echo done 3
t4:
cmds:
- echo done 4
t5:
cmds:
- echo done 5
t6:
cmds:
- echo done 6

View File

@@ -2,6 +2,7 @@ package task
import ( import (
"context" "context"
"fmt"
"os" "os"
"os/signal" "os/signal"
"path/filepath" "path/filepath"
@@ -129,7 +130,7 @@ func (e *Executor) registerWatchedFiles(w *watcher.Watcher, calls ...taskfile.Ca
for _, s := range task.Sources { for _, s := range task.Sources {
files, err := zglob.Glob(s) files, err := zglob.Glob(s)
if err != nil { if err != nil {
return err return fmt.Errorf("task: %s: %w", s, err)
} }
for _, f := range files { for _, f := range files {
absFile, err := filepath.Abs(f) absFile, err := filepath.Abs(f)