go-task / task

A task runner / simpler Make alternative written in Go
https://taskfile.dev
MIT License
11.55k stars 616 forks source link

On `--list`, show tasks in the root Taskfile first #806

Closed deepbrook closed 2 years ago

deepbrook commented 2 years ago

Currently, when running task -l the available tasks are listed alphabetically. While this works for simple taskfiles, in cases with several includes and many compound tasks in the root file, I'd hoped that those tasks defined in the root taskfile are listed first (visually separated by an empty line).

Example: Given two taskfiles to be included:

# taskfile.lib.yaml
---
version: 3
tasks:
  some_task: 
    desc: greet someone
    cmds: ['echo "hello"']
---
# taskfile.tools.yaml
---
version: 3
tasks:
  some_other_task: 
    desc: point somewhere
    cmds: ['echo "there"']
---

The files are included in the root taskfile:

# Taskfile.yaml
version: 3
include:
  lib:
    taskfile: taskfile.lib.yaml
  tools:
    taskfile: taskfile.tools.yaml
tasks:
  main_task:
    desc: do the thing.
    cmds:
      - task: lib:some_task
      - task: tools:some_other_task

The output would currently look like this:

* lib:some_task                    greet someone
* main_task                        do the thing.
* tools:some_other_task            point somewhere

I'm suggesting it should group the tasks like this instead:

* main_task                        do the thing.  # several tasks in the root file can be listed alphabetically again

* lib:some_task                    greet someone
* tools:some_other_task            point somewhere

Alternatively, add an option to include to not list the included tasks, even if they have a desc attribute:

include:
  lib:
    taskfile: taskfile.lib.yaml
    hide: true
  tools:
    taskfile: taskfile.tools.yaml
    hide: true
deepbrook commented 2 years ago

Visually differentiating the included tasks by their prefix would also be neat - i.e. add a newline before each block of tasks with the same prefix. Helpful in bigger compositions, like this one:

🐟 ❯ task -l
task: Available tasks for this project:
* bootstrap:deploy:     Deploy the plan created with `task bootstrap:plan`.
* bootstrap:docs:tf:    Create an updated README.md for the terraform config at deploy/bootstrap.
* bootstrap:plan:       Compile var files and execute a plan action for the bootstrap terraform configuration.
* bootstrap:recover:    Import any resources we can find for the bootstrap module into its Terraform state.
* compile:              Compile input variables for all terraform configuration modules
* docs:                 Create an updated README.md for each of the terraform configs in deploy/
* fmt:                  Format terraform files of configuration modules in deploy/
* gitlab:deploy:        Deploy the plan created with `task gitlab:plan` for $purpose.
* gitlab:docs:tf:       Create an updated README.md for the terraform config at deploy/gitlab.
* gitlab:plan:          Compile var files and execute a plan action for the gitlab terraform configuration and given $purpose.
* gitlab:recover:       Import any resources we can find for the gitlab module into the Terraform state of the given $registry and $.
* harbor:deploy:        Deploy the plan created with `task harbor:plan` for $purpose.
* harbor:docs:tf:       Create an updated README.md for the terraform config at deploy/harbor.
* harbor:plan:          Compile var files and execute a plan action for the harbor terraform configuration and given $purpose.
* harbor:recover:       Import any resources we can find for the harbor module into the Terraform state of the given $purpose and $harbor_group_id.
* ldap:deploy:          Deploy the plan created with `task ldap:plan` for $purpose.
* ldap:docs:tf:         Create an updated README.md for the terraform config at deploy/ldap.
* ldap:plan:            Compile var files and execute a plan action for the ldap terraform configuration and given $purpose.
* ldap:recover:         Import any resources we can find for the ldap module into the Terraform state of the given $purpose.
* opsgenie:deploy:      Deploy the plan created with `task opsgenie:plan` for $purpose.
* opsgenie:docs:tf:     Create an updated README.md for the terraform config at deploy/opsgenie.
* opsgenie:plan:        Compile var files and execute a plan action for the opsgenie terraform configuration and given $purpose.
* opsgenie:recover:     Import any resources we can find for the opsgenie module into the Terraform state of the given $purpose.
* registry:deploy:      Deploy the plan created with `task registry:plan`.
* registry:docs:tf:     Create an updated README.md for the terraform config at deploy/registry.
* registry:plan:        Compile var files and execute a plan action for the registry terraform configuration.
* registry:recover:     Import any resources we can find for the registry module into its Terraform state.
* validate:             Validate all terraform configuration modules in deploy/ using `terraform validate`
andreynering commented 2 years ago

Hi @deepbrook, thanks for opening this issue.

I'm not a fan of the hide: true idea.

I'm also not sure about having empty lines between groups. At minimum it would break the current completion scripts which use the outputs of --list and --list-all.

That said, moving all tasks in the root Taskfile to the top makes sense!

deepbrook commented 2 years ago

You know how they asay: if you need 5$, ask for 10$ ;D Thanks for your consideration.

ynachi commented 2 years ago

Hello @andreynering , I am very interrested working on this issue. I am entering the opensource contribution space and would also like to shape my Go skills. Do you mind assigning it to me ?

Also, to be sure I understood what to do, at the end, we want to display the tasks in the root first and display the rest later. If this is the case, I would like to put something that make the separation beteween the root tasks and imported one to avoid confusion. Something like:

task: Available tasks for this project:
root tasks:
* bootstrap:deploy:     Deploy the plan created with `task bootstrap:plan`.
* bootstrap:docs:tf:    Create an updated README.md for the terraform config at deploy/bootstrap.
* bootstrap:plan:       Compile var files and execute a plan action for the bootstrap terraform configuration.

imported tasks:
* bootstrap:recover:    Import any resources we can find for the bootstrap module into its Terraform state.
* compile:              Compile input variables for all terraform configuration modules
* docs:                 Create an updated README.md for each of the terraform configs in deploy/
* fmt:                  Format terraform files of configuration modules in deploy/
* gitlab:deploy:        Deploy the plan created with `task gitlab:plan` for $purpose.
* gitlab:docs:tf:       Create an updated README.md for the terraform config at deploy/gitlab.
* gitlab:plan:          Compile var files and execute a plan action for the gitlab terraform configuration and given $purpose.
* gitlab:recover:       Import any resources we can find for the gitlab module into the Terraform state of the given $registry and $.
* harbor:deploy:        Deploy the plan created with `task harbor:plan` for $purpose.

Thanks

andreynering commented 2 years ago

Hi @ynachi,

Sure, just assigned it to you.

I'm not a fan of the separation necessarily, and as I said before, I fear that it would break the current completion scripts, so I would avoid it.

I'm opening to hear opinions if someone disagree, but I would just change the sorting of the tasks.

Perhaps sorting by tasks without an : first would be enough to do the trick (sorting alphabetically as the second order, of course).

ynachi commented 2 years ago

Thanks. Ok let’s do the sorting part for now.

MarioSchwalbe commented 2 years ago

About hiding tasks. A more flexible solution would be to automatically hide tasks whose desc: expands to the empty string. This way one could pass a variable at the include site to selectively hide all or a selection of tasks. Currently this is not possible, because tasks with empty descriptions are shown:

# Taskfile.yml
version: '3'

vars:
  HIDE: yes

tasks:
  SomeTask:
    desc: '{{ if not .HIDE }}SomeTask{{ end }}'
    cmds:
      - echo Boom

Test:

$ task -l
task: Available tasks for this project:
* SomeTask:     
$ task foo
task: Available tasks for this project:
* SomeTask:     
task: Task "foo" not found
deepbrook commented 2 years ago

As far as I can tell, the internal: true flag for includes takes care of hiding tasks which are not meant for end-user execution (and also hides the tasks from the --list option. So, this issue can be closed imo.

pd93 commented 2 years ago

I think there is still value here. internal: true solves the case where your included Taskfile only contains utilities, but if I have a separate Taskfile for docs (like the Taskfile repo itself has), then sorting with the root Taskfile's tasks first still makes sense.

pd93 commented 2 years ago

@deepbrook FYI, I've posted #890, which (among other things) will fix this issue.