mirror of
https://github.com/go-task/task.git
synced 2024-12-12 10:45:49 +02:00
fix(#584): Add support to yaml extension
- init creates Taskfile.yaml - add changelog entry - add zsh completion support for Taskfile.yaml
This commit is contained in:
parent
17e18442ab
commit
1d7982e80a
1
.github/ISSUE_TEMPLATE/bug_report.md
vendored
1
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@ -1,7 +1,6 @@
|
|||||||
---
|
---
|
||||||
name: Bug Report
|
name: Bug Report
|
||||||
about: Use the template to report bugs and issues
|
about: Use the template to report bugs and issues
|
||||||
labels: bug
|
|
||||||
---
|
---
|
||||||
|
|
||||||
- Task version:
|
- Task version:
|
||||||
|
1
.github/ISSUE_TEMPLATE/feature_request.md
vendored
1
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@ -1,7 +1,6 @@
|
|||||||
---
|
---
|
||||||
name: Feature Request
|
name: Feature Request
|
||||||
about: Use the template to make feature requests
|
about: Use the template to make feature requests
|
||||||
labels: feature
|
|
||||||
---
|
---
|
||||||
|
|
||||||
Describe in detail what feature do you want to see in Task.
|
Describe in detail what feature do you want to see in Task.
|
||||||
|
4
.github/workflows/release.yml
vendored
4
.github/workflows/release.yml
vendored
@ -10,10 +10,10 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v1
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
- name: Set up Go
|
- name: Set up Go
|
||||||
uses: actions/setup-go@v1
|
uses: actions/setup-go@v2
|
||||||
with:
|
with:
|
||||||
go-version: 1.17.x
|
go-version: 1.17.x
|
||||||
|
|
||||||
|
4
.github/workflows/test.yml
vendored
4
.github/workflows/test.yml
vendored
@ -10,13 +10,13 @@ jobs:
|
|||||||
runs-on: ${{matrix.platform}}
|
runs-on: ${{matrix.platform}}
|
||||||
steps:
|
steps:
|
||||||
- name: Set up Go ${{matrix.go-version}}
|
- name: Set up Go ${{matrix.go-version}}
|
||||||
uses: actions/setup-go@v1
|
uses: actions/setup-go@v2
|
||||||
with:
|
with:
|
||||||
go-version: ${{matrix.go-version}}
|
go-version: ${{matrix.go-version}}
|
||||||
id: go
|
id: go
|
||||||
|
|
||||||
- name: Check out code into the Go module directory
|
- name: Check out code into the Go module directory
|
||||||
uses: actions/checkout@v1
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
- name: Download Go modules
|
- name: Download Go modules
|
||||||
run: go mod download
|
run: go mod download
|
||||||
|
25
CHANGELOG.md
25
CHANGELOG.md
@ -2,6 +2,31 @@
|
|||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
|
- Add support for yaml extension ([#584](https://github.com/go-task/task/issues/584))
|
||||||
|
|
||||||
|
## v3.9.2 - 2021-12-02
|
||||||
|
|
||||||
|
- Upgrade [mvdan/sh](https://github.com/mvdan/sh) which contains a fix a for
|
||||||
|
a important regression on Windows
|
||||||
|
([#619](https://github.com/go-task/task/issues/619), [mvdan/sh#768](https://github.com/mvdan/sh/issues/768), [mvdan/sh#769](https://github.com/mvdan/sh/pull/769)).
|
||||||
|
|
||||||
|
## v3.9.1 - 2021-11-28
|
||||||
|
|
||||||
|
- Add logging in verbose mode for when a task starts and finishes
|
||||||
|
([#533](https://github.com/go-task/task/issues/533), [#588](https://github.com/go-task/task/pull/588)).
|
||||||
|
- Fix an issue with preconditions and context errors
|
||||||
|
([#597](https://github.com/go-task/task/issues/597), [#598](https://github.com/go-task/task/pull/598)).
|
||||||
|
- Quote each `{{.CLI_ARGS}}` argument to prevent one with spaces to become many
|
||||||
|
([#613](https://github.com/go-task/task/pull/613)).
|
||||||
|
- Fix nil pointer when `cmd:` was left empty
|
||||||
|
([#612](https://github.com/go-task/task/issues/612), [#614](https://github.com/go-task/task/pull/614)).
|
||||||
|
- Upgrade [mvdan/sh](https://github.com/mvdan/sh) which contains two
|
||||||
|
relevant fixes:
|
||||||
|
- Fix quote of empty strings in `shellQuote`
|
||||||
|
([#609](https://github.com/go-task/task/issues/609), [mvdan/sh#763](https://github.com/mvdan/sh/issues/763)).
|
||||||
|
- Fix issue of wrong environment variable being picked when there's another
|
||||||
|
very similar one
|
||||||
|
([#586](https://github.com/go-task/task/issues/586), [mvdan/sh#745](https://github.com/mvdan/sh/pull/745)).
|
||||||
- Install shell completions automatically when installing via Homebrew
|
- Install shell completions automatically when installing via Homebrew
|
||||||
([#264](https://github.com/go-task/task/issues/264), [#592](https://github.com/go-task/task/pull/592), [go-task/homebrew-tap#2](https://github.com/go-task/homebrew-tap/pull/2)).
|
([#264](https://github.com/go-task/task/issues/264), [#592](https://github.com/go-task/task/pull/592), [go-task/homebrew-tap#2](https://github.com/go-task/homebrew-tap/pull/2)).
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
|
"mvdan.cc/sh/v3/syntax"
|
||||||
|
|
||||||
"github.com/go-task/task/v3"
|
"github.com/go-task/task/v3"
|
||||||
"github.com/go-task/task/v3/args"
|
"github.com/go-task/task/v3/args"
|
||||||
@ -76,7 +77,7 @@ func main() {
|
|||||||
|
|
||||||
pflag.BoolVar(&versionFlag, "version", false, "show Task version")
|
pflag.BoolVar(&versionFlag, "version", false, "show Task version")
|
||||||
pflag.BoolVarP(&helpFlag, "help", "h", false, "shows Task usage")
|
pflag.BoolVarP(&helpFlag, "help", "h", false, "shows Task usage")
|
||||||
pflag.BoolVarP(&init, "init", "i", false, "creates a new Taskfile.yml in the current folder")
|
pflag.BoolVarP(&init, "init", "i", false, "creates a new Taskfile.yaml in the current folder")
|
||||||
pflag.BoolVarP(&list, "list", "l", false, "lists tasks with description of current Taskfile")
|
pflag.BoolVarP(&list, "list", "l", false, "lists tasks with description of current Taskfile")
|
||||||
pflag.BoolVar(&status, "status", false, "exits with non-zero exit code if any of the given tasks is not up-to-date")
|
pflag.BoolVar(&status, "status", false, "exits with non-zero exit code if any of the given tasks is not up-to-date")
|
||||||
pflag.BoolVarP(&force, "force", "f", false, "forces execution even when the task is up-to-date")
|
pflag.BoolVarP(&force, "force", "f", false, "forces execution even when the task is up-to-date")
|
||||||
@ -121,8 +122,6 @@ func main() {
|
|||||||
if entrypoint != "" {
|
if entrypoint != "" {
|
||||||
dir = filepath.Dir(entrypoint)
|
dir = filepath.Dir(entrypoint)
|
||||||
entrypoint = filepath.Base(entrypoint)
|
entrypoint = filepath.Base(entrypoint)
|
||||||
} else {
|
|
||||||
entrypoint = "Taskfile.yml"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
e := task.Executor{
|
e := task.Executor{
|
||||||
@ -159,18 +158,22 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
calls []taskfile.Call
|
calls []taskfile.Call
|
||||||
globals *taskfile.Vars
|
globals *taskfile.Vars
|
||||||
tasksAndVars, cliArgs = getArgs()
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
tasksAndVars, cliArgs, err := getArgs()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
if v >= 3.0 {
|
if v >= 3.0 {
|
||||||
calls, globals = args.ParseV3(tasksAndVars...)
|
calls, globals = args.ParseV3(tasksAndVars...)
|
||||||
} else {
|
} else {
|
||||||
calls, globals = args.ParseV2(tasksAndVars...)
|
calls, globals = args.ParseV2(tasksAndVars...)
|
||||||
}
|
}
|
||||||
|
|
||||||
globals.Set("CLI_ARGS", taskfile.Var{Static: strings.Join(cliArgs, " ")})
|
globals.Set("CLI_ARGS", taskfile.Var{Static: cliArgs})
|
||||||
e.Taskfile.Vars.Merge(globals)
|
e.Taskfile.Vars.Merge(globals)
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
@ -191,20 +194,25 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getArgs() (tasksAndVars, cliArgs []string) {
|
func getArgs() ([]string, string, error) {
|
||||||
var (
|
var (
|
||||||
args = pflag.Args()
|
args = pflag.Args()
|
||||||
doubleDashPos = pflag.CommandLine.ArgsLenAtDash()
|
doubleDashPos = pflag.CommandLine.ArgsLenAtDash()
|
||||||
)
|
)
|
||||||
|
|
||||||
if doubleDashPos != -1 {
|
if doubleDashPos == -1 {
|
||||||
tasksAndVars = args[:doubleDashPos]
|
return args, "", nil
|
||||||
cliArgs = args[doubleDashPos:]
|
|
||||||
} else {
|
|
||||||
tasksAndVars = args
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
var quotedCliArgs []string
|
||||||
|
for _, arg := range args[doubleDashPos:] {
|
||||||
|
quotedCliArg, err := syntax.Quote(arg, syntax.LangBash)
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", err
|
||||||
|
}
|
||||||
|
quotedCliArgs = append(quotedCliArgs, quotedCliArg)
|
||||||
|
}
|
||||||
|
return args[:doubleDashPos], strings.Join(quotedCliArgs, " "), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getSignalContext() context.Context {
|
func getSignalContext() context.Context {
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
function __list() {
|
function __list() {
|
||||||
local -a scripts
|
local -a scripts
|
||||||
|
|
||||||
if [ -f Taskfile.yml ]; then
|
if [ -f Taskfile.yml ] || [ -f Taskfile.yaml ]; then
|
||||||
scripts=($(task -l | sed '1d' | sed 's/^\* //' | awk '{ print $1 }' | sed 's/:$//' | sed 's/:/\\:/g'))
|
scripts=($(task -l | sed '1d' | sed 's/^\* //' | awk '{ print $1 }' | sed 's/:$//' | sed 's/:/\\:/g'))
|
||||||
_describe 'script' scripts
|
_describe 'script' scripts
|
||||||
fi
|
fi
|
||||||
|
2
go.mod
2
go.mod
@ -11,7 +11,7 @@ require (
|
|||||||
github.com/stretchr/testify v1.7.0
|
github.com/stretchr/testify v1.7.0
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c
|
||||||
mvdan.cc/sh/v3 v3.4.0
|
mvdan.cc/sh/v3 v3.4.2-0.20211202103622-5ae9d64e1402
|
||||||
)
|
)
|
||||||
|
|
||||||
go 1.16
|
go 1.16
|
||||||
|
4
go.sum
4
go.sum
@ -68,5 +68,5 @@ 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.2.0/go.mod h1:lvnnD3BNdBYkhq+B4uBuFFKatfp02eB6HixDvEz91C0=
|
mvdan.cc/editorconfig v0.2.0/go.mod h1:lvnnD3BNdBYkhq+B4uBuFFKatfp02eB6HixDvEz91C0=
|
||||||
mvdan.cc/sh/v3 v3.4.0 h1:thPCJ0hffn/Y/vMGs3HVMPYStNTyr2+lQee8LQiPZSU=
|
mvdan.cc/sh/v3 v3.4.2-0.20211202103622-5ae9d64e1402 h1:IhYcaLRZjSJqGoLrn+sXXFq3Xhd40I0wBkoIyg6cSZs=
|
||||||
mvdan.cc/sh/v3 v3.4.0/go.mod h1:p/tqPPI4Epfk2rICAe2RoaNd8HBSJ8t9Y2DA9yQlbzY=
|
mvdan.cc/sh/v3 v3.4.2-0.20211202103622-5ae9d64e1402/go.mod h1:p/tqPPI4Epfk2rICAe2RoaNd8HBSJ8t9Y2DA9yQlbzY=
|
||||||
|
7
init.go
7
init.go
@ -3,7 +3,6 @@ package task
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
)
|
)
|
||||||
@ -24,15 +23,15 @@ tasks:
|
|||||||
|
|
||||||
// InitTaskfile Taskfile creates a new Taskfile
|
// InitTaskfile Taskfile creates a new Taskfile
|
||||||
func InitTaskfile(w io.Writer, dir string) error {
|
func InitTaskfile(w io.Writer, dir string) error {
|
||||||
f := filepath.Join(dir, "Taskfile.yml")
|
f := filepath.Join(dir, "Taskfile.yaml")
|
||||||
|
|
||||||
if _, err := os.Stat(f); err == nil {
|
if _, err := os.Stat(f); err == nil {
|
||||||
return ErrTaskfileAlreadyExists
|
return ErrTaskfileAlreadyExists
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := ioutil.WriteFile(f, []byte(defaultTaskfile), 0644); err != nil {
|
if err := os.WriteFile(f, []byte(defaultTaskfile), 0644); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
fmt.Fprintf(w, "Taskfile.yml created in the current directory\n")
|
fmt.Fprintf(w, "Taskfile.yaml created in the current directory\n")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@ import (
|
|||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
@ -30,7 +29,7 @@ func (c *Checksum) IsUpToDate() (bool, error) {
|
|||||||
|
|
||||||
checksumFile := c.checksumFilePath()
|
checksumFile := c.checksumFilePath()
|
||||||
|
|
||||||
data, _ := ioutil.ReadFile(checksumFile)
|
data, _ := os.ReadFile(checksumFile)
|
||||||
oldMd5 := strings.TrimSpace(string(data))
|
oldMd5 := strings.TrimSpace(string(data))
|
||||||
|
|
||||||
sources, err := globs(c.TaskDir, c.Sources)
|
sources, err := globs(c.TaskDir, c.Sources)
|
||||||
@ -45,7 +44,7 @@ func (c *Checksum) IsUpToDate() (bool, error) {
|
|||||||
|
|
||||||
if !c.Dry {
|
if !c.Dry {
|
||||||
_ = os.MkdirAll(filepath.Join(c.BaseDir, ".task", "checksum"), 0755)
|
_ = os.MkdirAll(filepath.Join(c.BaseDir, ".task", "checksum"), 0755)
|
||||||
if err = ioutil.WriteFile(checksumFile, []byte(newMd5+"\n"), 0644); err != nil {
|
if err = os.WriteFile(checksumFile, []byte(newMd5+"\n"), 0644); err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
10
task.go
10
task.go
@ -105,10 +105,6 @@ func (e *Executor) Run(ctx context.Context, calls ...taskfile.Call) error {
|
|||||||
|
|
||||||
// Setup setups Executor's internal state
|
// Setup setups Executor's internal state
|
||||||
func (e *Executor) Setup() error {
|
func (e *Executor) Setup() error {
|
||||||
if e.Entrypoint == "" {
|
|
||||||
e.Entrypoint = "Taskfile.yml"
|
|
||||||
}
|
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
e.Taskfile, err = read.Taskfile(e.Dir, e.Entrypoint)
|
e.Taskfile, err = read.Taskfile(e.Dir, e.Entrypoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -310,11 +306,16 @@ func (e *Executor) RunTask(ctx context.Context, call taskfile.Call) error {
|
|||||||
defer release()
|
defer release()
|
||||||
|
|
||||||
return e.startExecution(ctx, t, func(ctx context.Context) error {
|
return e.startExecution(ctx, t, func(ctx context.Context) error {
|
||||||
|
e.Logger.VerboseErrf(logger.Magenta, `task: "%s" started`, call.Task)
|
||||||
if err := e.runDeps(ctx, t); err != nil {
|
if err := e.runDeps(ctx, t); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !e.Force {
|
if !e.Force {
|
||||||
|
if err := ctx.Err(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
preCondMet, err := e.areTaskPreconditionsMet(ctx, t)
|
preCondMet, err := e.areTaskPreconditionsMet(ctx, t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -351,6 +352,7 @@ func (e *Executor) RunTask(ctx context.Context, call taskfile.Call) error {
|
|||||||
return &taskRunError{t.Task, err}
|
return &taskRunError{t.Task, err}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
e.Logger.VerboseErrf(logger.Magenta, `task: "%s" finished`, call.Task)
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
107
task_test.go
107
task_test.go
@ -4,7 +4,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
@ -24,10 +24,11 @@ func init() {
|
|||||||
// fileContentTest provides a basic reusable test-case for running a Taskfile
|
// fileContentTest provides a basic reusable test-case for running a Taskfile
|
||||||
// and inspect generated files.
|
// and inspect generated files.
|
||||||
type fileContentTest struct {
|
type fileContentTest struct {
|
||||||
Dir string
|
Dir string
|
||||||
Target string
|
Entrypoint string
|
||||||
TrimSpace bool
|
Target string
|
||||||
Files map[string]string
|
TrimSpace bool
|
||||||
|
Files map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fct fileContentTest) name(file string) string {
|
func (fct fileContentTest) name(file string) string {
|
||||||
@ -40,16 +41,17 @@ func (fct fileContentTest) Run(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
e := &task.Executor{
|
e := &task.Executor{
|
||||||
Dir: fct.Dir,
|
Dir: fct.Dir,
|
||||||
Stdout: ioutil.Discard,
|
Entrypoint: fct.Entrypoint,
|
||||||
Stderr: ioutil.Discard,
|
Stdout: io.Discard,
|
||||||
|
Stderr: io.Discard,
|
||||||
}
|
}
|
||||||
assert.NoError(t, e.Setup(), "e.Setup()")
|
assert.NoError(t, e.Setup(), "e.Setup()")
|
||||||
assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: fct.Target}), "e.Run(target)")
|
assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: fct.Target}), "e.Run(target)")
|
||||||
|
|
||||||
for name, expectContent := range fct.Files {
|
for name, expectContent := range fct.Files {
|
||||||
t.Run(fct.name(name), func(t *testing.T) {
|
t.Run(fct.name(name), func(t *testing.T) {
|
||||||
b, err := ioutil.ReadFile(filepath.Join(fct.Dir, name))
|
b, err := os.ReadFile(filepath.Join(fct.Dir, name))
|
||||||
assert.NoError(t, err, "Error reading file")
|
assert.NoError(t, err, "Error reading file")
|
||||||
s := string(b)
|
s := string(b)
|
||||||
if fct.TrimSpace {
|
if fct.TrimSpace {
|
||||||
@ -63,8 +65,8 @@ func (fct fileContentTest) Run(t *testing.T) {
|
|||||||
func TestEmptyTask(t *testing.T) {
|
func TestEmptyTask(t *testing.T) {
|
||||||
e := &task.Executor{
|
e := &task.Executor{
|
||||||
Dir: "testdata/empty_task",
|
Dir: "testdata/empty_task",
|
||||||
Stdout: ioutil.Discard,
|
Stdout: io.Discard,
|
||||||
Stderr: ioutil.Discard,
|
Stderr: io.Discard,
|
||||||
}
|
}
|
||||||
assert.NoError(t, e.Setup(), "e.Setup()")
|
assert.NoError(t, e.Setup(), "e.Setup()")
|
||||||
assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: "default"}))
|
assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: "default"}))
|
||||||
@ -168,8 +170,8 @@ func TestVarsInvalidTmpl(t *testing.T) {
|
|||||||
|
|
||||||
e := &task.Executor{
|
e := &task.Executor{
|
||||||
Dir: dir,
|
Dir: dir,
|
||||||
Stdout: ioutil.Discard,
|
Stdout: io.Discard,
|
||||||
Stderr: ioutil.Discard,
|
Stderr: io.Discard,
|
||||||
}
|
}
|
||||||
assert.NoError(t, e.Setup(), "e.Setup()")
|
assert.NoError(t, e.Setup(), "e.Setup()")
|
||||||
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)")
|
||||||
@ -183,8 +185,8 @@ func TestConcurrency(t *testing.T) {
|
|||||||
|
|
||||||
e := &task.Executor{
|
e := &task.Executor{
|
||||||
Dir: dir,
|
Dir: dir,
|
||||||
Stdout: ioutil.Discard,
|
Stdout: io.Discard,
|
||||||
Stderr: ioutil.Discard,
|
Stderr: io.Discard,
|
||||||
Concurrency: 1,
|
Concurrency: 1,
|
||||||
}
|
}
|
||||||
assert.NoError(t, e.Setup(), "e.Setup()")
|
assert.NoError(t, e.Setup(), "e.Setup()")
|
||||||
@ -236,8 +238,8 @@ func TestDeps(t *testing.T) {
|
|||||||
|
|
||||||
e := &task.Executor{
|
e := &task.Executor{
|
||||||
Dir: dir,
|
Dir: dir,
|
||||||
Stdout: ioutil.Discard,
|
Stdout: io.Discard,
|
||||||
Stderr: ioutil.Discard,
|
Stderr: io.Discard,
|
||||||
}
|
}
|
||||||
assert.NoError(t, e.Setup())
|
assert.NoError(t, e.Setup())
|
||||||
assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: "default"}))
|
assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: "default"}))
|
||||||
@ -550,20 +552,21 @@ func TestStatusVariables(t *testing.T) {
|
|||||||
|
|
||||||
func TestInit(t *testing.T) {
|
func TestInit(t *testing.T) {
|
||||||
const dir = "testdata/init"
|
const dir = "testdata/init"
|
||||||
var file = filepath.Join(dir, "Taskfile.yml")
|
var file = filepath.Join(dir, "Taskfile.yaml")
|
||||||
|
|
||||||
_ = os.Remove(file)
|
_ = os.Remove(file)
|
||||||
if _, err := os.Stat(file); err == nil {
|
if _, err := os.Stat(file); err == nil {
|
||||||
t.Errorf("Taskfile.yml should not exist")
|
t.Errorf("Taskfile.yaml should not exist")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := task.InitTaskfile(ioutil.Discard, dir); err != nil {
|
if err := task.InitTaskfile(io.Discard, dir); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := os.Stat(file); err != nil {
|
if _, err := os.Stat(file); err != nil {
|
||||||
t.Errorf("Taskfile.yml should exist")
|
t.Errorf("Taskfile.yaml should exist")
|
||||||
}
|
}
|
||||||
|
_ = os.Remove(file)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCyclicDep(t *testing.T) {
|
func TestCyclicDep(t *testing.T) {
|
||||||
@ -571,8 +574,8 @@ func TestCyclicDep(t *testing.T) {
|
|||||||
|
|
||||||
e := task.Executor{
|
e := task.Executor{
|
||||||
Dir: dir,
|
Dir: dir,
|
||||||
Stdout: ioutil.Discard,
|
Stdout: io.Discard,
|
||||||
Stderr: ioutil.Discard,
|
Stderr: io.Discard,
|
||||||
}
|
}
|
||||||
assert.NoError(t, e.Setup())
|
assert.NoError(t, e.Setup())
|
||||||
assert.IsType(t, &task.MaximumTaskCallExceededError{}, e.Run(context.Background(), taskfile.Call{Task: "task-1"}))
|
assert.IsType(t, &task.MaximumTaskCallExceededError{}, e.Run(context.Background(), taskfile.Call{Task: "task-1"}))
|
||||||
@ -590,8 +593,8 @@ func TestTaskVersion(t *testing.T) {
|
|||||||
t.Run(test.Dir, func(t *testing.T) {
|
t.Run(test.Dir, func(t *testing.T) {
|
||||||
e := task.Executor{
|
e := task.Executor{
|
||||||
Dir: test.Dir,
|
Dir: test.Dir,
|
||||||
Stdout: ioutil.Discard,
|
Stdout: io.Discard,
|
||||||
Stderr: ioutil.Discard,
|
Stderr: io.Discard,
|
||||||
}
|
}
|
||||||
assert.NoError(t, e.Setup())
|
assert.NoError(t, e.Setup())
|
||||||
assert.Equal(t, test.Version, e.Taskfile.Version)
|
assert.Equal(t, test.Version, e.Taskfile.Version)
|
||||||
@ -605,8 +608,8 @@ func TestTaskIgnoreErrors(t *testing.T) {
|
|||||||
|
|
||||||
e := task.Executor{
|
e := task.Executor{
|
||||||
Dir: dir,
|
Dir: dir,
|
||||||
Stdout: ioutil.Discard,
|
Stdout: io.Discard,
|
||||||
Stderr: ioutil.Discard,
|
Stderr: io.Discard,
|
||||||
}
|
}
|
||||||
assert.NoError(t, e.Setup())
|
assert.NoError(t, e.Setup())
|
||||||
|
|
||||||
@ -668,8 +671,8 @@ func TestDryChecksum(t *testing.T) {
|
|||||||
|
|
||||||
e := task.Executor{
|
e := task.Executor{
|
||||||
Dir: dir,
|
Dir: dir,
|
||||||
Stdout: ioutil.Discard,
|
Stdout: io.Discard,
|
||||||
Stderr: ioutil.Discard,
|
Stderr: io.Discard,
|
||||||
Dry: true,
|
Dry: true,
|
||||||
}
|
}
|
||||||
assert.NoError(t, e.Setup())
|
assert.NoError(t, e.Setup())
|
||||||
@ -756,21 +759,21 @@ func TestIncludesCallingRoot(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestIncludesOptional(t *testing.T) {
|
func TestIncludesOptional(t *testing.T) {
|
||||||
tt := fileContentTest{
|
tt := fileContentTest{
|
||||||
Dir: "testdata/includes_optional",
|
Dir: "testdata/includes_optional",
|
||||||
Target: "default",
|
Target: "default",
|
||||||
TrimSpace: true,
|
TrimSpace: true,
|
||||||
Files: map[string]string{
|
Files: map[string]string{
|
||||||
"called_dep.txt": "called_dep",
|
"called_dep.txt": "called_dep",
|
||||||
}}
|
}}
|
||||||
tt.Run(t)
|
tt.Run(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestIncludesOptionalImplicitFalse(t *testing.T) {
|
func TestIncludesOptionalImplicitFalse(t *testing.T) {
|
||||||
e := task.Executor{
|
e := task.Executor{
|
||||||
Dir: "testdata/includes_optional_implicit_false",
|
Dir: "testdata/includes_optional_implicit_false",
|
||||||
Stdout: ioutil.Discard,
|
Stdout: io.Discard,
|
||||||
Stderr: ioutil.Discard,
|
Stderr: io.Discard,
|
||||||
}
|
}
|
||||||
|
|
||||||
err := e.Setup()
|
err := e.Setup()
|
||||||
@ -781,8 +784,8 @@ func TestIncludesOptionalImplicitFalse(t *testing.T) {
|
|||||||
func TestIncludesOptionalExplicitFalse(t *testing.T) {
|
func TestIncludesOptionalExplicitFalse(t *testing.T) {
|
||||||
e := task.Executor{
|
e := task.Executor{
|
||||||
Dir: "testdata/includes_optional_explicit_false",
|
Dir: "testdata/includes_optional_explicit_false",
|
||||||
Stdout: ioutil.Discard,
|
Stdout: io.Discard,
|
||||||
Stderr: ioutil.Discard,
|
Stderr: io.Discard,
|
||||||
}
|
}
|
||||||
|
|
||||||
err := e.Setup()
|
err := e.Setup()
|
||||||
@ -790,6 +793,21 @@ func TestIncludesOptionalExplicitFalse(t *testing.T) {
|
|||||||
assert.Equal(t, "stat testdata/includes_optional_explicit_false/TaskfileOptional.yml: no such file or directory", err.Error())
|
assert.Equal(t, "stat testdata/includes_optional_explicit_false/TaskfileOptional.yml: no such file or directory", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestIncludesFromCustomTaskfile(t *testing.T) {
|
||||||
|
tt := fileContentTest{
|
||||||
|
Dir: "testdata/includes_yaml",
|
||||||
|
Entrypoint: "Custom.ext",
|
||||||
|
Target: "default",
|
||||||
|
TrimSpace: true,
|
||||||
|
Files: map[string]string{
|
||||||
|
"main.txt": "main",
|
||||||
|
"included_with_yaml_extension.txt": "included_with_yaml_extension",
|
||||||
|
"included_with_custom_file.txt": "included_with_custom_file",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
tt.Run(t)
|
||||||
|
}
|
||||||
|
|
||||||
func TestSummary(t *testing.T) {
|
func TestSummary(t *testing.T) {
|
||||||
const dir = "testdata/summary"
|
const dir = "testdata/summary"
|
||||||
|
|
||||||
@ -804,7 +822,7 @@ func TestSummary(t *testing.T) {
|
|||||||
assert.NoError(t, e.Setup())
|
assert.NoError(t, e.Setup())
|
||||||
assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: "task-with-summary"}, taskfile.Call{Task: "other-task-with-summary"}))
|
assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: "task-with-summary"}, taskfile.Call{Task: "other-task-with-summary"}))
|
||||||
|
|
||||||
data, err := ioutil.ReadFile(filepath.Join(dir, "task-with-summary.txt"))
|
data, err := os.ReadFile(filepath.Join(dir, "task-with-summary.txt"))
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
expectedOutput := string(data)
|
expectedOutput := string(data)
|
||||||
@ -895,8 +913,8 @@ func TestDynamicVariablesShouldRunOnTheTaskDir(t *testing.T) {
|
|||||||
func TestDisplaysErrorOnUnsupportedVersion(t *testing.T) {
|
func TestDisplaysErrorOnUnsupportedVersion(t *testing.T) {
|
||||||
e := task.Executor{
|
e := task.Executor{
|
||||||
Dir: "testdata/version/v1",
|
Dir: "testdata/version/v1",
|
||||||
Stdout: ioutil.Discard,
|
Stdout: io.Discard,
|
||||||
Stderr: ioutil.Discard,
|
Stderr: io.Discard,
|
||||||
}
|
}
|
||||||
err := e.Setup()
|
err := e.Setup()
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
@ -1033,6 +1051,7 @@ func TestIgnoreNilElements(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
{"nil cmd", "testdata/ignore_nil_elements/cmds"},
|
{"nil cmd", "testdata/ignore_nil_elements/cmds"},
|
||||||
{"nil dep", "testdata/ignore_nil_elements/deps"},
|
{"nil dep", "testdata/ignore_nil_elements/deps"},
|
||||||
|
{"nil include", "testdata/ignore_nil_elements/includes"},
|
||||||
{"nil precondition", "testdata/ignore_nil_elements/preconditions"},
|
{"nil precondition", "testdata/ignore_nil_elements/preconditions"},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ func Merge(t1, t2 *Taskfile, namespaces ...string) error {
|
|||||||
dep.Task = taskNameWithNamespace(dep.Task, namespaces...)
|
dep.Task = taskNameWithNamespace(dep.Task, namespaces...)
|
||||||
}
|
}
|
||||||
for _, cmd := range v.Cmds {
|
for _, cmd := range v.Cmds {
|
||||||
if cmd.Task != "" {
|
if cmd != nil && cmd.Task != "" {
|
||||||
cmd.Task = taskNameWithNamespace(cmd.Task, namespaces...)
|
cmd.Task = taskNameWithNamespace(cmd.Task, namespaces...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,14 +19,26 @@ var (
|
|||||||
ErrIncludedTaskfilesCantHaveIncludes = errors.New("task: Included Taskfiles can't have includes. Please, move the include to the main Taskfile")
|
ErrIncludedTaskfilesCantHaveIncludes = errors.New("task: Included Taskfiles can't have includes. Please, move the include to the main Taskfile")
|
||||||
// ErrIncludedTaskfilesCantHaveDotenvs is returned when a included Taskfile contains dotenvs
|
// ErrIncludedTaskfilesCantHaveDotenvs is returned when a included Taskfile contains dotenvs
|
||||||
ErrIncludedTaskfilesCantHaveDotenvs = errors.New("task: Included Taskfiles can't have dotenv declarations. Please, move the dotenv declaration to the main Taskfile")
|
ErrIncludedTaskfilesCantHaveDotenvs = errors.New("task: Included Taskfiles can't have dotenv declarations. Please, move the dotenv declaration to the main Taskfile")
|
||||||
|
|
||||||
|
defaultTaskfiles = []string{"Taskfile.yml", "Taskfile.yaml"}
|
||||||
)
|
)
|
||||||
|
|
||||||
// Taskfile reads a Taskfile for a given directory
|
// Taskfile reads a Taskfile for a given directory
|
||||||
|
// Uses current dir when dir is left empty. Uses Taskfile.yml
|
||||||
|
// or Taskfile.yaml when entrypoint is left empty
|
||||||
func Taskfile(dir string, entrypoint string) (*taskfile.Taskfile, error) {
|
func Taskfile(dir string, entrypoint string) (*taskfile.Taskfile, error) {
|
||||||
path := filepath.Join(dir, entrypoint)
|
if dir == "" {
|
||||||
if _, err := os.Stat(path); err != nil {
|
d, err := os.Getwd()
|
||||||
return nil, fmt.Errorf(`task: No Taskfile found on "%s". Use "task --init" to create a new one`, path)
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
dir = d
|
||||||
}
|
}
|
||||||
|
path, err := exists(filepath.Join(dir, entrypoint))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
t, err := readTaskfile(path)
|
t, err := readTaskfile(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -59,16 +71,14 @@ func Taskfile(dir string, entrypoint string) (*taskfile.Taskfile, error) {
|
|||||||
path = filepath.Join(dir, path)
|
path = filepath.Join(dir, path)
|
||||||
}
|
}
|
||||||
|
|
||||||
info, err := os.Stat(path)
|
path, err = exists(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if includedTask.Optional {
|
if includedTask.Optional {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if info.IsDir() {
|
|
||||||
path = filepath.Join(path, "Taskfile.yml")
|
|
||||||
}
|
|
||||||
includedTaskfile, err := readTaskfile(path)
|
includedTaskfile, err := readTaskfile(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -141,3 +151,22 @@ func readTaskfile(file string) (*taskfile.Taskfile, error) {
|
|||||||
var t taskfile.Taskfile
|
var t taskfile.Taskfile
|
||||||
return &t, yaml.NewDecoder(f).Decode(&t)
|
return &t, yaml.NewDecoder(f).Decode(&t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func exists(path string) (string, error) {
|
||||||
|
fi, err := os.Stat(path)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if fi.Mode().IsRegular() {
|
||||||
|
return path, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, n := range defaultTaskfiles {
|
||||||
|
fpath := filepath.Join(path, n)
|
||||||
|
if _, err := os.Stat(fpath); err == nil {
|
||||||
|
return fpath, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", fmt.Errorf(`task: No Taskfile found in "%s". Use "task --init" to create a new one`, path)
|
||||||
|
}
|
||||||
|
9
testdata/ignore_nil_elements/includes/Taskfile.yml
vendored
Normal file
9
testdata/ignore_nil_elements/includes/Taskfile.yml
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
version: '3'
|
||||||
|
|
||||||
|
includes:
|
||||||
|
inc: inc.yml
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
default:
|
||||||
|
cmds:
|
||||||
|
- task: inc:default
|
7
testdata/ignore_nil_elements/includes/inc.yml
vendored
Normal file
7
testdata/ignore_nil_elements/includes/inc.yml
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
version: '3'
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
default:
|
||||||
|
cmds:
|
||||||
|
-
|
||||||
|
- echo "string-slice-1"
|
1
testdata/includes_yaml/.gitignore
vendored
Normal file
1
testdata/includes_yaml/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
*.txt
|
16
testdata/includes_yaml/Custom.ext
vendored
Normal file
16
testdata/includes_yaml/Custom.ext
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
version: '3'
|
||||||
|
|
||||||
|
includes:
|
||||||
|
included: ./included
|
||||||
|
custom: ./included/custom.yaml
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
default:
|
||||||
|
cmds:
|
||||||
|
- task: gen
|
||||||
|
- task: included:gen
|
||||||
|
- task: custom:gen
|
||||||
|
|
||||||
|
gen:
|
||||||
|
cmds:
|
||||||
|
- echo main > main.txt
|
6
testdata/includes_yaml/included/Taskfile.yaml
vendored
Normal file
6
testdata/includes_yaml/included/Taskfile.yaml
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
version: '3'
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
gen:
|
||||||
|
cmds:
|
||||||
|
- echo included_with_yaml_extension > included_with_yaml_extension.txt
|
6
testdata/includes_yaml/included/custom.yaml
vendored
Normal file
6
testdata/includes_yaml/included/custom.yaml
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
version: '3'
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
gen:
|
||||||
|
cmds:
|
||||||
|
- echo included_with_custom_file > included_with_custom_file.txt
|
Loading…
Reference in New Issue
Block a user