Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow multiple commands in a task for loop #1306

Closed
JonZeolla opened this issue Aug 17, 2023 · 3 comments
Closed

Allow multiple commands in a task for loop #1306

JonZeolla opened this issue Aug 17, 2023 · 3 comments

Comments

@JonZeolla
Copy link
Contributor

I would like to be able to specify a list of commands inside of a task for loop.

This is useful if the second cmd relies on an output of the first cmd, but each iteration of the first cmd overwrites prior iterations. This is useful if, for instance, the first cmd loads the example:latest image of platform arm into the local docker daemon, and then the second command execs some tests against it. Because other image platforms would have the same name and tag (in the case of a multiplatform manifest), it would overwrite prior work locally and cause a mismatch when testing.

For example:

---
version: '3'

tasks:
  build:
    cmds:
      - echo 'hit {{.PLATFORM}}'

  example:
    cmds:
      - for:
          var: PLATFORM
          split: ','
          as: platform
        cmds:
          - task: build
            vars:
              PLATFORM: '{{.platform}}'
          - echo 'Do things with platform {{.platform}}'

Expected Output:

$ PLATFORM='arm,amd' task example
task: [build] echo 'hit arm'
hit arm
task: [example] echo 'Do things with platform arm'
Do things with platform arm
task: [build] echo 'hit amd'
hit amd
task: [example] echo 'Do things with platform amd'
Do things with platform amd

Instead you need to do something like:

---
version: '3'

tasks:
  build:
    cmds:
      - echo 'hit {{.PLATFORM}}'

  example:
    cmds:
      - for:
          var: PLATFORM
          split: ','
          as: platform
        task: build
        vars:
          PLATFORM: '{{.platform}}'
      - for:
          var: PLATFORM
          split: ','
          as: platform
        cmd: echo 'Do things with platform {{.platform}}'

Actual Output:

$ PLATFORM='arm,amd' task example
task: [build] echo 'hit arm'
hit arm
task: [build] echo 'hit amd'
hit amd
task: [example] echo 'Do things with platform arm'
Do things with platform arm
task: [example] echo 'Do things with platform amd'
Do things with platform amd

The way I read it this is similar to but different from #1299

@task-bot task-bot added the state: needs triage Waiting to be triaged by a maintainer. label Aug 17, 2023
@pd93
Copy link
Member

pd93 commented Aug 21, 2023

I'm not a huge fan of the multi-nested cmds block (i.e. tasks[].cmds[].for.cmds[]). It makes the Taskfile hard to parse IMO (by both humans and our code). When designing this feature, there were a few ways we could have gone about doing it. The way it is implemented now keeps the YAML as simple and readable as possible and still offers maximum flexibility.

If you need to loop over multiple commands, why not just wrap up your functionality in a separate task? This means that if you ever need to run that set of commands for a single item or a different set of items, then your Taskfile will already support it. e.g.

version: '3'

tasks:
  do-thing-for-all-platforms:
    cmds:
      - for:
          var: PLATFORM
          split: ','
        task: do-thing-for-platform
        vars:
          PLATFORM: {{.ITEM}}
  
  do-thing-for-platform:
    cmds:
      - task: build
        vars:
          PLATFORM: '{{.PLATFORM}}'
      - echo 'Do things with platform {{.PLATFORM}}'

  build:
    cmds:
      - echo 'hit {{.PLATFORM}}'

It's also worth remembering that if you don't want certain tasks to be executable via the CLI, you can add internal: true to the definition.

  do-thing-for-platform:
    internal: true
    cmds:
      - ...

@pd93 pd93 added the state: awaiting response Waiting for issue author to respond. label Aug 21, 2023
@JonZeolla
Copy link
Contributor Author

While I still prefer the former, my workaround was essentially what you showed.

Currently our task files are getting pretty complex. We have a library of different task files for inclusion, indirection points (multiple includes), etc. I like my suggestion better because it reduces the amount of spaghetti - one less task - but this is not a critical item. Thanks!

@task-bot task-bot removed the state: awaiting response Waiting for issue author to respond. label Sep 2, 2023
@pd93
Copy link
Member

pd93 commented Sep 2, 2023

I'm going to decline this for now for the reasons I gave above. for is still pretty new, so I'd like to let some time pass in its current state before we make any changes, but if we see more requests for this kind of feature then its something we can reconsider in the future.

@pd93 pd93 closed this as completed Sep 2, 2023
@task-bot task-bot removed the state: needs triage Waiting to be triaged by a maintainer. label Sep 2, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants