Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions task_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1243,6 +1243,12 @@ func TestIncludesFlatten(t *testing.T) {
{name: "included flatten with deps", taskfile: "Taskfile.yml", task: "with_deps", expectedOutput: "gen from included\nwith_deps from included\n"},
{name: "included flatten nested", taskfile: "Taskfile.yml", task: "from_nested", expectedOutput: "from nested\n"},
{name: "included flatten multiple same task", taskfile: "Taskfile.multiple.yml", task: "gen", expectedErr: true, expectedOutput: "task: Found multiple tasks (gen) included by \"included\"\""},
{name: "included flatten overridden", taskfile: "Taskfile.override.yml", task: "override", expectedOutput: "overridden task\n"},
{name: "included flatten override unique task", taskfile: "Taskfile.override.yml", task: "unique", expectedOutput: "unique task\n"},
{name: "included flatten override", taskfile: "Taskfile.override.yml", task: "gen", expectedOutput: "gen from included\n"},
{name: "included flatten override with parent", taskfile: "Taskfile.override.yml", task: "override_with_parent", expectedOutput: "task: [included:override] echo \"base task\"\nbase task\noverridden task\n"},
{name: "included flatten override with deps", taskfile: "Taskfile.override.yml", task: "with_deps", expectedOutput: "gen from included\nwith_deps from included\n"},
{name: "included flatten override nested", taskfile: "Taskfile.override.yml", task: "from_nested", expectedOutput: "from nested\n"},
}

for _, test := range tests {
Expand Down
4 changes: 4 additions & 0 deletions taskfile/ast/include.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ type Include struct {
AdvancedImport bool
Vars *Vars
Flatten bool
Override bool
}

// Includes represents information about included tasksfiles
Expand Down Expand Up @@ -83,6 +84,7 @@ func (include *Include) UnmarshalYAML(node *yaml.Node) error {
Optional bool
Internal bool
Flatten bool
Override bool
Aliases []string
Vars *Vars
}
Expand All @@ -97,6 +99,7 @@ func (include *Include) UnmarshalYAML(node *yaml.Node) error {
include.AdvancedImport = true
include.Vars = includedTaskfile.Vars
include.Flatten = includedTaskfile.Flatten
include.Override = includedTaskfile.Override
return nil
}

Expand All @@ -118,5 +121,6 @@ func (include *Include) DeepCopy() *Include {
AdvancedImport: include.AdvancedImport,
Vars: include.Vars.DeepCopy(),
Flatten: include.Flatten,
Override: include.Override,
}
}
13 changes: 9 additions & 4 deletions taskfile/ast/tasks.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,13 +100,18 @@ func (t1 *Tasks) Merge(t2 Tasks, include *Include, includedTaskfileVars *Vars) e
task.IncludedTaskfileVars = includedTaskfileVars.DeepCopy()
}

// Check for task name conflicts, if t1 already has a task with the same name fail
// If marked as override, replace the task with t1's task
if t1.Get(taskName) != nil {
return &errors.TaskNameFlattenConflictError{
TaskName: taskName,
Include: include.Namespace,
if include.Override {
return nil
} else {
return &errors.TaskNameFlattenConflictError{
TaskName: taskName,
Include: include.Namespace,
}
}
}
// Add the task to the merged taskfile
t1.Set(taskName, task)

return nil
Expand Down
1 change: 1 addition & 0 deletions taskfile/reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ func (r *Reader) include(node Node) error {
Optional: include.Optional,
Internal: include.Internal,
Flatten: include.Flatten,
Override: include.Override,
Aliases: include.Aliases,
AdvancedImport: include.AdvancedImport,
Vars: include.Vars,
Expand Down
26 changes: 26 additions & 0 deletions testdata/includes_flatten/Taskfile.override.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
version: '3'

includes:
included:
taskfile: ./included
dir: ./included
flatten: true
override: true

tasks:
default:
cmds:
- echo root_directory > root_directory.txt

override:
cmds:
- echo "overridden task"

override_with_parent:
cmds:
- task included:override
- echo "overridden task"

unique:
cmds:
- echo "unique task"
7 changes: 5 additions & 2 deletions testdata/includes_flatten/included/Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,12 @@ tasks:
- gen
cmds:
- echo "with_deps from included"



pwd:
desc: Print working directory
cmds:
- pwd

override:
cmds:
- echo "base task"
1 change: 1 addition & 0 deletions website/docs/reference/schema.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ toc_max_heading_level: 5
| `dir` | `string` | The parent Taskfile directory | The working directory of the included tasks when run. |
| `optional` | `bool` | `false` | If `true`, no errors will be thrown if the specified file does not exist. |
| `flatten` | `bool` | `false` | If `true`, the tasks from the included Taskfile will be available in the including Taskfile without a namespace. If a task with the same name already exists in the including Taskfile, an error will be thrown. |
| `override` | `bool` | `false` | If `true`, the tasks from the included Taskfile will be available in the including Taskfile without a namespace. If a task with the same name already exists in the including Taskfile, the included task is overridden. |
| `internal` | `bool` | `false` | Stops any task in the included Taskfile from being callable on the command line. These commands will also be omitted from the output when used with `--list`. |
| `aliases` | `[]string` | | Alternative names for the namespace of the included Taskfile. |
| `vars` | `map[string]Variable` | | A set of variables to apply to the included Taskfile. |
Expand Down
54 changes: 54 additions & 0 deletions website/docs/usage.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -441,9 +441,63 @@ task: Found multiple tasks (greet) included by "lib"

```

#### Flatten Override

When using flatten, it may be desirable to override a specific command that is included. When enabled, you can avoid multiple task conflicts by instead overriding the task in the default namespace.

If multiple tasks have the same name, the highest order task is executed:

<Tabs defaultValue="1"
values={[
{label: 'Taskfile.yml', value: '1'},
{label: 'Included.yml', value: '2'}
]}>

<TabItem value="1">

```yaml
version: '3'
includes:
lib:
taskfile: ./Included.yml
flatten: true
override: true

tasks:
greet:
cmds:
- echo "Greet"
- task: foo
```


</TabItem>
<TabItem value="2">

```yaml
version: '3'

tasks:
greet:
cmds:
- echo "Foo"
```


</TabItem></Tabs>

If you run `task -a` it will print:
```text
task: Available tasks for this project:
* default:
* greet:
```

If you run `task greet` it will print:
```text
Greet
Foo
```

### Vars of included Taskfiles

Expand Down
4 changes: 4 additions & 0 deletions website/static/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -623,6 +623,10 @@
"description": "If `true`, the tasks from the included Taskfile will be available in the including Taskfile without a namespace. If a task with the same name already exists in the including Taskfile, an error will be thrown.",
"type": "boolean"
},
"override": {
"description": "If `true`, the tasks from the included Taskfile will be available in the including Taskfile without a namespace. If a task with the same name already exists in the including Taskfile, the included task is overridden.",
"type": "boolean"
},
"internal": {
"description": "Stops any task in the included Taskfile from being callable on the command line. These commands will also be omitted from the output when used with `--list`.",
"type": "boolean"
Expand Down