mirror of
https://github.com/go-task/task.git
synced 2025-06-06 23:46:46 +02:00
feat: implement gentle force experiment draft (#1216)
* feat: implement gentle force experiment draft * docs: changelog
This commit is contained in:
parent
d8a12fe56d
commit
5fdaa9aa36
@ -6,8 +6,10 @@
|
|||||||
- e.g. `taskfile.yml`, `taskfile.yaml`, `taskfile.dist.yml` &
|
- e.g. `taskfile.yml`, `taskfile.yaml`, `taskfile.dist.yml` &
|
||||||
`taskfile.dist.yaml`
|
`taskfile.dist.yaml`
|
||||||
- Bug fixed were made to the
|
- Bug fixed were made to the
|
||||||
[npm installation method](https://taskfile.dev/installation/#npm).
|
[npm installation method](https://taskfile.dev/installation/#npm). (#1190, by
|
||||||
(#1190, by @sounisi5011).
|
@sounisi5011).
|
||||||
|
- Added the [gentle force experiment](https://taskfile.dev/experiments) as a
|
||||||
|
draft (#1200, #1216 by @pd93).
|
||||||
|
|
||||||
## v3.26.0 - 2023-06-10
|
## v3.26.0 - 2023-06-10
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ func ParseV3(args ...string) ([]taskfile.Call, *taskfile.Vars) {
|
|||||||
|
|
||||||
for _, arg := range args {
|
for _, arg := range args {
|
||||||
if !strings.Contains(arg, "=") {
|
if !strings.Contains(arg, "=") {
|
||||||
calls = append(calls, taskfile.Call{Task: arg})
|
calls = append(calls, taskfile.Call{Task: arg, Direct: true})
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -22,7 +22,7 @@ func ParseV3(args ...string) ([]taskfile.Call, *taskfile.Vars) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(calls) == 0 {
|
if len(calls) == 0 {
|
||||||
calls = append(calls, taskfile.Call{Task: "default"})
|
calls = append(calls, taskfile.Call{Task: "default", Direct: true})
|
||||||
}
|
}
|
||||||
|
|
||||||
return calls, globals
|
return calls, globals
|
||||||
@ -35,7 +35,7 @@ func ParseV2(args ...string) ([]taskfile.Call, *taskfile.Vars) {
|
|||||||
|
|
||||||
for _, arg := range args {
|
for _, arg := range args {
|
||||||
if !strings.Contains(arg, "=") {
|
if !strings.Contains(arg, "=") {
|
||||||
calls = append(calls, taskfile.Call{Task: arg})
|
calls = append(calls, taskfile.Call{Task: arg, Direct: true})
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,7 +52,7 @@ func ParseV2(args ...string) ([]taskfile.Call, *taskfile.Vars) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(calls) == 0 {
|
if len(calls) == 0 {
|
||||||
calls = append(calls, taskfile.Call{Task: "default"})
|
calls = append(calls, taskfile.Call{Task: "default", Direct: true})
|
||||||
}
|
}
|
||||||
|
|
||||||
return calls, globals
|
return calls, globals
|
||||||
|
@ -20,17 +20,17 @@ func TestArgsV3(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Args: []string{"task-a", "task-b", "task-c"},
|
Args: []string{"task-a", "task-b", "task-c"},
|
||||||
ExpectedCalls: []taskfile.Call{
|
ExpectedCalls: []taskfile.Call{
|
||||||
{Task: "task-a"},
|
{Task: "task-a", Direct: true},
|
||||||
{Task: "task-b"},
|
{Task: "task-b", Direct: true},
|
||||||
{Task: "task-c"},
|
{Task: "task-c", Direct: true},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Args: []string{"task-a", "FOO=bar", "task-b", "task-c", "BAR=baz", "BAZ=foo"},
|
Args: []string{"task-a", "FOO=bar", "task-b", "task-c", "BAR=baz", "BAZ=foo"},
|
||||||
ExpectedCalls: []taskfile.Call{
|
ExpectedCalls: []taskfile.Call{
|
||||||
{Task: "task-a"},
|
{Task: "task-a", Direct: true},
|
||||||
{Task: "task-b"},
|
{Task: "task-b", Direct: true},
|
||||||
{Task: "task-c"},
|
{Task: "task-c", Direct: true},
|
||||||
},
|
},
|
||||||
ExpectedGlobals: &taskfile.Vars{
|
ExpectedGlobals: &taskfile.Vars{
|
||||||
OrderedMap: orderedmap.FromMapWithOrder(
|
OrderedMap: orderedmap.FromMapWithOrder(
|
||||||
@ -46,7 +46,7 @@ func TestArgsV3(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Args: []string{"task-a", "CONTENT=with some spaces"},
|
Args: []string{"task-a", "CONTENT=with some spaces"},
|
||||||
ExpectedCalls: []taskfile.Call{
|
ExpectedCalls: []taskfile.Call{
|
||||||
{Task: "task-a"},
|
{Task: "task-a", Direct: true},
|
||||||
},
|
},
|
||||||
ExpectedGlobals: &taskfile.Vars{
|
ExpectedGlobals: &taskfile.Vars{
|
||||||
OrderedMap: orderedmap.FromMapWithOrder(
|
OrderedMap: orderedmap.FromMapWithOrder(
|
||||||
@ -60,8 +60,8 @@ func TestArgsV3(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Args: []string{"FOO=bar", "task-a", "task-b"},
|
Args: []string{"FOO=bar", "task-a", "task-b"},
|
||||||
ExpectedCalls: []taskfile.Call{
|
ExpectedCalls: []taskfile.Call{
|
||||||
{Task: "task-a"},
|
{Task: "task-a", Direct: true},
|
||||||
{Task: "task-b"},
|
{Task: "task-b", Direct: true},
|
||||||
},
|
},
|
||||||
ExpectedGlobals: &taskfile.Vars{
|
ExpectedGlobals: &taskfile.Vars{
|
||||||
OrderedMap: orderedmap.FromMapWithOrder(
|
OrderedMap: orderedmap.FromMapWithOrder(
|
||||||
@ -75,19 +75,19 @@ func TestArgsV3(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Args: nil,
|
Args: nil,
|
||||||
ExpectedCalls: []taskfile.Call{
|
ExpectedCalls: []taskfile.Call{
|
||||||
{Task: "default"},
|
{Task: "default", Direct: true},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Args: []string{},
|
Args: []string{},
|
||||||
ExpectedCalls: []taskfile.Call{
|
ExpectedCalls: []taskfile.Call{
|
||||||
{Task: "default"},
|
{Task: "default", Direct: true},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Args: []string{"FOO=bar", "BAR=baz"},
|
Args: []string{"FOO=bar", "BAR=baz"},
|
||||||
ExpectedCalls: []taskfile.Call{
|
ExpectedCalls: []taskfile.Call{
|
||||||
{Task: "default"},
|
{Task: "default", Direct: true},
|
||||||
},
|
},
|
||||||
ExpectedGlobals: &taskfile.Vars{
|
ExpectedGlobals: &taskfile.Vars{
|
||||||
OrderedMap: orderedmap.FromMapWithOrder(
|
OrderedMap: orderedmap.FromMapWithOrder(
|
||||||
@ -122,9 +122,9 @@ func TestArgsV2(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Args: []string{"task-a", "task-b", "task-c"},
|
Args: []string{"task-a", "task-b", "task-c"},
|
||||||
ExpectedCalls: []taskfile.Call{
|
ExpectedCalls: []taskfile.Call{
|
||||||
{Task: "task-a"},
|
{Task: "task-a", Direct: true},
|
||||||
{Task: "task-b"},
|
{Task: "task-b", Direct: true},
|
||||||
{Task: "task-c"},
|
{Task: "task-c", Direct: true},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -132,6 +132,7 @@ func TestArgsV2(t *testing.T) {
|
|||||||
ExpectedCalls: []taskfile.Call{
|
ExpectedCalls: []taskfile.Call{
|
||||||
{
|
{
|
||||||
Task: "task-a",
|
Task: "task-a",
|
||||||
|
Direct: true,
|
||||||
Vars: &taskfile.Vars{
|
Vars: &taskfile.Vars{
|
||||||
OrderedMap: orderedmap.FromMapWithOrder(
|
OrderedMap: orderedmap.FromMapWithOrder(
|
||||||
map[string]taskfile.Var{
|
map[string]taskfile.Var{
|
||||||
@ -141,9 +142,10 @@ func TestArgsV2(t *testing.T) {
|
|||||||
),
|
),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{Task: "task-b"},
|
{Task: "task-b", Direct: true},
|
||||||
{
|
{
|
||||||
Task: "task-c",
|
Task: "task-c",
|
||||||
|
Direct: true,
|
||||||
Vars: &taskfile.Vars{
|
Vars: &taskfile.Vars{
|
||||||
OrderedMap: orderedmap.FromMapWithOrder(
|
OrderedMap: orderedmap.FromMapWithOrder(
|
||||||
map[string]taskfile.Var{
|
map[string]taskfile.Var{
|
||||||
@ -161,6 +163,7 @@ func TestArgsV2(t *testing.T) {
|
|||||||
ExpectedCalls: []taskfile.Call{
|
ExpectedCalls: []taskfile.Call{
|
||||||
{
|
{
|
||||||
Task: "task-a",
|
Task: "task-a",
|
||||||
|
Direct: true,
|
||||||
Vars: &taskfile.Vars{
|
Vars: &taskfile.Vars{
|
||||||
OrderedMap: orderedmap.FromMapWithOrder(
|
OrderedMap: orderedmap.FromMapWithOrder(
|
||||||
map[string]taskfile.Var{
|
map[string]taskfile.Var{
|
||||||
@ -175,8 +178,8 @@ func TestArgsV2(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Args: []string{"FOO=bar", "task-a", "task-b"},
|
Args: []string{"FOO=bar", "task-a", "task-b"},
|
||||||
ExpectedCalls: []taskfile.Call{
|
ExpectedCalls: []taskfile.Call{
|
||||||
{Task: "task-a"},
|
{Task: "task-a", Direct: true},
|
||||||
{Task: "task-b"},
|
{Task: "task-b", Direct: true},
|
||||||
},
|
},
|
||||||
ExpectedGlobals: &taskfile.Vars{
|
ExpectedGlobals: &taskfile.Vars{
|
||||||
OrderedMap: orderedmap.FromMapWithOrder(
|
OrderedMap: orderedmap.FromMapWithOrder(
|
||||||
@ -190,19 +193,19 @@ func TestArgsV2(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Args: nil,
|
Args: nil,
|
||||||
ExpectedCalls: []taskfile.Call{
|
ExpectedCalls: []taskfile.Call{
|
||||||
{Task: "default"},
|
{Task: "default", Direct: true},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Args: []string{},
|
Args: []string{},
|
||||||
ExpectedCalls: []taskfile.Call{
|
ExpectedCalls: []taskfile.Call{
|
||||||
{Task: "default"},
|
{Task: "default", Direct: true},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Args: []string{"FOO=bar", "BAR=baz"},
|
Args: []string{"FOO=bar", "BAR=baz"},
|
||||||
ExpectedCalls: []taskfile.Call{
|
ExpectedCalls: []taskfile.Call{
|
||||||
{Task: "default"},
|
{Task: "default", Direct: true},
|
||||||
},
|
},
|
||||||
ExpectedGlobals: &taskfile.Vars{
|
ExpectedGlobals: &taskfile.Vars{
|
||||||
OrderedMap: orderedmap.FromMapWithOrder(
|
OrderedMap: orderedmap.FromMapWithOrder(
|
||||||
|
@ -15,6 +15,7 @@ import (
|
|||||||
"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"
|
||||||
"github.com/go-task/task/v3/errors"
|
"github.com/go-task/task/v3/errors"
|
||||||
|
"github.com/go-task/task/v3/internal/experiments"
|
||||||
"github.com/go-task/task/v3/internal/logger"
|
"github.com/go-task/task/v3/internal/logger"
|
||||||
"github.com/go-task/task/v3/internal/sort"
|
"github.com/go-task/task/v3/internal/sort"
|
||||||
ver "github.com/go-task/task/v3/internal/version"
|
ver "github.com/go-task/task/v3/internal/version"
|
||||||
@ -53,6 +54,7 @@ var flags struct {
|
|||||||
taskSort string
|
taskSort string
|
||||||
status bool
|
status bool
|
||||||
force bool
|
force bool
|
||||||
|
forceAll bool
|
||||||
watch bool
|
watch bool
|
||||||
verbose bool
|
verbose bool
|
||||||
silent bool
|
silent bool
|
||||||
@ -78,7 +80,6 @@ func main() {
|
|||||||
Verbose: flags.verbose,
|
Verbose: flags.verbose,
|
||||||
Color: flags.color,
|
Color: flags.color,
|
||||||
}
|
}
|
||||||
|
|
||||||
if err, ok := err.(*errors.TaskRunError); ok && flags.exitCode {
|
if err, ok := err.(*errors.TaskRunError); ok && flags.exitCode {
|
||||||
l.Errf(logger.Red, "%v\n", err)
|
l.Errf(logger.Red, "%v\n", err)
|
||||||
os.Exit(err.TaskExitCode())
|
os.Exit(err.TaskExitCode())
|
||||||
@ -110,7 +111,6 @@ func run() error {
|
|||||||
pflag.BoolVarP(&flags.listJson, "json", "j", false, "Formats task list as JSON.")
|
pflag.BoolVarP(&flags.listJson, "json", "j", false, "Formats task list as JSON.")
|
||||||
pflag.StringVar(&flags.taskSort, "sort", "", "Changes the order of the tasks when listed. [default|alphanumeric|none].")
|
pflag.StringVar(&flags.taskSort, "sort", "", "Changes the order of the tasks when listed. [default|alphanumeric|none].")
|
||||||
pflag.BoolVar(&flags.status, "status", false, "Exits with non-zero exit code if any of the given tasks is not up-to-date.")
|
pflag.BoolVar(&flags.status, "status", false, "Exits with non-zero exit code if any of the given tasks is not up-to-date.")
|
||||||
pflag.BoolVarP(&flags.force, "force", "f", false, "Forces execution even when the task is up-to-date.")
|
|
||||||
pflag.BoolVarP(&flags.watch, "watch", "w", false, "Enables watch of the given task.")
|
pflag.BoolVarP(&flags.watch, "watch", "w", false, "Enables watch of the given task.")
|
||||||
pflag.BoolVarP(&flags.verbose, "verbose", "v", false, "Enables verbose mode.")
|
pflag.BoolVarP(&flags.verbose, "verbose", "v", false, "Enables verbose mode.")
|
||||||
pflag.BoolVarP(&flags.silent, "silent", "s", false, "Disables echoing.")
|
pflag.BoolVarP(&flags.silent, "silent", "s", false, "Disables echoing.")
|
||||||
@ -129,6 +129,15 @@ func run() error {
|
|||||||
pflag.IntVarP(&flags.concurrency, "concurrency", "C", 0, "Limit number tasks to run concurrently.")
|
pflag.IntVarP(&flags.concurrency, "concurrency", "C", 0, "Limit number tasks to run concurrently.")
|
||||||
pflag.DurationVarP(&flags.interval, "interval", "I", 0, "Interval to watch for changes.")
|
pflag.DurationVarP(&flags.interval, "interval", "I", 0, "Interval to watch for changes.")
|
||||||
pflag.BoolVarP(&flags.global, "global", "g", false, "Runs global Taskfile, from $HOME/{T,t}askfile.{yml,yaml}.")
|
pflag.BoolVarP(&flags.global, "global", "g", false, "Runs global Taskfile, from $HOME/{T,t}askfile.{yml,yaml}.")
|
||||||
|
|
||||||
|
// Gentle force experiment will override the force flag and add a new force-all flag
|
||||||
|
if experiments.GentleForce {
|
||||||
|
pflag.BoolVarP(&flags.force, "force", "f", false, "Forces execution of the directly called task.")
|
||||||
|
pflag.BoolVar(&flags.forceAll, "force-all", false, "Forces execution of the called task and all its dependant tasks.")
|
||||||
|
} else {
|
||||||
|
pflag.BoolVarP(&flags.forceAll, "force", "f", false, "Forces execution even when the task is up-to-date.")
|
||||||
|
}
|
||||||
|
|
||||||
pflag.Parse()
|
pflag.Parse()
|
||||||
|
|
||||||
if flags.version {
|
if flags.version {
|
||||||
@ -194,6 +203,7 @@ func run() error {
|
|||||||
|
|
||||||
e := task.Executor{
|
e := task.Executor{
|
||||||
Force: flags.force,
|
Force: flags.force,
|
||||||
|
ForceAll: flags.forceAll,
|
||||||
Watch: flags.watch,
|
Watch: flags.watch,
|
||||||
Verbose: flags.verbose,
|
Verbose: flags.verbose,
|
||||||
Silent: flags.silent,
|
Silent: flags.silent,
|
||||||
|
@ -70,6 +70,27 @@ version 3 as soon as possible.
|
|||||||
A list of changes between version 2 and version 3 are available in the [Task v3
|
A list of changes between version 2 and version 3 are available in the [Task v3
|
||||||
Release Notes][version-3-release-notes].
|
Release Notes][version-3-release-notes].
|
||||||
|
|
||||||
|
### ![experiment] Gentle Force ([#1200](https://github.com/go-task/task/issues/1200))
|
||||||
|
|
||||||
|
- Environment variable: `TASK_X_FORCE=1`
|
||||||
|
- Breaks: `--force` flag
|
||||||
|
|
||||||
|
The `--force` flag currently forces _all_ tasks to run regardless of the status
|
||||||
|
checks. This can be useful, but we have found that most of the time users only
|
||||||
|
expect the direct task they are calling to be forced and _not_ all of its
|
||||||
|
dependant tasks.
|
||||||
|
|
||||||
|
This experiment changes the `--force` flag to only force the directly called
|
||||||
|
task. All dependant tasks will have their statuses checked as normal and will
|
||||||
|
only run if Task considers them to be out of date. A new `--force-all` flag will
|
||||||
|
also be added to maintain the current behavior for users that need this
|
||||||
|
functionality.
|
||||||
|
|
||||||
|
If you want to migrate, but continue to force all dependant tasks to run, you
|
||||||
|
should replace all uses of the `--force` flag with `--force-all`. Alternatively,
|
||||||
|
if you want to adopt the new behavior, you can continue to use the `--force`
|
||||||
|
flag as you do now!
|
||||||
|
|
||||||
<!-- prettier-ignore-start -->
|
<!-- prettier-ignore-start -->
|
||||||
[breaking-change-proposal]: https://github.com/go-task/task/discussions/1191
|
[breaking-change-proposal]: https://github.com/go-task/task/discussions/1191
|
||||||
[deprecate-version-2-schema]: https://github.com/go-task/task/issues/1197
|
[deprecate-version-2-schema]: https://github.com/go-task/task/issues/1197
|
||||||
|
@ -11,13 +11,13 @@ import (
|
|||||||
|
|
||||||
const envPrefix = "TASK_X_"
|
const envPrefix = "TASK_X_"
|
||||||
|
|
||||||
var TestExperiment bool
|
var GentleForce bool
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
if err := readDotEnv(); err != nil {
|
if err := readDotEnv(); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
TestExperiment = parseEnv("TestExperiment")
|
GentleForce = parseEnv("GENTLE_FORCE")
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseEnv(xName string) bool {
|
func parseEnv(xName string) bool {
|
||||||
|
4
task.go
4
task.go
@ -50,6 +50,7 @@ type Executor struct {
|
|||||||
TempDir string
|
TempDir string
|
||||||
Entrypoint string
|
Entrypoint string
|
||||||
Force bool
|
Force bool
|
||||||
|
ForceAll bool
|
||||||
Watch bool
|
Watch bool
|
||||||
Verbose bool
|
Verbose bool
|
||||||
Silent bool
|
Silent bool
|
||||||
@ -179,7 +180,8 @@ func (e *Executor) RunTask(ctx context.Context, call taskfile.Call) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !e.Force {
|
skipFingerprinting := e.ForceAll || (call.Direct && e.Force)
|
||||||
|
if !skipFingerprinting {
|
||||||
if err := ctx.Err(); err != nil {
|
if err := ctx.Err(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
46
task_test.go
46
task_test.go
@ -2120,3 +2120,49 @@ func TestSilence(t *testing.T) {
|
|||||||
|
|
||||||
buff.Reset()
|
buff.Reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestForce(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
env map[string]string
|
||||||
|
force bool
|
||||||
|
forceAll bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "force",
|
||||||
|
force: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "force-all",
|
||||||
|
forceAll: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "force with gentle force experiment",
|
||||||
|
force: true,
|
||||||
|
env: map[string]string{
|
||||||
|
"TASK_X_GENTLE_FORCE": "1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "force-all with gentle force experiment",
|
||||||
|
forceAll: true,
|
||||||
|
env: map[string]string{
|
||||||
|
"TASK_X_GENTLE_FORCE": "1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
var buff bytes.Buffer
|
||||||
|
e := task.Executor{
|
||||||
|
Dir: "testdata/force",
|
||||||
|
Stdout: &buff,
|
||||||
|
Stderr: &buff,
|
||||||
|
Force: tt.force,
|
||||||
|
ForceAll: tt.forceAll,
|
||||||
|
}
|
||||||
|
require.NoError(t, e.Setup())
|
||||||
|
require.NoError(t, e.Run(context.Background(), taskfile.Call{Task: "task-with-dep", Direct: true}))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -5,4 +5,5 @@ type Call struct {
|
|||||||
Task string
|
Task string
|
||||||
Vars *Vars
|
Vars *Vars
|
||||||
Silent bool
|
Silent bool
|
||||||
|
Direct bool // Was the task called directly or via another task?
|
||||||
}
|
}
|
||||||
|
19
testdata/force/Taskfile.yml
vendored
Normal file
19
testdata/force/Taskfile.yml
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
version: "3"
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
task-with-dep:
|
||||||
|
status: [ test true ]
|
||||||
|
deps: [ indirect ]
|
||||||
|
cmds:
|
||||||
|
- echo "direct"
|
||||||
|
|
||||||
|
task-with-subtask:
|
||||||
|
status: [ test true ]
|
||||||
|
cmds:
|
||||||
|
- task: indirect
|
||||||
|
- echo "direct"
|
||||||
|
|
||||||
|
indirect:
|
||||||
|
status: [ test true ]
|
||||||
|
cmds:
|
||||||
|
- echo "indirect"
|
Loading…
x
Reference in New Issue
Block a user