From 02e7ff27c79d8ab9c98c6892432e5ecf6dc03bcb Mon Sep 17 00:00:00 2001 From: tylermmorton Date: Fri, 14 Jan 2022 22:38:37 -0500 Subject: [PATCH 01/11] Add support for multi-level includes and cyclic include detection --- task.go | 7 ++- task_test.go | 25 ++++++++ taskfile/read/taskfile.go | 58 +++++++++++++------ testdata/includes_cycle/Taskfile.yml | 12 ++++ testdata/includes_cycle/one/Taskfile.yml | 9 +++ testdata/includes_cycle/one/two/Taskfile.yml | 9 +++ testdata/includes_multi_level/Taskfile.yml | 12 ++++ .../includes_multi_level/one/Taskfile.yml | 9 +++ .../includes_multi_level/one/two/Taskfile.yml | 6 ++ 9 files changed, 127 insertions(+), 20 deletions(-) create mode 100644 testdata/includes_cycle/Taskfile.yml create mode 100644 testdata/includes_cycle/one/Taskfile.yml create mode 100644 testdata/includes_cycle/one/two/Taskfile.yml create mode 100644 testdata/includes_multi_level/Taskfile.yml create mode 100644 testdata/includes_multi_level/one/Taskfile.yml create mode 100644 testdata/includes_multi_level/one/two/Taskfile.yml diff --git a/task.go b/task.go index 17e5be10..21abcf79 100644 --- a/task.go +++ b/task.go @@ -106,7 +106,12 @@ func (e *Executor) Run(ctx context.Context, calls ...taskfile.Call) error { // Setup setups Executor's internal state func (e *Executor) Setup() error { var err error - e.Taskfile, err = read.Taskfile(e.Dir, e.Entrypoint) + e.Taskfile, err = read.Taskfile(&read.ReaderNode{ + Dir: e.Dir, + Entrypoint: e.Entrypoint, + Parent: nil, + Optional: false, + }) if err != nil { return err } diff --git a/task_test.go b/task_test.go index cb75bb00..47c2a8bd 100644 --- a/task_test.go +++ b/task_test.go @@ -753,6 +753,31 @@ func TestIncludes(t *testing.T) { tt.Run(t) } +func TestIncludesMultiLevel(t *testing.T) { + tt := fileContentTest{ + Dir: "testdata/includes_multi_level", + Target: "default", + TrimSpace: true, + Files: map[string]string{}, + } + tt.Run(t) +} + +func TestIncludeCycle(t *testing.T) { + const dir = "testdata/includes_cycle" + expectedError := "include cycle detected between testdata/includes_cycle/Taskfile.yml <--> testdata/includes_cycle/one/two/Taskfile.yml" + + var buff bytes.Buffer + e := task.Executor{ + Dir: dir, + Stdout: &buff, + Stderr: &buff, + Silent: true, + } + + assert.EqualError(t, e.Setup(), expectedError) +} + func TestIncorrectVersionIncludes(t *testing.T) { const dir = "testdata/incorrect_includes" expectedError := "task: Import with additional parameters is only available starting on Taskfile version v3" diff --git a/taskfile/read/taskfile.go b/taskfile/read/taskfile.go index ec7a3ab9..b97d21ab 100644 --- a/taskfile/read/taskfile.go +++ b/taskfile/read/taskfile.go @@ -15,29 +15,35 @@ import ( ) var ( - // ErrIncludedTaskfilesCantHaveIncludes is returned when a included Taskfile contains includes - 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 = 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"} ) +type ReaderNode struct { + Dir string + Entrypoint string + Optional bool + Parent *ReaderNode +} + // 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) { - if dir == "" { +func Taskfile(readerNode *ReaderNode) (*taskfile.Taskfile, error) { + if readerNode.Dir == "" { d, err := os.Getwd() if err != nil { return nil, err } - dir = d + readerNode.Dir = d } - path, err := exists(filepath.Join(dir, entrypoint)) + path, err := exists(filepath.Join(readerNode.Dir, readerNode.Entrypoint)) if err != nil { return nil, err } + readerNode.Entrypoint = filepath.Base(path) t, err := readTaskfile(path) if err != nil { @@ -68,10 +74,32 @@ func Taskfile(dir string, entrypoint string) (*taskfile.Taskfile, error) { return err } if !filepath.IsAbs(path) { - path = filepath.Join(dir, path) + path = filepath.Join(readerNode.Dir, path) } - path, err = exists(path) + // check for cyclic include references by walking up + // node tree of parents and comparing paths + var curNode = readerNode + for curNode.Parent != nil { + curNode = curNode.Parent + curPath := filepath.Join(curNode.Dir, curNode.Entrypoint) + if curPath == path { + return fmt.Errorf("include cycle detected between %s <--> %s", + curPath, + filepath.Join(readerNode.Dir, readerNode.Entrypoint), + ) + } + } + + // if we made it here then there is no cyclic include + readOpts := &ReaderNode{ + Dir: filepath.Dir(path), + Entrypoint: filepath.Base(path), + Parent: readerNode, + Optional: includedTask.Optional, + } + + includedTaskfile, err := Taskfile(readOpts) if err != nil { if includedTask.Optional { return nil @@ -79,14 +107,6 @@ func Taskfile(dir string, entrypoint string) (*taskfile.Taskfile, error) { return err } - includedTaskfile, err := readTaskfile(path) - if err != nil { - return err - } - if includedTaskfile.Includes.Len() > 0 { - return ErrIncludedTaskfilesCantHaveIncludes - } - if v >= 3.0 && len(includedTaskfile.Dotenv) > 0 { return ErrIncludedTaskfilesCantHaveDotenvs } @@ -94,12 +114,12 @@ func Taskfile(dir string, entrypoint string) (*taskfile.Taskfile, error) { if includedTask.AdvancedImport { for k, v := range includedTaskfile.Vars.Mapping { o := v - o.Dir = filepath.Join(dir, includedTask.Dir) + o.Dir = filepath.Join(readerNode.Dir, includedTask.Dir) includedTaskfile.Vars.Mapping[k] = o } for k, v := range includedTaskfile.Env.Mapping { o := v - o.Dir = filepath.Join(dir, includedTask.Dir) + o.Dir = filepath.Join(readerNode.Dir, includedTask.Dir) includedTaskfile.Env.Mapping[k] = o } @@ -120,7 +140,7 @@ func Taskfile(dir string, entrypoint string) (*taskfile.Taskfile, error) { } if v < 3.0 { - path = filepath.Join(dir, fmt.Sprintf("Taskfile_%s.yml", runtime.GOOS)) + path = filepath.Join(readerNode.Dir, fmt.Sprintf("Taskfile_%s.yml", runtime.GOOS)) if _, err = os.Stat(path); err == nil { osTaskfile, err := readTaskfile(path) if err != nil { diff --git a/testdata/includes_cycle/Taskfile.yml b/testdata/includes_cycle/Taskfile.yml new file mode 100644 index 00000000..56748cd7 --- /dev/null +++ b/testdata/includes_cycle/Taskfile.yml @@ -0,0 +1,12 @@ +version: '3' + +includes: + 'one': ./one/Taskfile.yml + +tasks: + default: + cmds: + - echo "called_dep" > called_dep.txt + level1: + cmds: + - echo "hello level 1" \ No newline at end of file diff --git a/testdata/includes_cycle/one/Taskfile.yml b/testdata/includes_cycle/one/Taskfile.yml new file mode 100644 index 00000000..a948df55 --- /dev/null +++ b/testdata/includes_cycle/one/Taskfile.yml @@ -0,0 +1,9 @@ +version: '3' + +includes: + 'two': ./two/Taskfile.yml + +tasks: + level2: + cmds: + - echo "hello level 2" \ No newline at end of file diff --git a/testdata/includes_cycle/one/two/Taskfile.yml b/testdata/includes_cycle/one/two/Taskfile.yml new file mode 100644 index 00000000..b01e4642 --- /dev/null +++ b/testdata/includes_cycle/one/two/Taskfile.yml @@ -0,0 +1,9 @@ +version: '3' + +includes: + bad: "../../Taskfile.yml" + +tasks: + level3: + cmds: + - echo "hello level 3" \ No newline at end of file diff --git a/testdata/includes_multi_level/Taskfile.yml b/testdata/includes_multi_level/Taskfile.yml new file mode 100644 index 00000000..56748cd7 --- /dev/null +++ b/testdata/includes_multi_level/Taskfile.yml @@ -0,0 +1,12 @@ +version: '3' + +includes: + 'one': ./one/Taskfile.yml + +tasks: + default: + cmds: + - echo "called_dep" > called_dep.txt + level1: + cmds: + - echo "hello level 1" \ No newline at end of file diff --git a/testdata/includes_multi_level/one/Taskfile.yml b/testdata/includes_multi_level/one/Taskfile.yml new file mode 100644 index 00000000..a948df55 --- /dev/null +++ b/testdata/includes_multi_level/one/Taskfile.yml @@ -0,0 +1,9 @@ +version: '3' + +includes: + 'two': ./two/Taskfile.yml + +tasks: + level2: + cmds: + - echo "hello level 2" \ No newline at end of file diff --git a/testdata/includes_multi_level/one/two/Taskfile.yml b/testdata/includes_multi_level/one/two/Taskfile.yml new file mode 100644 index 00000000..738fa5ae --- /dev/null +++ b/testdata/includes_multi_level/one/two/Taskfile.yml @@ -0,0 +1,6 @@ +version: '3' + +tasks: + level3: + cmds: + - echo "hello level 3" \ No newline at end of file From c73a2c8f840bf966a13230497b75bfcb0b22aa49 Mon Sep 17 00:00:00 2001 From: tylermmorton Date: Sat, 15 Jan 2022 23:34:59 -0500 Subject: [PATCH 02/11] Move circular include logic to a separate function --- taskfile/read/taskfile.go | 45 ++++++++++++------- testdata/includes_multi_level/Taskfile.yml | 5 +-- .../includes_multi_level/one/Taskfile.yml | 4 +- .../includes_multi_level/one/two/Taskfile.yml | 4 +- 4 files changed, 33 insertions(+), 25 deletions(-) diff --git a/taskfile/read/taskfile.go b/taskfile/read/taskfile.go index b97d21ab..6bd8a005 100644 --- a/taskfile/read/taskfile.go +++ b/taskfile/read/taskfile.go @@ -77,29 +77,18 @@ func Taskfile(readerNode *ReaderNode) (*taskfile.Taskfile, error) { path = filepath.Join(readerNode.Dir, path) } - // check for cyclic include references by walking up - // node tree of parents and comparing paths - var curNode = readerNode - for curNode.Parent != nil { - curNode = curNode.Parent - curPath := filepath.Join(curNode.Dir, curNode.Entrypoint) - if curPath == path { - return fmt.Errorf("include cycle detected between %s <--> %s", - curPath, - filepath.Join(readerNode.Dir, readerNode.Entrypoint), - ) - } - } - - // if we made it here then there is no cyclic include - readOpts := &ReaderNode{ + includeReaderNode := &ReaderNode{ Dir: filepath.Dir(path), Entrypoint: filepath.Base(path), Parent: readerNode, Optional: includedTask.Optional, } - includedTaskfile, err := Taskfile(readOpts) + if err := checkCircularIncludes(includeReaderNode); err != nil { + return err + } + + includedTaskfile, err := Taskfile(includeReaderNode) if err != nil { if includedTask.Optional { return nil @@ -190,3 +179,25 @@ func exists(path string) (string, error) { return "", fmt.Errorf(`task: No Taskfile found in "%s". Use "task --init" to create a new one`, path) } + +func checkCircularIncludes(node *ReaderNode) error { + if node == nil { + return errors.New("failed to check for include cycle: node was nil") + } + if node.Parent == nil { + return errors.New("failed to check for include cycle: node.Parent was nil") + } + var curNode = node + var basePath = filepath.Join(node.Dir, node.Entrypoint) + for curNode.Parent != nil { + curNode = curNode.Parent + curPath := filepath.Join(curNode.Dir, curNode.Entrypoint) + if curPath == basePath { + return fmt.Errorf("include cycle detected between %s <--> %s", + curPath, + filepath.Join(node.Parent.Dir, node.Parent.Entrypoint), + ) + } + } + return nil +} diff --git a/testdata/includes_multi_level/Taskfile.yml b/testdata/includes_multi_level/Taskfile.yml index 56748cd7..a2a6aea5 100644 --- a/testdata/includes_multi_level/Taskfile.yml +++ b/testdata/includes_multi_level/Taskfile.yml @@ -6,7 +6,4 @@ includes: tasks: default: cmds: - - echo "called_dep" > called_dep.txt - level1: - cmds: - - echo "hello level 1" \ No newline at end of file + - task: one:two:default \ No newline at end of file diff --git a/testdata/includes_multi_level/one/Taskfile.yml b/testdata/includes_multi_level/one/Taskfile.yml index a948df55..34d26381 100644 --- a/testdata/includes_multi_level/one/Taskfile.yml +++ b/testdata/includes_multi_level/one/Taskfile.yml @@ -4,6 +4,6 @@ includes: 'two': ./two/Taskfile.yml tasks: - level2: + level1: cmds: - - echo "hello level 2" \ No newline at end of file + - echo "hello level 1" \ No newline at end of file diff --git a/testdata/includes_multi_level/one/two/Taskfile.yml b/testdata/includes_multi_level/one/two/Taskfile.yml index 738fa5ae..d12ab6be 100644 --- a/testdata/includes_multi_level/one/two/Taskfile.yml +++ b/testdata/includes_multi_level/one/two/Taskfile.yml @@ -1,6 +1,6 @@ version: '3' tasks: - level3: + default: cmds: - - echo "hello level 3" \ No newline at end of file + - echo "called_dep" > called_dep.txt \ No newline at end of file From 66748ab5e51fb9c04d7964392b51b2da3b1ebe21 Mon Sep 17 00:00:00 2001 From: tylermmorton Date: Sat, 15 Jan 2022 23:37:39 -0500 Subject: [PATCH 03/11] Update docs to account for new feature --- docs/usage.md | 153 +++++++++++++++++++++++++------------------------- 1 file changed, 75 insertions(+), 78 deletions(-) diff --git a/docs/usage.md b/docs/usage.md index 780b1f27..a67cfadd 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -8,7 +8,7 @@ The example below allows compiling a Go app and uses [Minify][minify] to concat and minify multiple CSS files into a single one. ```yaml -version: '3' +version: "3" tasks: build: @@ -40,7 +40,7 @@ If you omit a task name, "default" will be assumed. You can use `env` to set custom environment variables for a specific task: ```yaml -version: '3' +version: "3" tasks: greet: @@ -54,7 +54,7 @@ Additionally, you can set globally environment variables, that'll be available to all tasks: ```yaml -version: '3' +version: "3" env: GREETING: Hey, there! @@ -86,12 +86,12 @@ ENDPOINT=testing.com ```yaml # Taskfile.yml -version: '3' +version: "3" env: ENV: testing -dotenv: ['.env', '{{.ENV}}/.env.', '{{.HOME}}/.env'] +dotenv: [".env", "{{.ENV}}/.env.", "{{.HOME}}/.env"] tasks: greet: @@ -105,7 +105,7 @@ If you want to share tasks between different projects (Taskfiles), you can use the importing mechanism to include other Taskfiles using the `includes` keyword: ```yaml -version: '3' +version: "3" includes: docs: ./documentation # will look for ./documentation/Taskfile.yml @@ -126,7 +126,7 @@ was removed on version 3, but you still can have a similar behavior by explicitly importing these files: ```yaml -version: '3' +version: "3" includes: build: ./Taskfile_{{OS}}.yml @@ -139,7 +139,7 @@ if the Taskfile is in another directory, but you can force its tasks to run in another directory by using this alternative syntax: ```yaml -version: '3' +version: "3" includes: docs: @@ -150,17 +150,13 @@ includes: > The included Taskfiles must be using the same schema version the main > Taskfile uses. -> Also, for now included Taskfiles can't include other Taskfiles. -> This was a deliberate decision to keep use and implementation simple. -> If you disagree, open an GitHub issue and explain your use case. =) - ### Optional includes Includes marked as optional will allow Task to continue execution as normal if the included file is missing. ```yaml -version: '3' +version: "3" includes: tests: @@ -180,7 +176,7 @@ located. But you can easily make the task run in another folder informing `dir`: ```yaml -version: '3' +version: "3" tasks: serve: @@ -202,7 +198,7 @@ You may have tasks that depend on others. Just pointing them on `deps` will make them run automatically before running the parent task: ```yaml -version: '3' +version: "3" tasks: build: @@ -221,7 +217,7 @@ In the above example, `assets` will always run right before `build` if you run A task can have only dependencies and no commands to group tasks together: ```yaml -version: '3' +version: "3" tasks: assets: @@ -246,15 +242,15 @@ If you want to pass information to dependencies, you can do that the same manner as you would to [call another task](#calling-another-task): ```yaml -version: '3' +version: "3" tasks: default: deps: - task: echo_sth - vars: {TEXT: "before 1"} + vars: { TEXT: "before 1" } - task: echo_sth - vars: {TEXT: "before 2"} + vars: { TEXT: "before 2" } cmds: - echo "after" @@ -270,7 +266,7 @@ often result in a faster build pipeline. But in some situations you may need to call other tasks serially. In this case, just use the following syntax: ```yaml -version: '3' +version: "3" tasks: main-task: @@ -292,7 +288,7 @@ Overriding variables in the called task is as simple as informing `vars` attribute: ```yaml -version: '3' +version: "3" tasks: greet: @@ -304,7 +300,7 @@ tasks: greet-pessimistically: cmds: - task: greet - vars: {RECIPIENT: "Cruel World"} + vars: { RECIPIENT: "Cruel World" } ``` The above syntax is also supported in `deps`. @@ -321,7 +317,7 @@ If a task generates something, you can inform Task the source and generated files, so Task will prevent to run them if not necessary. ```yaml -version: '3' +version: "3" tasks: build: @@ -357,7 +353,7 @@ If you prefer this check to be made by the modification timestamp of the files, instead of its checksum (content), just set the `method` property to `timestamp`. ```yaml -version: '3' +version: "3" tasks: build: @@ -382,7 +378,7 @@ 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: ```yaml -version: '3' +version: "3" tasks: generate-files: @@ -421,13 +417,13 @@ the tasks are not up-to-date. ### Using programmatic checks to cancel execution of an task and it's dependencies 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 +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 -version: '3' +version: "3" tasks: generate-files: @@ -446,7 +442,7 @@ Preconditions can set specific failure messages that can tell a user what steps to take using the `msg` field. If a task has a dependency on a sub-task with a precondition, and that -precondition is not met - the calling task will fail. Note that a task +precondition is not met - the calling task will fail. Note that a task executed with a failing precondition will not run unless `--force` is given. @@ -455,7 +451,7 @@ executing tasks that depend on it, a `precondition` will fail a task, along with any other tasks that depend on it. ```yaml -version: '3' +version: "3" tasks: task-will-fail: @@ -481,24 +477,24 @@ overridden. Supported values for `run`: - * `always` (default) always attempt to invoke the task regardless of the +- `always` (default) always attempt to invoke the task regardless of the number of previous executions - * `once` only invoke this task once regardless of the number of references - * `when_changed` only invokes the task once for each unique set of variables +- `once` only invoke this task once regardless of the number of references +- `when_changed` only invokes the task once for each unique set of variables passed into the task ```yaml -version: '3' +version: "3" tasks: default: cmds: - task: generate-file - vars: { CONTENT: '1' } + vars: { CONTENT: "1" } - task: generate-file - vars: { CONTENT: '2' } + vars: { CONTENT: "2" } - task: generate-file - vars: { CONTENT: '2' } + vars: { CONTENT: "2" } generate-file: run: when_changed @@ -543,7 +539,7 @@ $ task write-file FILE=file.txt "CONTENT=Hello, World!" print "MESSAGE=All done! Example of locally declared vars: ```yaml -version: '3' +version: "3" tasks: print-var: @@ -556,7 +552,7 @@ tasks: Example of global vars in a `Taskfile.yml`: ```yaml -version: '3' +version: "3" vars: GREETING: Hello from Taskfile! @@ -574,7 +570,7 @@ The value will be treated as a command and the output assigned. If there is one or more trailing newlines, the last newline will be trimmed. ```yaml -version: '3' +version: "3" tasks: build: @@ -600,7 +596,7 @@ $ task yarn -- install ``` ```yaml -version: '3' +version: "3" tasks: yarn: @@ -617,7 +613,7 @@ that this command will run even when the task fails. In the example below `rm -rf tmpdir/` will run even if the third command fails: ```yaml -version: '3' +version: "3" tasks: default: @@ -631,7 +627,7 @@ If you want to move the cleanup command into another task, that's possible as well: ```yaml -version: '3' +version: "3" tasks: default: @@ -644,8 +640,8 @@ tasks: ``` > NOTE: Due to the nature of how the -[Go's own `defer` work](https://go.dev/tour/flowcontrol/13), the deferred -commands are executed in the reverse order if you schedule multiple of them. +> [Go's own `defer` work](https://go.dev/tour/flowcontrol/13), the deferred +> commands are executed in the reverse order if you schedule multiple of them. ## Go's template engine @@ -656,7 +652,7 @@ All functions by the Go's [slim-sprig lib](https://go-task.github.io/slim-sprig/ are available. The following example gets the current date in a given format: ```yaml -version: '3' +version: "3" tasks: print-date: @@ -685,7 +681,7 @@ Task also adds the following functions: Example: ```yaml -version: '3' +version: "3" tasks: print-os: @@ -713,7 +709,7 @@ Running `task --list` (or `task -l`) lists all tasks with a description. The following Taskfile: ```yaml -version: '3' +version: "3" tasks: build: @@ -750,7 +746,7 @@ Running `task --summary task-name` will show a summary of a task. The following Taskfile: ```yaml -version: '3' +version: "3" tasks: release: @@ -768,7 +764,7 @@ tasks: - your-build-tool ``` -with running ``task --summary release`` would print the following output: +with running `task --summary release` would print the following output: ``` task: release @@ -784,10 +780,11 @@ dependencies: commands: - your-release-tool ``` + If a summary is missing, the description will be printed. If the task does not have a summary or a description, a warning is printed. -Please note: *showing the summary will not execute the command*. +Please note: _showing the summary will not execute the command_. ## Overriding task name @@ -796,7 +793,7 @@ messages to STDOUT, etc. In this case you can just set `label:`, which can also be interpolated with variables: ```yaml -version: '3' +version: "3" tasks: default: @@ -808,7 +805,7 @@ tasks: MESSAGE: world print: - label: 'print-{{.MESSAGE}}' + label: "print-{{.MESSAGE}}" cmds: - echo "{{.MESSAGE}}" ``` @@ -819,7 +816,7 @@ Silent mode disables echoing of commands before Task runs it. For the following Taskfile: ```yaml -version: '3' +version: "3" tasks: echo: @@ -842,10 +839,10 @@ Print something There are four ways to enable silent mode: -* At command level: +- At command level: ```yaml -version: '3' +version: "3" tasks: echo: @@ -854,10 +851,10 @@ tasks: silent: true ``` -* At task level: +- At task level: ```yaml -version: '3' +version: "3" tasks: echo: @@ -866,10 +863,10 @@ tasks: silent: true ``` -* Globally at Taskfile level: +- Globally at Taskfile level: ```yaml -version: '3' +version: "3" silent: true @@ -879,12 +876,12 @@ tasks: - echo "Print something" ``` -* Or globally with `--silent` or `-s` flag +- Or globally with `--silent` or `-s` flag If you want to suppress STDOUT instead, just redirect a command to `/dev/null`: ```yaml -version: '3' +version: "3" tasks: echo: @@ -903,7 +900,7 @@ You have the option to ignore errors during command execution. Given the following Taskfile: ```yaml -version: '3' +version: "3" tasks: echo: @@ -916,7 +913,7 @@ Task will abort the execution after running `exit 1` because the status code `1` However it is possible to continue with execution using `ignore_error`: ```yaml -version: '3' +version: "3" tasks: echo: @@ -947,24 +944,24 @@ options you can choose: To choose another one, just set it to root in the Taskfile: ```yaml -version: '3' +version: "3" -output: 'group' +output: "group" tasks: # ... ``` - The `group` output will print the entire output of a command once, after it - finishes, so you won't have live feedback for commands that take a long time - to run. +The `group` output will print the entire output of a command once, after it +finishes, so you won't have live feedback for commands that take a long time +to run. - The `prefix` output will prefix every line printed by a command with - `[task-name] ` as the prefix, but you can customize the prefix for a command - with the `prefix:` attribute: +The `prefix` output will prefix every line printed by a command with +`[task-name] ` as the prefix, but you can customize the prefix for a command +with the `prefix:` attribute: - ```yaml -version: '3' +```yaml +version: "3" output: prefixed @@ -972,11 +969,11 @@ tasks: default: deps: - task: print - vars: {TEXT: foo} + vars: { TEXT: foo } - task: print - vars: {TEXT: bar} + vars: { TEXT: bar } - task: print - vars: {TEXT: baz} + vars: { TEXT: baz } print: cmds: @@ -1005,7 +1002,7 @@ The `interactive: true` tells Task this is an interactive application, and Task will try to optimize for it: ```yaml -version: '3' +version: "3" tasks: cmds: @@ -1022,7 +1019,7 @@ Starting on Task v3, you can now write tasks with a shorter syntax if they have the default settings (e.g. no custom `env:`, `vars:`, `desc:`, `silent:` , etc): ```yaml -version: '3' +version: "3" tasks: build: go build -v -o ./app{{exeExt}} . From 15e831c0b00a93cce700815f789c000c6c7e4575 Mon Sep 17 00:00:00 2001 From: tylermmorton Date: Thu, 3 Feb 2022 22:09:57 -0500 Subject: [PATCH 04/11] Revert "Update docs to account for new feature" This reverts commit 66748ab5e51fb9c04d7964392b51b2da3b1ebe21. --- docs/usage.md | 153 +++++++++++++++++++++++++------------------------- 1 file changed, 78 insertions(+), 75 deletions(-) diff --git a/docs/usage.md b/docs/usage.md index a67cfadd..780b1f27 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -8,7 +8,7 @@ The example below allows compiling a Go app and uses [Minify][minify] to concat and minify multiple CSS files into a single one. ```yaml -version: "3" +version: '3' tasks: build: @@ -40,7 +40,7 @@ If you omit a task name, "default" will be assumed. You can use `env` to set custom environment variables for a specific task: ```yaml -version: "3" +version: '3' tasks: greet: @@ -54,7 +54,7 @@ Additionally, you can set globally environment variables, that'll be available to all tasks: ```yaml -version: "3" +version: '3' env: GREETING: Hey, there! @@ -86,12 +86,12 @@ ENDPOINT=testing.com ```yaml # Taskfile.yml -version: "3" +version: '3' env: ENV: testing -dotenv: [".env", "{{.ENV}}/.env.", "{{.HOME}}/.env"] +dotenv: ['.env', '{{.ENV}}/.env.', '{{.HOME}}/.env'] tasks: greet: @@ -105,7 +105,7 @@ If you want to share tasks between different projects (Taskfiles), you can use the importing mechanism to include other Taskfiles using the `includes` keyword: ```yaml -version: "3" +version: '3' includes: docs: ./documentation # will look for ./documentation/Taskfile.yml @@ -126,7 +126,7 @@ was removed on version 3, but you still can have a similar behavior by explicitly importing these files: ```yaml -version: "3" +version: '3' includes: build: ./Taskfile_{{OS}}.yml @@ -139,7 +139,7 @@ if the Taskfile is in another directory, but you can force its tasks to run in another directory by using this alternative syntax: ```yaml -version: "3" +version: '3' includes: docs: @@ -150,13 +150,17 @@ includes: > The included Taskfiles must be using the same schema version the main > Taskfile uses. +> Also, for now included Taskfiles can't include other Taskfiles. +> This was a deliberate decision to keep use and implementation simple. +> If you disagree, open an GitHub issue and explain your use case. =) + ### Optional includes Includes marked as optional will allow Task to continue execution as normal if the included file is missing. ```yaml -version: "3" +version: '3' includes: tests: @@ -176,7 +180,7 @@ located. But you can easily make the task run in another folder informing `dir`: ```yaml -version: "3" +version: '3' tasks: serve: @@ -198,7 +202,7 @@ You may have tasks that depend on others. Just pointing them on `deps` will make them run automatically before running the parent task: ```yaml -version: "3" +version: '3' tasks: build: @@ -217,7 +221,7 @@ In the above example, `assets` will always run right before `build` if you run A task can have only dependencies and no commands to group tasks together: ```yaml -version: "3" +version: '3' tasks: assets: @@ -242,15 +246,15 @@ If you want to pass information to dependencies, you can do that the same manner as you would to [call another task](#calling-another-task): ```yaml -version: "3" +version: '3' tasks: default: deps: - task: echo_sth - vars: { TEXT: "before 1" } + vars: {TEXT: "before 1"} - task: echo_sth - vars: { TEXT: "before 2" } + vars: {TEXT: "before 2"} cmds: - echo "after" @@ -266,7 +270,7 @@ often result in a faster build pipeline. But in some situations you may need to call other tasks serially. In this case, just use the following syntax: ```yaml -version: "3" +version: '3' tasks: main-task: @@ -288,7 +292,7 @@ Overriding variables in the called task is as simple as informing `vars` attribute: ```yaml -version: "3" +version: '3' tasks: greet: @@ -300,7 +304,7 @@ tasks: greet-pessimistically: cmds: - task: greet - vars: { RECIPIENT: "Cruel World" } + vars: {RECIPIENT: "Cruel World"} ``` The above syntax is also supported in `deps`. @@ -317,7 +321,7 @@ If a task generates something, you can inform Task the source and generated files, so Task will prevent to run them if not necessary. ```yaml -version: "3" +version: '3' tasks: build: @@ -353,7 +357,7 @@ If you prefer this check to be made by the modification timestamp of the files, instead of its checksum (content), just set the `method` property to `timestamp`. ```yaml -version: "3" +version: '3' tasks: build: @@ -378,7 +382,7 @@ 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: ```yaml -version: "3" +version: '3' tasks: generate-files: @@ -417,13 +421,13 @@ the tasks are not up-to-date. ### Using programmatic checks to cancel execution of an task and it's dependencies 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 +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 -version: "3" +version: '3' tasks: generate-files: @@ -442,7 +446,7 @@ Preconditions can set specific failure messages that can tell a user what steps to take using the `msg` field. If a task has a dependency on a sub-task with a precondition, and that -precondition is not met - the calling task will fail. Note that a task +precondition is not met - the calling task will fail. Note that a task executed with a failing precondition will not run unless `--force` is given. @@ -451,7 +455,7 @@ executing tasks that depend on it, a `precondition` will fail a task, along with any other tasks that depend on it. ```yaml -version: "3" +version: '3' tasks: task-will-fail: @@ -477,24 +481,24 @@ overridden. Supported values for `run`: -- `always` (default) always attempt to invoke the task regardless of the + * `always` (default) always attempt to invoke the task regardless of the number of previous executions -- `once` only invoke this task once regardless of the number of references -- `when_changed` only invokes the task once for each unique set of variables + * `once` only invoke this task once regardless of the number of references + * `when_changed` only invokes the task once for each unique set of variables passed into the task ```yaml -version: "3" +version: '3' tasks: default: cmds: - task: generate-file - vars: { CONTENT: "1" } + vars: { CONTENT: '1' } - task: generate-file - vars: { CONTENT: "2" } + vars: { CONTENT: '2' } - task: generate-file - vars: { CONTENT: "2" } + vars: { CONTENT: '2' } generate-file: run: when_changed @@ -539,7 +543,7 @@ $ task write-file FILE=file.txt "CONTENT=Hello, World!" print "MESSAGE=All done! Example of locally declared vars: ```yaml -version: "3" +version: '3' tasks: print-var: @@ -552,7 +556,7 @@ tasks: Example of global vars in a `Taskfile.yml`: ```yaml -version: "3" +version: '3' vars: GREETING: Hello from Taskfile! @@ -570,7 +574,7 @@ The value will be treated as a command and the output assigned. If there is one or more trailing newlines, the last newline will be trimmed. ```yaml -version: "3" +version: '3' tasks: build: @@ -596,7 +600,7 @@ $ task yarn -- install ``` ```yaml -version: "3" +version: '3' tasks: yarn: @@ -613,7 +617,7 @@ that this command will run even when the task fails. In the example below `rm -rf tmpdir/` will run even if the third command fails: ```yaml -version: "3" +version: '3' tasks: default: @@ -627,7 +631,7 @@ If you want to move the cleanup command into another task, that's possible as well: ```yaml -version: "3" +version: '3' tasks: default: @@ -640,8 +644,8 @@ tasks: ``` > NOTE: Due to the nature of how the -> [Go's own `defer` work](https://go.dev/tour/flowcontrol/13), the deferred -> commands are executed in the reverse order if you schedule multiple of them. +[Go's own `defer` work](https://go.dev/tour/flowcontrol/13), the deferred +commands are executed in the reverse order if you schedule multiple of them. ## Go's template engine @@ -652,7 +656,7 @@ All functions by the Go's [slim-sprig lib](https://go-task.github.io/slim-sprig/ are available. The following example gets the current date in a given format: ```yaml -version: "3" +version: '3' tasks: print-date: @@ -681,7 +685,7 @@ Task also adds the following functions: Example: ```yaml -version: "3" +version: '3' tasks: print-os: @@ -709,7 +713,7 @@ Running `task --list` (or `task -l`) lists all tasks with a description. The following Taskfile: ```yaml -version: "3" +version: '3' tasks: build: @@ -746,7 +750,7 @@ Running `task --summary task-name` will show a summary of a task. The following Taskfile: ```yaml -version: "3" +version: '3' tasks: release: @@ -764,7 +768,7 @@ tasks: - your-build-tool ``` -with running `task --summary release` would print the following output: +with running ``task --summary release`` would print the following output: ``` task: release @@ -780,11 +784,10 @@ dependencies: commands: - your-release-tool ``` - If a summary is missing, the description will be printed. If the task does not have a summary or a description, a warning is printed. -Please note: _showing the summary will not execute the command_. +Please note: *showing the summary will not execute the command*. ## Overriding task name @@ -793,7 +796,7 @@ messages to STDOUT, etc. In this case you can just set `label:`, which can also be interpolated with variables: ```yaml -version: "3" +version: '3' tasks: default: @@ -805,7 +808,7 @@ tasks: MESSAGE: world print: - label: "print-{{.MESSAGE}}" + label: 'print-{{.MESSAGE}}' cmds: - echo "{{.MESSAGE}}" ``` @@ -816,7 +819,7 @@ Silent mode disables echoing of commands before Task runs it. For the following Taskfile: ```yaml -version: "3" +version: '3' tasks: echo: @@ -839,10 +842,10 @@ Print something There are four ways to enable silent mode: -- At command level: +* At command level: ```yaml -version: "3" +version: '3' tasks: echo: @@ -851,10 +854,10 @@ tasks: silent: true ``` -- At task level: +* At task level: ```yaml -version: "3" +version: '3' tasks: echo: @@ -863,10 +866,10 @@ tasks: silent: true ``` -- Globally at Taskfile level: +* Globally at Taskfile level: ```yaml -version: "3" +version: '3' silent: true @@ -876,12 +879,12 @@ tasks: - echo "Print something" ``` -- Or globally with `--silent` or `-s` flag +* Or globally with `--silent` or `-s` flag If you want to suppress STDOUT instead, just redirect a command to `/dev/null`: ```yaml -version: "3" +version: '3' tasks: echo: @@ -900,7 +903,7 @@ You have the option to ignore errors during command execution. Given the following Taskfile: ```yaml -version: "3" +version: '3' tasks: echo: @@ -913,7 +916,7 @@ Task will abort the execution after running `exit 1` because the status code `1` However it is possible to continue with execution using `ignore_error`: ```yaml -version: "3" +version: '3' tasks: echo: @@ -944,24 +947,24 @@ options you can choose: To choose another one, just set it to root in the Taskfile: ```yaml -version: "3" +version: '3' -output: "group" +output: 'group' tasks: # ... ``` -The `group` output will print the entire output of a command once, after it -finishes, so you won't have live feedback for commands that take a long time -to run. + The `group` output will print the entire output of a command once, after it + finishes, so you won't have live feedback for commands that take a long time + to run. -The `prefix` output will prefix every line printed by a command with -`[task-name] ` as the prefix, but you can customize the prefix for a command -with the `prefix:` attribute: + The `prefix` output will prefix every line printed by a command with + `[task-name] ` as the prefix, but you can customize the prefix for a command + with the `prefix:` attribute: -```yaml -version: "3" + ```yaml +version: '3' output: prefixed @@ -969,11 +972,11 @@ tasks: default: deps: - task: print - vars: { TEXT: foo } + vars: {TEXT: foo} - task: print - vars: { TEXT: bar } + vars: {TEXT: bar} - task: print - vars: { TEXT: baz } + vars: {TEXT: baz} print: cmds: @@ -1002,7 +1005,7 @@ The `interactive: true` tells Task this is an interactive application, and Task will try to optimize for it: ```yaml -version: "3" +version: '3' tasks: cmds: @@ -1019,7 +1022,7 @@ Starting on Task v3, you can now write tasks with a shorter syntax if they have the default settings (e.g. no custom `env:`, `vars:`, `desc:`, `silent:` , etc): ```yaml -version: "3" +version: '3' tasks: build: go build -v -o ./app{{exeExt}} . From 6e5f8b1fb00338669353acfb80deb6fff92ccd40 Mon Sep 17 00:00:00 2001 From: tylermmorton Date: Thu, 3 Feb 2022 22:12:58 -0500 Subject: [PATCH 05/11] Append task prefix to log messages --- taskfile/read/taskfile.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/taskfile/read/taskfile.go b/taskfile/read/taskfile.go index 6bd8a005..58b720f9 100644 --- a/taskfile/read/taskfile.go +++ b/taskfile/read/taskfile.go @@ -182,10 +182,10 @@ func exists(path string) (string, error) { func checkCircularIncludes(node *ReaderNode) error { if node == nil { - return errors.New("failed to check for include cycle: node was nil") + return errors.New("task: failed to check for include cycle: node was nil") } if node.Parent == nil { - return errors.New("failed to check for include cycle: node.Parent was nil") + return errors.New("task: failed to check for include cycle: node.Parent was nil") } var curNode = node var basePath = filepath.Join(node.Dir, node.Entrypoint) @@ -193,7 +193,7 @@ func checkCircularIncludes(node *ReaderNode) error { curNode = curNode.Parent curPath := filepath.Join(curNode.Dir, curNode.Entrypoint) if curPath == basePath { - return fmt.Errorf("include cycle detected between %s <--> %s", + return fmt.Errorf("task: include cycle detected between %s <--> %s", curPath, filepath.Join(node.Parent.Dir, node.Parent.Entrypoint), ) From 0ac56f89736fcbea3220e3211aedd8f111756d7d Mon Sep 17 00:00:00 2001 From: tylermmorton Date: Thu, 3 Feb 2022 22:13:43 -0500 Subject: [PATCH 06/11] Add newlines to test Taskfiles --- testdata/includes_cycle/Taskfile.yml | 2 +- testdata/includes_cycle/one/Taskfile.yml | 2 +- testdata/includes_cycle/one/two/Taskfile.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/testdata/includes_cycle/Taskfile.yml b/testdata/includes_cycle/Taskfile.yml index 56748cd7..2eee81b4 100644 --- a/testdata/includes_cycle/Taskfile.yml +++ b/testdata/includes_cycle/Taskfile.yml @@ -9,4 +9,4 @@ tasks: - echo "called_dep" > called_dep.txt level1: cmds: - - echo "hello level 1" \ No newline at end of file + - echo "hello level 1" diff --git a/testdata/includes_cycle/one/Taskfile.yml b/testdata/includes_cycle/one/Taskfile.yml index a948df55..a8be0fd1 100644 --- a/testdata/includes_cycle/one/Taskfile.yml +++ b/testdata/includes_cycle/one/Taskfile.yml @@ -6,4 +6,4 @@ includes: tasks: level2: cmds: - - echo "hello level 2" \ No newline at end of file + - echo "hello level 2" diff --git a/testdata/includes_cycle/one/two/Taskfile.yml b/testdata/includes_cycle/one/two/Taskfile.yml index b01e4642..d849448a 100644 --- a/testdata/includes_cycle/one/two/Taskfile.yml +++ b/testdata/includes_cycle/one/two/Taskfile.yml @@ -6,4 +6,4 @@ includes: tasks: level3: cmds: - - echo "hello level 3" \ No newline at end of file + - echo "hello level 3" From 35af240faaabed8f95c8b6f88cc4880caf869141 Mon Sep 17 00:00:00 2001 From: tylermmorton Date: Thu, 3 Feb 2022 22:19:07 -0500 Subject: [PATCH 07/11] Add newlines to multi-level test Taskfiles --- testdata/includes_multi_level/Taskfile.yml | 2 +- testdata/includes_multi_level/one/Taskfile.yml | 2 +- testdata/includes_multi_level/one/two/Taskfile.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/testdata/includes_multi_level/Taskfile.yml b/testdata/includes_multi_level/Taskfile.yml index a2a6aea5..0639601f 100644 --- a/testdata/includes_multi_level/Taskfile.yml +++ b/testdata/includes_multi_level/Taskfile.yml @@ -6,4 +6,4 @@ includes: tasks: default: cmds: - - task: one:two:default \ No newline at end of file + - task: one:two:default diff --git a/testdata/includes_multi_level/one/Taskfile.yml b/testdata/includes_multi_level/one/Taskfile.yml index 34d26381..30316593 100644 --- a/testdata/includes_multi_level/one/Taskfile.yml +++ b/testdata/includes_multi_level/one/Taskfile.yml @@ -6,4 +6,4 @@ includes: tasks: level1: cmds: - - echo "hello level 1" \ No newline at end of file + - echo "hello level 1" diff --git a/testdata/includes_multi_level/one/two/Taskfile.yml b/testdata/includes_multi_level/one/two/Taskfile.yml index d12ab6be..83ae318e 100644 --- a/testdata/includes_multi_level/one/two/Taskfile.yml +++ b/testdata/includes_multi_level/one/two/Taskfile.yml @@ -3,4 +3,4 @@ version: '3' tasks: default: cmds: - - echo "called_dep" > called_dep.txt \ No newline at end of file + - echo "called_dep" > called_dep.txt From 13606e5e0019e6b3305a990a65f6064b1bab10da Mon Sep 17 00:00:00 2001 From: tylermmorton Date: Thu, 3 Feb 2022 22:20:49 -0500 Subject: [PATCH 08/11] Remove note about multi level includes from usage documentation --- docs/usage.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/docs/usage.md b/docs/usage.md index 780b1f27..50c39e2a 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -150,10 +150,6 @@ includes: > The included Taskfiles must be using the same schema version the main > Taskfile uses. -> Also, for now included Taskfiles can't include other Taskfiles. -> This was a deliberate decision to keep use and implementation simple. -> If you disagree, open an GitHub issue and explain your use case. =) - ### Optional includes Includes marked as optional will allow Task to continue execution as normal if From 7cdf0000d91c55f8256ebd6dfe546a4b9c095b6b Mon Sep 17 00:00:00 2001 From: tylermmorton Date: Thu, 3 Feb 2022 22:23:01 -0500 Subject: [PATCH 09/11] Fix error message assertion in task_test --- task_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/task_test.go b/task_test.go index 47c2a8bd..6d4fdce2 100644 --- a/task_test.go +++ b/task_test.go @@ -765,7 +765,7 @@ func TestIncludesMultiLevel(t *testing.T) { func TestIncludeCycle(t *testing.T) { const dir = "testdata/includes_cycle" - expectedError := "include cycle detected between testdata/includes_cycle/Taskfile.yml <--> testdata/includes_cycle/one/two/Taskfile.yml" + expectedError := "task: include cycle detected between testdata/includes_cycle/Taskfile.yml <--> testdata/includes_cycle/one/two/Taskfile.yml" var buff bytes.Buffer e := task.Executor{ From 1f1275255c70571bbdc47b0852dcb4e4bb12fc87 Mon Sep 17 00:00:00 2001 From: tylermmorton Date: Mon, 21 Feb 2022 15:31:55 -0500 Subject: [PATCH 10/11] Fix bug in includes where default taskfiles were not being checked. --- task_test.go | 6 +++++- taskfile/read/taskfile.go | 7 +++++++ testdata/includes_multi_level/Taskfile.yml | 4 +++- testdata/includes_multi_level/called_one.txt | 1 + testdata/includes_multi_level/called_three.txt | 1 + testdata/includes_multi_level/called_two.txt | 1 + testdata/includes_multi_level/one/Taskfile.yml | 6 ++---- testdata/includes_multi_level/one/two/Taskfile.yml | 7 ++++--- testdata/includes_multi_level/one/two/three/Taskfile.yml | 4 ++++ 9 files changed, 28 insertions(+), 9 deletions(-) create mode 100644 testdata/includes_multi_level/called_one.txt create mode 100644 testdata/includes_multi_level/called_three.txt create mode 100644 testdata/includes_multi_level/called_two.txt create mode 100644 testdata/includes_multi_level/one/two/three/Taskfile.yml diff --git a/task_test.go b/task_test.go index 6d4fdce2..2d3cc361 100644 --- a/task_test.go +++ b/task_test.go @@ -758,7 +758,11 @@ func TestIncludesMultiLevel(t *testing.T) { Dir: "testdata/includes_multi_level", Target: "default", TrimSpace: true, - Files: map[string]string{}, + Files: map[string]string{ + "called_one.txt": "one", + "called_two.txt": "two", + "called_three.txt": "three", + }, } tt.Run(t) } diff --git a/taskfile/read/taskfile.go b/taskfile/read/taskfile.go index 58b720f9..c0546741 100644 --- a/taskfile/read/taskfile.go +++ b/taskfile/read/taskfile.go @@ -76,6 +76,13 @@ func Taskfile(readerNode *ReaderNode) (*taskfile.Taskfile, error) { if !filepath.IsAbs(path) { path = filepath.Join(readerNode.Dir, path) } + path, err = exists(path) + if err != nil { + if includedTask.Optional { + return nil + } + return err + } includeReaderNode := &ReaderNode{ Dir: filepath.Dir(path), diff --git a/testdata/includes_multi_level/Taskfile.yml b/testdata/includes_multi_level/Taskfile.yml index 0639601f..3734d069 100644 --- a/testdata/includes_multi_level/Taskfile.yml +++ b/testdata/includes_multi_level/Taskfile.yml @@ -1,9 +1,11 @@ version: '3' includes: - 'one': ./one/Taskfile.yml + 'one': ./one/ tasks: default: cmds: + - task: one:default - task: one:two:default + - task: one:two:three:default diff --git a/testdata/includes_multi_level/called_one.txt b/testdata/includes_multi_level/called_one.txt new file mode 100644 index 00000000..5626abf0 --- /dev/null +++ b/testdata/includes_multi_level/called_one.txt @@ -0,0 +1 @@ +one diff --git a/testdata/includes_multi_level/called_three.txt b/testdata/includes_multi_level/called_three.txt new file mode 100644 index 00000000..2bdf67ab --- /dev/null +++ b/testdata/includes_multi_level/called_three.txt @@ -0,0 +1 @@ +three diff --git a/testdata/includes_multi_level/called_two.txt b/testdata/includes_multi_level/called_two.txt new file mode 100644 index 00000000..f719efd4 --- /dev/null +++ b/testdata/includes_multi_level/called_two.txt @@ -0,0 +1 @@ +two diff --git a/testdata/includes_multi_level/one/Taskfile.yml b/testdata/includes_multi_level/one/Taskfile.yml index 30316593..aaf899f2 100644 --- a/testdata/includes_multi_level/one/Taskfile.yml +++ b/testdata/includes_multi_level/one/Taskfile.yml @@ -1,9 +1,7 @@ version: '3' includes: - 'two': ./two/Taskfile.yml + 'two': ./two/ tasks: - level1: - cmds: - - echo "hello level 1" + default: echo one > called_one.txt \ No newline at end of file diff --git a/testdata/includes_multi_level/one/two/Taskfile.yml b/testdata/includes_multi_level/one/two/Taskfile.yml index 83ae318e..ed393064 100644 --- a/testdata/includes_multi_level/one/two/Taskfile.yml +++ b/testdata/includes_multi_level/one/two/Taskfile.yml @@ -1,6 +1,7 @@ version: '3' +includes: + 'three': ./three/Taskfile.yml + tasks: - default: - cmds: - - echo "called_dep" > called_dep.txt + default: echo two > called_two.txt diff --git a/testdata/includes_multi_level/one/two/three/Taskfile.yml b/testdata/includes_multi_level/one/two/three/Taskfile.yml new file mode 100644 index 00000000..db4152be --- /dev/null +++ b/testdata/includes_multi_level/one/two/three/Taskfile.yml @@ -0,0 +1,4 @@ +version: '3' + +tasks: + default: echo three > called_three.txt \ No newline at end of file From fc95061f4c181a0ab492a074c86e249cdba03604 Mon Sep 17 00:00:00 2001 From: tylermmorton Date: Mon, 21 Feb 2022 15:33:54 -0500 Subject: [PATCH 11/11] Add missing newlines --- testdata/includes_multi_level/one/Taskfile.yml | 3 ++- testdata/includes_multi_level/one/two/three/Taskfile.yml | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/testdata/includes_multi_level/one/Taskfile.yml b/testdata/includes_multi_level/one/Taskfile.yml index aaf899f2..11ee8f74 100644 --- a/testdata/includes_multi_level/one/Taskfile.yml +++ b/testdata/includes_multi_level/one/Taskfile.yml @@ -4,4 +4,5 @@ includes: 'two': ./two/ tasks: - default: echo one > called_one.txt \ No newline at end of file + default: echo one > called_one.txt + \ No newline at end of file diff --git a/testdata/includes_multi_level/one/two/three/Taskfile.yml b/testdata/includes_multi_level/one/two/three/Taskfile.yml index db4152be..b674fbc6 100644 --- a/testdata/includes_multi_level/one/two/three/Taskfile.yml +++ b/testdata/includes_multi_level/one/two/three/Taskfile.yml @@ -1,4 +1,5 @@ version: '3' tasks: - default: echo three > called_three.txt \ No newline at end of file + default: echo three > called_three.txt + \ No newline at end of file