1
0
mirror of https://github.com/go-task/task.git synced 2025-06-15 00:15:10 +02:00

Changes per feedback

This commit is contained in:
Stephen Prater
2019-08-25 10:30:00 -07:00
parent e0f72a6193
commit db36bc67f1
7 changed files with 60 additions and 41 deletions

View File

@ -266,6 +266,8 @@ The above syntax is also supported in `deps`.
## Prevent unnecessary work ## Prevent unnecessary work
### By fingerprinting locally generated files and their sources
If a task generates something, you can inform Task the source and generated If a task generates something, you can inform Task the source and generated
files, so Task will prevent to run them if not necessary. files, so Task will prevent to run them if not necessary.
@ -321,6 +323,9 @@ tasks:
> TIP: method `none` skips any validation and always run the task. > TIP: method `none` skips any validation and always run the task.
### Using programmatic checks to indicate a task is up to date.
Alternatively, you can inform a sequence of tests as `status`. If no error Alternatively, you can inform a sequence of tests as `status`. If no error
is returned (exit status 0), the task is considered up-to-date: is returned (exit status 0), the task is considered up-to-date:
@ -340,7 +345,8 @@ tasks:
- test -f directory/file2.txt - test -f directory/file2.txt
``` ```
Normally, you would use either `status` or `sources` in combination with
Normally, you would use `sources` in combination with
`generates` - but for tasks that generate remote artifacts (Docker images, `generates` - but for tasks that generate remote artifacts (Docker images,
deploys, CD releases) the checksum source and timestamps require either deploys, CD releases) the checksum source and timestamps require either
access to the artifact or for an out-of-band refresh of the `.checksum` access to the artifact or for an out-of-band refresh of the `.checksum`
@ -356,9 +362,13 @@ up-to-date.
Also, `task --status [tasks]...` will exit with a non-zero exit code if any of Also, `task --status [tasks]...` will exit with a non-zero exit code if any of
the tasks are not up-to-date. the tasks are not up-to-date.
If you need a certain set of conditions to be _true_ you can use the ### Using programmatic checks to cancel execution of an task and it's dependencies
`preconditions` stanza. `preconditions` are very similar to `status`
lines except they support `sh` expansion and they SHOULD all return 0. In addition to `status` checks, there are also `preconditions` checks, which are
the logical inverse of `status` checks. That is, if you need a certain set of
conditions to be _true_ you can use the `preconditions` stanza.
`preconditions` are similar to `status` lines except they support `sh`
expansion and they SHOULD all return 0.
```yaml ```yaml
version: '2' version: '2'

6
go.mod
View File

@ -14,10 +14,8 @@ require (
github.com/radovskyb/watcher v1.0.5 github.com/radovskyb/watcher v1.0.5
github.com/spf13/pflag v1.0.3 github.com/spf13/pflag v1.0.3
github.com/stretchr/testify v1.3.0 github.com/stretchr/testify v1.3.0
golang.org/x/crypto v0.0.0-20180830192347-182538f80094 // indirect golang.org/x/sync v0.0.0-20190423024810-112230192c58
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d // indirect golang.org/x/tools/gopls v0.1.3 // indirect
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f
golang.org/x/sys v0.0.0-20180831094639-fa5fdf94c789 // indirect
gopkg.in/yaml.v2 v2.2.1 gopkg.in/yaml.v2 v2.2.1
mvdan.cc/sh v2.6.4+incompatible mvdan.cc/sh v2.6.4+incompatible
) )

12
go.sum
View File

@ -33,12 +33,24 @@ github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
golang.org/x/crypto v0.0.0-20180830192347-182538f80094 h1:rVTAlhYa4+lCfNxmAIEOGQRoD23UqP72M3+rSWVGDTg= golang.org/x/crypto v0.0.0-20180830192347-182538f80094 h1:rVTAlhYa4+lCfNxmAIEOGQRoD23UqP72M3+rSWVGDTg=
golang.org/x/crypto v0.0.0-20180830192347-182538f80094/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180830192347-182538f80094/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d h1:g9qWBGx4puODJTMVyoPrpoxPFgVGd+z1DZwjfRu4d0I= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d h1:g9qWBGx4puODJTMVyoPrpoxPFgVGd+z1DZwjfRu4d0I=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180831094639-fa5fdf94c789 h1:T8D7l6WB3tLu+VpKvw06ieD/OhBi1XpJmG1U/FtttZg= golang.org/x/sys v0.0.0-20180831094639-fa5fdf94c789 h1:T8D7l6WB3tLu+VpKvw06ieD/OhBi1XpJmG1U/FtttZg=
golang.org/x/sys v0.0.0-20180831094639-fa5fdf94c789/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180831094639-fa5fdf94c789/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20190710153321-831012c29e42 h1:4IOeC7p+OItq3+O5BWkcmVu2uBe3jekXau5S4QZX9DU=
golang.org/x/tools v0.0.0-20190710153321-831012c29e42/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
golang.org/x/tools/gopls v0.1.3 h1:CB5ECiPysqZrwxcyRjN+exyZpY0gODTZvNiqQi3lpeo=
golang.org/x/tools/gopls v0.1.3/go.mod h1:vrCQzOKxvuiZLjCKSmbbov04oeBQQOb4VQqwYK2PWIY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= 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/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=

View File

@ -46,10 +46,6 @@ func (c *Checksum) IsUpToDate() (bool, error) {
return oldMd5 == newMd5, nil return oldMd5 == newMd5, nil
} }
func (t *Checksum) Kind() string {
return "checksum"
}
func (c *Checksum) checksum(files ...string) (string, error) { func (c *Checksum) checksum(files ...string) (string, error) {
h := md5.New() h := md5.New()
@ -77,7 +73,7 @@ func (c *Checksum) checksum(files ...string) (string, error) {
return fmt.Sprintf("%x", h.Sum(nil)), nil return fmt.Sprintf("%x", h.Sum(nil)), nil
} }
// Value implements the Chcker Interface // Value implements the Checker Interface
func (c *Checksum) Value() (string, error) { func (c *Checksum) Value() (string, error) {
return c.checksum() return c.checksum()
} }
@ -87,6 +83,11 @@ func (c *Checksum) OnError() error {
return os.Remove(c.checksumFilePath()) return os.Remove(c.checksumFilePath())
} }
// Kind implements the Checker Interface
func (t *Checksum) Kind() string {
return "checksum"
}
func (c *Checksum) checksumFilePath() string { func (c *Checksum) checksumFilePath() string {
return filepath.Join(c.Dir, ".task", "checksum", c.normalizeFilename(c.Task)) return filepath.Join(c.Dir, ".task", "checksum", c.normalizeFilename(c.Task))
} }

View File

@ -18,6 +18,10 @@ type Templater struct {
err error err error
} }
func (r *Templater) RefreshStringMap() {
r.strMap = r.Vars.ToStringMap()
}
func (r *Templater) Replace(str string) string { func (r *Templater) Replace(str string) string {
if r.err != nil || str == "" { if r.err != nil || str == "" {
return "" return ""

View File

@ -32,7 +32,7 @@ func (e *Executor) isTaskUpToDate(ctx context.Context, t *taskfile.Task) (bool,
return e.isTaskUpToDateStatus(ctx, t) return e.isTaskUpToDateStatus(ctx, t)
} }
checker, err := e.GetStatusChecker(t) checker, err := e.getStatusChecker(t)
if err != nil { if err != nil {
return false, err return false, err
} }
@ -41,14 +41,14 @@ func (e *Executor) isTaskUpToDate(ctx context.Context, t *taskfile.Task) (bool,
} }
func (e *Executor) statusOnError(t *taskfile.Task) error { func (e *Executor) statusOnError(t *taskfile.Task) error {
checker, err := e.GetStatusChecker(t) checker, err := e.getStatusChecker(t)
if err != nil { if err != nil {
return err return err
} }
return checker.OnError() return checker.OnError()
} }
func (e *Executor) GetStatusChecker(t *taskfile.Task) (status.Checker, error) { func (e *Executor) getStatusChecker(t *taskfile.Task) (status.Checker, error) {
switch t.Method { switch t.Method {
case "", "timestamp": case "", "timestamp":
return &status.Timestamp{ return &status.Timestamp{

View File

@ -1,7 +1,6 @@
package task package task
import ( import (
"io/ioutil"
"path/filepath" "path/filepath"
"strings" "strings"
@ -64,30 +63,6 @@ func (e *Executor) CompiledTask(call taskfile.Call) (*taskfile.Task, error) {
new.Env[k] = taskfile.Var{Static: static} new.Env[k] = taskfile.Var{Static: static}
} }
if len(origTask.Status) > 0 {
e := &Executor{
Dir: new.Dir,
Stdout: ioutil.Discard,
Stderr: ioutil.Discard,
Dry: true,
}
checker, err := e.GetStatusChecker(&new)
if err != nil {
return nil, err
}
value, err := checker.Value()
if err != nil {
return nil, err
}
vars[strings.ToUpper(checker.Kind())] = taskfile.Var{Static: value}
statusTemplater := templater.Templater{Vars: vars}
new.Status = statusTemplater.ReplaceSlice(origTask.Status)
}
if len(origTask.Cmds) > 0 { if len(origTask.Cmds) > 0 {
new.Cmds = make([]*taskfile.Cmd, len(origTask.Cmds)) new.Cmds = make([]*taskfile.Cmd, len(origTask.Cmds))
for i, cmd := range origTask.Cmds { for i, cmd := range origTask.Cmds {
@ -120,5 +95,24 @@ func (e *Executor) CompiledTask(call taskfile.Call) (*taskfile.Task, error) {
} }
} }
if len(origTask.Status) > 0 {
checker, err := e.getStatusChecker(&new)
if err != nil {
return nil, err
}
value, err := checker.Value()
if err != nil {
return nil, err
}
vars[strings.ToUpper(checker.Kind())] = taskfile.Var{Static: value}
// Adding new static variables, requires us to refresh the templaters
// cache of the the static values
r.RefreshStringMap()
new.Status = r.ReplaceSlice(origTask.Status)
}
return &new, r.Err() return &new, r.Err()
} }