1
0
mirror of https://github.com/go-task/task.git synced 2024-12-12 10:45:49 +02:00

feat: exclude task from being included

This commit is contained in:
Valentin Maerten 2024-09-24 08:32:28 +02:00
parent 38d0fc2c55
commit bf0ebfcabb
No known key found for this signature in database
GPG Key ID: 2F8E54DDF815C341
8 changed files with 126 additions and 13 deletions

View File

@ -1305,6 +1305,34 @@ func TestIncludesInterpolation(t *testing.T) {
} }
} }
func TestIncludesWithExclude(t *testing.T) {
var buff bytes.Buffer
e := task.Executor{
Dir: "testdata/includes_with_excludes",
Silent: true,
Stdout: &buff,
Stderr: &buff,
}
require.NoError(t, e.Setup())
err := e.Run(context.Background(), &ast.Call{Task: "included:bar"})
require.NoError(t, err)
assert.Equal(t, "bar\n", buff.String())
buff.Reset()
err = e.Run(context.Background(), &ast.Call{Task: "included:foo"})
require.Error(t, err)
buff.Reset()
err = e.Run(context.Background(), &ast.Call{Task: "bar"})
require.Error(t, err)
buff.Reset()
err = e.Run(context.Background(), &ast.Call{Task: "foo"})
require.NoError(t, err)
assert.Equal(t, "foo\n", buff.String())
}
func TestIncludedTaskfileVarMerging(t *testing.T) { func TestIncludedTaskfileVarMerging(t *testing.T) {
const dir = "testdata/included_taskfile_var_merging" const dir = "testdata/included_taskfile_var_merging"
tests := []struct { tests := []struct {

View File

@ -4,6 +4,7 @@ import (
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
"github.com/go-task/task/v3/errors" "github.com/go-task/task/v3/errors"
"github.com/go-task/task/v3/internal/deepcopy"
omap "github.com/go-task/task/v3/internal/omap" omap "github.com/go-task/task/v3/internal/omap"
) )
@ -15,6 +16,7 @@ type Include struct {
Optional bool Optional bool
Internal bool Internal bool
Aliases []string Aliases []string
Excludes []string
AdvancedImport bool AdvancedImport bool
Vars *Vars Vars *Vars
Flatten bool Flatten bool
@ -84,6 +86,7 @@ func (include *Include) UnmarshalYAML(node *yaml.Node) error {
Internal bool Internal bool
Flatten bool Flatten bool
Aliases []string Aliases []string
Excludes []string
Vars *Vars Vars *Vars
} }
if err := node.Decode(&includedTaskfile); err != nil { if err := node.Decode(&includedTaskfile); err != nil {
@ -94,6 +97,7 @@ func (include *Include) UnmarshalYAML(node *yaml.Node) error {
include.Optional = includedTaskfile.Optional include.Optional = includedTaskfile.Optional
include.Internal = includedTaskfile.Internal include.Internal = includedTaskfile.Internal
include.Aliases = includedTaskfile.Aliases include.Aliases = includedTaskfile.Aliases
include.Excludes = includedTaskfile.Excludes
include.AdvancedImport = true include.AdvancedImport = true
include.Vars = includedTaskfile.Vars include.Vars = includedTaskfile.Vars
include.Flatten = includedTaskfile.Flatten include.Flatten = includedTaskfile.Flatten
@ -115,6 +119,7 @@ func (include *Include) DeepCopy() *Include {
Dir: include.Dir, Dir: include.Dir,
Optional: include.Optional, Optional: include.Optional,
Internal: include.Internal, Internal: include.Internal,
Excludes: deepcopy.Slice(include.Excludes),
AdvancedImport: include.AdvancedImport, AdvancedImport: include.AdvancedImport,
Vars: include.Vars.DeepCopy(), Vars: include.Vars.DeepCopy(),
Flatten: include.Flatten, Flatten: include.Flatten,

View File

@ -56,6 +56,12 @@ func (t1 *Tasks) Merge(t2 Tasks, include *Include, includedTaskfileVars *Vars) e
// taskfile are marked as internal // taskfile are marked as internal
task.Internal = task.Internal || (include != nil && include.Internal) task.Internal = task.Internal || (include != nil && include.Internal)
taskName := name taskName := name
// if the task is in the exclude list, don't add it to the merged taskfile and early return
if slices.Contains(include.Excludes, name) {
return nil
}
if !include.Flatten { if !include.Flatten {
// Add namespaces to task dependencies // Add namespaces to task dependencies
for _, dep := range task.Deps { for _, dep := range task.Deps {
@ -106,8 +112,12 @@ func (t1 *Tasks) Merge(t2 Tasks, include *Include, includedTaskfileVars *Vars) e
Include: include.Namespace, Include: include.Namespace,
} }
} }
// Add the task to the merged taskfile
t1.Set(taskName, task) if !slices.Contains(include.Excludes, taskName) {
println("taskName: ", taskName)
// Add the task to the merged taskfile
t1.Set(taskName, task)
}
return nil return nil
}) })

View File

@ -112,6 +112,7 @@ func (r *Reader) include(node Node) error {
Flatten: include.Flatten, Flatten: include.Flatten,
Aliases: include.Aliases, Aliases: include.Aliases,
AdvancedImport: include.AdvancedImport, AdvancedImport: include.AdvancedImport,
Excludes: include.Excludes,
Vars: include.Vars, Vars: include.Vars,
} }
if err := cache.Err(); err != nil { if err := cache.Err(); err != nil {

View File

@ -0,0 +1,17 @@
version: '3'
includes:
included:
taskfile: ./included/Taskfile.yml
excludes:
- foo
included_flatten:
taskfile: ./included/Taskfile.yml
flatten: true
excludes:
- bar
tasks:
default:
cmds:
- echo "called_dep" > called_dep.txt

View File

@ -0,0 +1,5 @@
version: '3'
tasks:
foo: echo foo
bar: echo bar

View File

@ -393,6 +393,8 @@ You can run `task foo` directly without the namespace.
You can also reference the task in other tasks without the namespace. So if you run `task greet` it will run `greet` and `foo` tasks and the output will be : You can also reference the task in other tasks without the namespace. So if you run `task greet` it will run `greet` and `foo` tasks and the output will be :
```text ```text
Greet
Foo
``` ```
If multiple tasks have the same name, an error will be thrown: If multiple tasks have the same name, an error will be thrown:
@ -409,14 +411,14 @@ If multiple tasks have the same name, an error will be thrown:
version: '3' version: '3'
includes: includes:
lib: lib:
taskfile: ./Included.yml taskfile: ./Included.yml
flatten: true flatten: true
tasks: tasks:
greet: greet:
cmds: cmds:
- echo "Greet" - echo "Greet"
- task: foo - task: foo
``` ```
@ -427,9 +429,9 @@ If multiple tasks have the same name, an error will be thrown:
version: '3' version: '3'
tasks: tasks:
greet: greet:
cmds: cmds:
- echo "Foo" - echo "Foo"
``` ```
@ -438,12 +440,50 @@ If multiple tasks have the same name, an error will be thrown:
If you run `task -a` it will print: If you run `task -a` it will print:
```text ```text
task: Found multiple tasks (greet) included by "lib" task: Found multiple tasks (greet) included by "lib"
``` ```
If you the included Taskfile has a task with the same name as a task in the main Taskfile,
you may want to exclude it from the flattened tasks.
You can do this by using the [`excludes` option](#exclude-tasks-from-being-included).
### Exclude tasks from being included
You can exclude tasks from being included by using the `excludes` option. This option takes the list of tasks to be excluded from this include.
<Tabs defaultValue="1"
values={[
{label: 'Taskfile.yml', value: '1'},
{label: 'Included.yml', value: '2'}
]}>
<TabItem value="1">
```yaml
version: '3'
includes:
included:
taskfile: ./Included.yml
excludes: [foo]
```
</TabItem>
<TabItem value="2">
```yaml
version: '3'
tasks:
foo: echo "Foo"
bar: echo "Bar"
```
</TabItem></Tabs>
`task included:foo` will throw an error because the `foo` task is excluded but `task included:bar` will work and display `Bar`.
It's compatible with the `flatten` option.
### Vars of included Taskfiles ### Vars of included Taskfiles

View File

@ -634,6 +634,13 @@
"type": "string" "type": "string"
} }
}, },
"excludes": {
"description": "A list of tasks to be excluded from inclusion.",
"type": "array",
"items": {
"type": "string"
}
},
"vars": { "vars": {
"description": "A set of variables to apply to the included Taskfile.", "description": "A set of variables to apply to the included Taskfile.",
"$ref": "#/definitions/vars" "$ref": "#/definitions/vars"