diff --git a/CHANGELOG.md b/CHANGELOG.md index 856b4705..19d670ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +- Add ability to set `watch: true` in a task to automatically run it in watch + mode (#231, #1361 by @andreynering). - Fixed a nil pointer error when running a Taskfile with no contents (#1341, #1342 by @pd93). - Added a new [exit code](https://taskfile.dev/api/#exit-codes) (107) for when a diff --git a/docs/docs/usage.md b/docs/docs/usage.md index 2635c265..deb443c5 100644 --- a/docs/docs/usage.md +++ b/docs/docs/usage.md @@ -1806,6 +1806,31 @@ The default watch interval is 5 seconds, but it's possible to change it by either setting `interval: '500ms'` in the root of the Taskfile passing it as an argument like `--interval=500ms`. +Also, it's possible to set `watch: true` in a given task and it'll automatically +run in watch mode: + +```yaml +version: '3' + +interval: 500ms + +tasks: + build: + desc: Builds the Go application + sources: + - '**/*.go' + cmds: + - go build # ... +``` + +:::info + +Note that when setting `watch: true` to a task, it'll only run in watch mode +when running from the CLI via `task my-watch-task`, but won't run in watch mode +if called by another task, either directly or as a dependency. + +::: + [gotemplate]: https://golang.org/pkg/text/template/ diff --git a/docs/static/schema.json b/docs/static/schema.json index b1f54af5..760c92fa 100644 --- a/docs/static/schema.json +++ b/docs/static/schema.json @@ -188,6 +188,11 @@ "requires": { "description": "A list of variables which should be set if this task is to run, if any of these variables are unset the task will error and not run", "$ref": "#/definitions/3/requires_obj" + }, + "watch": { + "description": "Configures a task to run in watch mode automatically.", + "type": "boolean", + "default": false } } }, diff --git a/task.go b/task.go index b02eceb3..e51e6d21 100644 --- a/task.go +++ b/task.go @@ -123,12 +123,13 @@ func (e *Executor) Run(ctx context.Context, calls ...taskfile.Call) error { return nil } - if e.Watch { - return e.watchTasks(calls...) + regularCalls, watchCalls, err := e.splitRegularAndWatchCalls(calls...) + if err != nil { + return err } g, ctx := errgroup.WithContext(ctx) - for _, c := range calls { + for _, c := range regularCalls { c := c if e.Parallel { g.Go(func() error { return e.RunTask(ctx, c) }) @@ -138,7 +139,31 @@ func (e *Executor) Run(ctx context.Context, calls ...taskfile.Call) error { } } } - return g.Wait() + if err := g.Wait(); err != nil { + return err + } + + if len(watchCalls) > 0 { + return e.watchTasks(watchCalls...) + } + + return nil +} + +func (e *Executor) splitRegularAndWatchCalls(calls ...taskfile.Call) (regularCalls []taskfile.Call, watchCalls []taskfile.Call, err error) { + for _, c := range calls { + t, err := e.GetTask(c) + if err != nil { + return nil, nil, err + } + + if e.Watch || t.Watch { + watchCalls = append(watchCalls, c) + } else { + regularCalls = append(regularCalls, c) + } + } + return } // RunTask runs a task by its name diff --git a/taskfile/task.go b/taskfile/task.go index 56e9bc0e..78239788 100644 --- a/taskfile/task.go +++ b/taskfile/task.go @@ -41,6 +41,7 @@ type Task struct { IncludedTaskfile *IncludedTaskfile Platforms []*Platform Location *Location + Watch bool } func (t *Task) Name() string { @@ -101,6 +102,7 @@ func (t *Task) UnmarshalYAML(node *yaml.Node) error { Run string Platforms []*Platform Requires *Requires + Watch bool } if err := node.Decode(&task); err != nil { return err @@ -138,6 +140,7 @@ func (t *Task) UnmarshalYAML(node *yaml.Node) error { t.Run = task.Run t.Platforms = task.Platforms t.Requires = task.Requires + t.Watch = task.Watch return nil } diff --git a/variables.go b/variables.go index 9038d4d3..005ad57d 100644 --- a/variables.go +++ b/variables.go @@ -70,6 +70,7 @@ func (e *Executor) compiledTask(call taskfile.Call, evaluateShVars bool) (*taskf Platforms: origTask.Platforms, Location: origTask.Location, Requires: origTask.Requires, + Watch: origTask.Watch, } new.Dir, err = execext.Expand(new.Dir) if err != nil {