From 6f8f1f1409d8416892623da376e70425cb52817e Mon Sep 17 00:00:00 2001 From: Pete Davison Date: Fri, 22 Jul 2022 02:15:35 +0000 Subject: [PATCH] feat(task): tasks can be internal (not accessible from cli) --- errors.go | 8 ++++++ help.go | 6 +++-- task.go | 7 ++++- task_test.go | 40 +++++++++++++++++++++++++++++ taskfile/task.go | 3 +++ testdata/internal_task/Taskfile.yml | 16 ++++++++++++ variables.go | 1 + 7 files changed, 78 insertions(+), 3 deletions(-) create mode 100644 testdata/internal_task/Taskfile.yml diff --git a/errors.go b/errors.go index e13ad9b3..14f3faee 100644 --- a/errors.go +++ b/errors.go @@ -20,6 +20,14 @@ func (err *taskNotFoundError) Error() string { return fmt.Sprintf(`task: Task "%s" not found`, err.taskName) } +type taskInternalError struct { + taskName string +} + +func (err *taskInternalError) Error() string { + return fmt.Sprintf(`task: Task "%s" is internal`, err.taskName) +} + type TaskRunError struct { taskName string err error diff --git a/help.go b/help.go index 0dc99718..c4b7ea47 100644 --- a/help.go +++ b/help.go @@ -52,7 +52,9 @@ func (e *Executor) printTasks(listAll bool) { func (e *Executor) allTaskNames() (tasks []*taskfile.Task) { tasks = make([]*taskfile.Task, 0, len(e.Taskfile.Tasks)) for _, task := range e.Taskfile.Tasks { - tasks = append(tasks, task) + if !task.Internal { + tasks = append(tasks, task) + } } sort.Slice(tasks, func(i, j int) bool { return tasks[i].Task < tasks[j].Task }) return @@ -61,7 +63,7 @@ func (e *Executor) allTaskNames() (tasks []*taskfile.Task) { func (e *Executor) tasksWithDesc() (tasks []*taskfile.Task) { tasks = make([]*taskfile.Task, 0, len(e.Taskfile.Tasks)) for _, task := range e.Taskfile.Tasks { - if task.Desc != "" { + if !task.Internal && task.Desc != "" { compiledTask, err := e.FastCompiledTask(taskfile.Call{Task: task.Task}) if err == nil { task = compiledTask diff --git a/task.go b/task.go index 90991c30..108cc775 100644 --- a/task.go +++ b/task.go @@ -64,11 +64,16 @@ type Executor struct { func (e *Executor) Run(ctx context.Context, calls ...taskfile.Call) error { // check if given tasks exist for _, c := range calls { - if _, ok := e.Taskfile.Tasks[c.Task]; !ok { + t, ok := e.Taskfile.Tasks[c.Task] + if !ok { // FIXME: move to the main package e.ListTasksWithDesc() return &taskNotFoundError{taskName: c.Task} } + if t.Internal { + e.ListTasksWithDesc() + return &taskInternalError{taskName: c.Task} + } } if e.Summary { diff --git a/task_test.go b/task_test.go index 216e3968..4c252067 100644 --- a/task_test.go +++ b/task_test.go @@ -929,6 +929,46 @@ func TestIncludesRelativePath(t *testing.T) { assert.Contains(t, buff.String(), "testdata/includes_rel_path/common") } +func TestInternalTask(t *testing.T) { + const dir = "testdata/internal_task" + tests := []struct { + name string + task string + expectedErr bool + expectedOutput string + }{ + {"internal task via task", "task-1", false, "Hello, World!\n"}, + {"internal task via dep", "task-2", false, "Hello, World!\n"}, + { + "internal direct", + "task-3", + true, + "task: No tasks with description available. Try --list-all to list all tasks\n", + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + var buff bytes.Buffer + e := task.Executor{ + Dir: dir, + Stdout: &buff, + Stderr: &buff, + Silent: true, + } + assert.NoError(t, e.Setup()) + + err := e.Run(context.Background(), taskfile.Call{Task: test.task}) + if test.expectedErr { + assert.Error(t, err, test.expectedErr) + } else { + assert.NoError(t, err) + } + assert.Equal(t, test.expectedOutput, buff.String()) + }) + } +} + func TestSupportedFileNames(t *testing.T) { fileNames := []string{ "Taskfile.yml", diff --git a/taskfile/task.go b/taskfile/task.go index 12484f0b..e13b8169 100644 --- a/taskfile/task.go +++ b/taskfile/task.go @@ -20,6 +20,7 @@ type Task struct { Env *Vars Silent bool Interactive bool + Internal bool Method string Prefix string IgnoreError bool @@ -63,6 +64,7 @@ func (t *Task) UnmarshalYAML(unmarshal func(interface{}) error) error { Env *Vars Silent bool Interactive bool + Internal bool Method string Prefix string IgnoreError bool `yaml:"ignore_error"` @@ -85,6 +87,7 @@ func (t *Task) UnmarshalYAML(unmarshal func(interface{}) error) error { t.Env = task.Env t.Silent = task.Silent t.Interactive = task.Interactive + t.Internal = task.Internal t.Method = task.Method t.Prefix = task.Prefix t.IgnoreError = task.IgnoreError diff --git a/testdata/internal_task/Taskfile.yml b/testdata/internal_task/Taskfile.yml new file mode 100644 index 00000000..8317cdaa --- /dev/null +++ b/testdata/internal_task/Taskfile.yml @@ -0,0 +1,16 @@ +version: '3' + +tasks: + + task-1: + cmds: + - task: task-3 + + task-2: + deps: + - task-3 + + task-3: + internal: true + cmds: + - echo "Hello, World!" diff --git a/variables.go b/variables.go index 80a232a3..fd2124f0 100644 --- a/variables.go +++ b/variables.go @@ -57,6 +57,7 @@ func (e *Executor) compiledTask(call taskfile.Call, evaluateShVars bool) (*taskf Env: nil, Silent: origTask.Silent, Interactive: origTask.Interactive, + Internal: origTask.Internal, Method: r.Replace(origTask.Method), Prefix: r.Replace(origTask.Prefix), IgnoreError: origTask.IgnoreError,