go-task / task

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

Add ability to register output of a task and make it available in templates context #1449

Open iilyak opened 9 months ago

iilyak commented 9 months ago

rash-sh allows passing arbitrary values from one task to another one via register (see here)

tasks:
  sources:
    cmds:
      - sh: find . -type f -name '*.c'
  mytask:
    cmds:
      - task: sources
        register: sources_result
      - echo discovered files {{ .sources.output }}
      - echo stderr {{ .sources.extra.stderr }}
      - echo return code {{ .sources.extra.return_code }}

Starting from the above we can go further and allow multiple named returns

  sources:
    cmds:
      - sh: find . -type f -name '*.c'
         register: c_sources
      - sh: find . -type f -name '*.cpp'
         register: cpp_sources
      - sh: find . -type f -name '*.h'
         register: h_sources
    register:
         sources: # the result would be flattened (concatenation of lists) 
            - c_sources
            - cpp_sources
         headers: h_sources

  mytask:
    cmds:
      - task: sources
        register:
           inputs: sources
           headers: headers
           rc: _rc # assume we always register return code in `_rc` output
           sterr: _stderr # assume we always register return code in `_stderr` output
      - echo discovered files {{ .inputs }}
      - echo header files {{ .headers }}
      - echo stderr {{ .stderr }}
      - echo return code {{ .rc }}

This design has sufficient level of indirection to avoid any name collisions. Also it doesn't pollute the global namespace.

thetanil commented 9 months ago

register is also supported in Ansible. you use it not just for templates context, but for conditionals in the task itself using when: and probably others.

example from ansible docs

- hosts: web_servers

  tasks:

     - name: Run a shell command and register its output as a variable
       ansible.builtin.shell: /usr/bin/foo
       register: foo_result
       ignore_errors: true

     - name: Run a shell command using output of the previous task
       ansible.builtin.shell: /usr/bin/bar
       when: foo_result.rc == 5

The struct for vars created with register are kind of complex in a way which I'm not a huge fan of, but exit status (registered_var.rc) and stdout separate from stderr is very useful.