go-task / task

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

Grouped output with GitHub Actions friendly begin/end markers #647

Closed janslow closed 2 years ago

janslow commented 2 years ago

Hi, thanks for the awesome project!

I was wondering if you'd consider supporting a variant of the group output, but also emitting a ::group::$TASK line before the group and ::endgroup:: after it, so that GitHub Actions will group all the output for a single task and allow it to be collapsed.

For example, if there's a Taskfile like this:

# Taskfile.yml
output: github_actions
tasks:
  default:
    cmds:
      - "echo 'Hello, World!'"

I'd expect task default to emit the following:

::group::default
Hello, World!
::endgroup::

Alternatively (as a non GitHub Actions-specific solution), adding support for custom begin/end markers, e.g.,

# Taskfile.yml
output:
  group:
    begin: '::group::%s'
    end: '::endgroup::'

I'm happy to put together a PR for this, if you'd consider reviewing it.

kerma commented 2 years ago

Thanks for the report @janslow ! Can you provide a more complex example where the same could not be achieved with just echoing the required output in the commands list?

tasks:
  default:
    cmds:
      - echo "::group::default"
      - "echo 'Hello, World!'"
      - echo "::endgroup::"

Any reason why this won't work?

janslow commented 2 years ago

Any reason why this won't work?

Mainly because you'd only want this behaviour when running in CI (e.g., I currently set --output=group in CI, because I want interleaved when running locally).

Additionally, it's going to make the tasks much more complex (because there's build and output logic mixed together) and (on larger taskfiles) a developer could forget to add one/both of those commands (unless there was a way to add pre/post commands to every job).

kerma commented 2 years ago

I usually separate CI specific tasks on into it's own group and add the necessary env, vars and other logic there. So a cli user would call a task default, but in CI task ci:default will be called. In GHA I'm currently doing something like:


tasks:
  default:
    vars:
       TAG:
          sh: "git log -n 1 --format=%h"
    cmds:
      - echo 'Hello, {{ .TAG }}'

  ci:default:
    cmds:
      - echo "::group::default"
      - task: default
         vars:
            TAG: 
              sh: echo "$GITHUB_SHA"
      - echo "::endgroup::" 
janslow commented 2 years ago

That seems like it would prevent the use of Task dependencies and other features of Taskfile.

For example,

tasks:
  default:
    vars:
       TAG:
          sh: "git log -n 1 --format=%h"
    deps:
      - prerequisites
    cmds:
      - echo 'Hello, {{ .TAG }}'
  prerequisites:
    cmds:
      - echo 'Downloading Prerequisites'
  ci:default:
    env:
       TAG:
          sh: echo "$GITHUB_SHA"
    cmds:
      - echo "::group::default"
      - task: default
         vars:
            TAG: 
              sh: echo "$GITHUB_SHA"
      - echo "::endgroup::" 

Would output:

::group::default
Downloading Prerequisites
Hello, 1.2.3
::endgroup::

Rather than:

::group::prerequisites
Downloading Prerequisites
::endgroup::
::group::default
Hello, 1.2.3
::endgroup::

It seems like you'd need to have two independent taskfiles to use this approach.

I probably didn't make it clear enough originally, but I want it to be clear in GitHub actions which task the output has come from

andreynering commented 2 years ago

Hi @janslow,

I didn't know GitHub Actions had this feature. Do other CI systems support something similar as well?

I think I like the idea of having this possibility. Not specifically to GitHub Actions but customizable to potentially include other use cases as well, as you suggested:

output:
  group:
    begin: '::group::{{.TASK}}'
    end: '::endgroup::'

In theory this would not be complex to implement, and I'd say a PR is welcome.

janslow commented 2 years ago

Do other CI systems support something similar as well?

Azure Devops supports ##[group] Message and ##[endgroup], but I'm not sure of any others

In theory this would not be complex to implement, and I'd say a PR is welcome.

Ok, I'll hopefully have a PR together soon.

@andreynering, for the CLI's --output flag, would you prefer:

a) Use the existing --output flag and encode the begin/end template in the value (e.g., task --output="group|::group::{{ .TASK }}|::endgroup::") b) Additional flags (e.g., task --output=group --output-group-begin="::group::{{ .TASK }}" --output-group-end="::endgroup::") c) Accept the serialized YAML in the --output flag (e.g., --output='{"group": {"begin": "::group::{{ .TASK }}", "end": "::endgroup::" } }'

(I can't see any other existing patterns for complex CLI options in the codebase atm)

andreynering commented 2 years ago

I like separated CLI arguments (option B) better.

Porges commented 2 years ago

Is there any way to have prefixed be the default but override it on commandline? At the moment this doesn't seem to work. I'd like prefixed for local dev and group in CI.

andreynering commented 2 years ago

@Porges Isn't the --output flag working for this?

https://taskfile.dev/api/#cli