diff --git a/task_test.go b/task_test.go index dd92f8eef5..68f9375f2b 100644 --- a/task_test.go +++ b/task_test.go @@ -1635,6 +1635,28 @@ func TestIncludesWithExclude(t *testing.T) { require.Error(t, err) buff.Reset() + err = e.Run(t.Context(), &task.Call{Task: "included:tools:lint"}) + require.Error(t, err) + buff.Reset() + + err = e.Run(t.Context(), &task.Call{Task: "included:tools:test"}) + require.Error(t, err) + buff.Reset() + + err = e.Run(t.Context(), &task.Call{Task: "included:toolshed"}) + require.NoError(t, err) + assert.Equal(t, "toolshed\n", buff.String()) + buff.Reset() + + err = e.Run(t.Context(), &task.Call{Task: "included:deploy:*"}) + require.Error(t, err) + buff.Reset() + + err = e.Run(t.Context(), &task.Call{Task: "included:deploy:one"}) + require.NoError(t, err) + assert.Equal(t, "deploy-one\n", buff.String()) + buff.Reset() + err = e.Run(t.Context(), &task.Call{Task: "bar"}) require.Error(t, err) buff.Reset() diff --git a/taskfile/ast/tasks.go b/taskfile/ast/tasks.go index 62aa53a6b4..c9d85faa33 100644 --- a/taskfile/ast/tasks.go +++ b/taskfile/ast/tasks.go @@ -130,8 +130,11 @@ func (t1 *Tasks) Merge(t2 *Tasks, include *Include, includedTaskfileVars *Vars) task.Internal = task.Internal || (include != nil && include.Internal) taskName := name - // if the task is in the exclude list, don't add it to the merged taskfile - if slices.Contains(include.Excludes, name) { + // If the task or one of its namespaces is in the exclude list, don't add + // it to the merged taskfile. + if slices.ContainsFunc(include.Excludes, func(exclude string) bool { + return name == exclude || strings.HasPrefix(name, exclude+":") + }) { continue } diff --git a/testdata/includes_with_excludes/Taskfile.yml b/testdata/includes_with_excludes/Taskfile.yml index 6548aab5aa..1a0ab37dbd 100644 --- a/testdata/includes_with_excludes/Taskfile.yml +++ b/testdata/includes_with_excludes/Taskfile.yml @@ -4,7 +4,9 @@ includes: included: taskfile: ./included/Taskfile.yml excludes: - - foo + - foo + - tools + - deploy:* included_flatten: taskfile: ./included/Taskfile.yml flatten: true diff --git a/testdata/includes_with_excludes/included/Taskfile.yml b/testdata/includes_with_excludes/included/Taskfile.yml index 6de33b0149..9612ba88cb 100644 --- a/testdata/includes_with_excludes/included/Taskfile.yml +++ b/testdata/includes_with_excludes/included/Taskfile.yml @@ -3,3 +3,8 @@ version: '3' tasks: foo: echo foo bar: echo bar + tools:lint: echo lint + tools:test: echo test + toolshed: echo toolshed + deploy:*: echo wildcard + deploy:one: echo deploy-one diff --git a/website/src/docs/guide.md b/website/src/docs/guide.md index 8a06d38a3a..0cae3b5576 100644 --- a/website/src/docs/guide.md +++ b/website/src/docs/guide.md @@ -413,7 +413,9 @@ You can do this by using the ### 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. +option takes a list of task names or namespaces to be excluded from this +include. Excluding a namespace also excludes all tasks below it. Entries are +matched literally and are not treated as glob patterns. ::: code-group @@ -423,7 +425,7 @@ version: '3' includes: included: taskfile: ./Included.yml - excludes: [foo] + excludes: [foo, tools] ``` ```yaml [Included.yml] @@ -432,6 +434,8 @@ version: '3' tasks: foo: echo "Foo" bar: echo "Bar" + tools:lint: echo "Lint" + tools:test: echo "Test" ``` ::: diff --git a/website/src/docs/reference/schema.md b/website/src/docs/reference/schema.md index 71ead0757e..429febde5e 100644 --- a/website/src/docs/reference/schema.md +++ b/website/src/docs/reference/schema.md @@ -297,13 +297,13 @@ includes: ### `excludes` - **Type**: `[]string` -- **Description**: Tasks to exclude from inclusion +- **Description**: Literal task names or namespaces to exclude from inclusion ```yaml includes: shared: taskfile: ./shared.yml - excludes: [internal-setup, debug-only] + excludes: [internal-setup, debug] ``` ### `vars`