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

Issue 813. Made watch interval configurable through global setting in Taskfile and through CLI arg.

Separated Taskfile param and Arg flag
This commit is contained in:
ilewin
2022-09-08 19:22:44 +02:00
parent 160b788198
commit 1c44d8049a
7 changed files with 122 additions and 1 deletions

View File

@ -73,6 +73,7 @@ func main() {
entrypoint string entrypoint string
output taskfile.Output output taskfile.Output
color bool color bool
interval string
) )
pflag.BoolVar(&versionFlag, "version", false, "show Task version") pflag.BoolVar(&versionFlag, "version", false, "show Task version")
@ -96,6 +97,7 @@ func main() {
pflag.StringVar(&output.Group.End, "output-group-end", "", "message template to print after a task's grouped output") pflag.StringVar(&output.Group.End, "output-group-end", "", "message template to print after a task's grouped output")
pflag.BoolVarP(&color, "color", "c", true, "colored output. Enabled by default. Set flag to false or use NO_COLOR=1 to disable") pflag.BoolVarP(&color, "color", "c", true, "colored output. Enabled by default. Set flag to false or use NO_COLOR=1 to disable")
pflag.IntVarP(&concurrency, "concurrency", "C", 0, "limit number tasks to run concurrently") pflag.IntVarP(&concurrency, "concurrency", "C", 0, "limit number tasks to run concurrently")
pflag.StringVarP(&interval, "interval", "I", "5s", "interval to watch for changes")
pflag.Parse() pflag.Parse()
if versionFlag { if versionFlag {
@ -151,6 +153,7 @@ func main() {
Parallel: parallel, Parallel: parallel,
Color: color, Color: color,
Concurrency: concurrency, Concurrency: concurrency,
Interval: interval,
Stdin: os.Stdin, Stdin: os.Stdin,
Stdout: os.Stdout, Stdout: os.Stdout,
@ -206,6 +209,10 @@ func main() {
e.InterceptInterruptSignals() e.InterceptInterruptSignals()
} }
if e.Interval == "" {
e.Interval = strings.TrimSpace(interval)
}
ctx := context.Background() ctx := context.Background()
if status { if status {

View File

@ -41,6 +41,7 @@ type Executor struct {
Parallel bool Parallel bool
Color bool Color bool
Concurrency int Concurrency int
Interval string
Stdin io.Reader Stdin io.Reader
Stdout io.Writer Stdout io.Writer

View File

@ -10,6 +10,7 @@ import (
"runtime" "runtime"
"strings" "strings"
"testing" "testing"
"time"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
@ -1400,3 +1401,63 @@ func TestEvaluateSymlinksInPaths(t *testing.T) {
err = os.RemoveAll(dir + "/.task") err = os.RemoveAll(dir + "/.task")
assert.NoError(t, err) assert.NoError(t, err)
} }
func TestFileWatcherInterval(t *testing.T) {
const dir = "testdata/watcher_interval"
expectedOutput := strings.TrimSpace(`
task: Started watching for tasks: default
task: [default] echo "Hello, World!"
Hello, World!
task: [default] echo "Hello, World!"
Hello, World!
`)
var buff bytes.Buffer
e := &task.Executor{
Dir: dir,
Stdout: &buff,
Stderr: &buff,
Watch: true,
}
assert.NoError(t, e.Setup())
buff.Reset()
ctx := context.Background()
ctx, cancel := context.WithCancel(ctx)
err := os.MkdirAll(dir+"/src", 0755)
assert.NoError(t, err)
err = os.WriteFile(dir+"/src/a", []byte("test"), 0644)
if err != nil {
t.Fatal(err)
}
go func(ctx context.Context) {
for {
select {
case <-ctx.Done():
return
default:
err := e.Run(ctx, taskfile.Call{Task: "default"})
if err != nil {
return
}
}
}
}(ctx)
time.Sleep(10 * time.Millisecond)
err = os.WriteFile(dir+"/src/a", []byte("test updated"), 0644)
if err != nil {
t.Fatal(err)
}
time.Sleep(70 * time.Millisecond)
cancel()
assert.Equal(t, expectedOutput, strings.TrimSpace(buff.String()))
buff.Reset()
err = os.RemoveAll(dir + "/.task")
assert.NoError(t, err)
}

View File

@ -18,6 +18,7 @@ type Taskfile struct {
Silent bool Silent bool
Dotenv []string Dotenv []string
Run string Run string
Interval string
} }
// UnmarshalYAML implements yaml.Unmarshaler interface // UnmarshalYAML implements yaml.Unmarshaler interface
@ -34,10 +35,13 @@ func (tf *Taskfile) UnmarshalYAML(unmarshal func(interface{}) error) error {
Silent bool Silent bool
Dotenv []string Dotenv []string
Run string Run string
Interval string
} }
if err := unmarshal(&taskfile); err != nil { if err := unmarshal(&taskfile); err != nil {
return err return err
} }
tf.Version = taskfile.Version tf.Version = taskfile.Version
tf.Expansions = taskfile.Expansions tf.Expansions = taskfile.Expansions
tf.Output = taskfile.Output tf.Output = taskfile.Output
@ -49,6 +53,8 @@ func (tf *Taskfile) UnmarshalYAML(unmarshal func(interface{}) error) error {
tf.Silent = taskfile.Silent tf.Silent = taskfile.Silent
tf.Dotenv = taskfile.Dotenv tf.Dotenv = taskfile.Dotenv
tf.Run = taskfile.Run tf.Run = taskfile.Run
tf.Interval = taskfile.Interval
if tf.Expansions <= 0 { if tf.Expansions <= 0 {
tf.Expansions = 2 tf.Expansions = 2
} }

1
testdata/watcher_interval/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
src/*

16
testdata/watcher_interval/Taskfile.yaml vendored Normal file
View File

@ -0,0 +1,16 @@
# https://taskfile.dev
version: '3'
vars:
GREETING: Hello, World!
interval: "50ms"
tasks:
default:
sources:
- "src/*"
cmds:
- echo "{{.GREETING}}"
silent: false

View File

@ -16,7 +16,7 @@ import (
"github.com/radovskyb/watcher" "github.com/radovskyb/watcher"
) )
const watchInterval = 5 * time.Second const defaultWatchInterval = 5 * time.Second
// watchTasks start watching the given tasks // watchTasks start watching the given tasks
func (e *Executor) watchTasks(calls ...taskfile.Call) error { func (e *Executor) watchTasks(calls ...taskfile.Call) error {
@ -24,6 +24,7 @@ func (e *Executor) watchTasks(calls ...taskfile.Call) error {
for i, c := range calls { for i, c := range calls {
tasks[i] = c.Task tasks[i] = c.Task
} }
e.Logger.Errf(logger.Green, "task: Started watching for tasks: %s", strings.Join(tasks, ", ")) e.Logger.Errf(logger.Green, "task: Started watching for tasks: %s", strings.Join(tasks, ", "))
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
@ -36,6 +37,26 @@ func (e *Executor) watchTasks(calls ...taskfile.Call) error {
}() }()
} }
var watchIntervalString string
if e.Taskfile.Interval != "" {
watchIntervalString = e.Taskfile.Interval
} else if e.Interval != "" {
watchIntervalString = e.Interval
}
watchInterval := defaultWatchInterval
if watchIntervalString != "" {
var err error
watchInterval, err = parsedWatchInterval(watchIntervalString)
if err != nil {
e.Logger.Errf(logger.Red, "%v", err)
}
}
e.Logger.VerboseOutf(logger.Green, "task: Watching for changes every %v", watchInterval)
w := watcher.New() w := watcher.New()
defer w.Close() defer w.Close()
w.SetMaxEvents(1) w.SetMaxEvents(1)
@ -163,3 +184,11 @@ func (e *Executor) registerWatchedFiles(w *watcher.Watcher, calls ...taskfile.Ca
func shouldIgnoreFile(path string) bool { func shouldIgnoreFile(path string) bool {
return strings.Contains(path, "/.git") || strings.Contains(path, "/.task") || strings.Contains(path, "/node_modules") return strings.Contains(path, "/.git") || strings.Contains(path, "/.task") || strings.Contains(path, "/node_modules")
} }
func parsedWatchInterval(watchInterval string) (time.Duration, error) {
v, err := time.ParseDuration(watchInterval)
if err != nil {
return 0, fmt.Errorf(`task: Could not parse watch interval "%s": %v`, watchInterval, err)
}
return v, nil
}