task icon indicating copy to clipboard operation
task copied to clipboard

Vars are not interpolated before deps in a task

Open weeping-somnambulist opened this issue 3 years ago • 7 comments

  • Task version: 3.6.0
  • Operating System: OpenSUSE Tumbleweed

I believe this is a bug as it is not expected behavior from a user's point of view. Variables that use the shell function, e.g. sh: foo, run before the dependencies in a task. This is, in my opinion, not the expected behavior for the user and is undesirable for most use cases, as it prevents information from being passed from the depended task to the dependent task.

I am trying to pass information from a dependency to a task. I need the dependency to generate a container image ID then use that image ID for subsequent tasks. It should be noted that not all tasks in this Taskfile create a container image, so this is not something that I would prefer to do globally.

If there is a better way to solve this problem please let me know.

Example Taskfile showing the issue

version: '3'

tasks:

  generate-bar:
    cmds:
      - echo foo > bar
    generates:
      - bar

  default:
    deps: [generate-bar]
    vars:
      BAZ:
        sh: cat bar 
    cmds:
      - echo {{.BAZ}}

Output

> task                        
cat: bar: No such file or directory
task: Command "cat bar" failed: exit status 1

weeping-somnambulist avatar Jul 28 '21 20:07 weeping-somnambulist

Hi @SwitchedToGitlab,

This is a side-effect of how caching of variables work, and it's not trivial to fix, specially without introducing breaking changes.

I'll keep this open for consideration if we have another vars refactor in the future.

andreynering avatar Jul 31 '21 23:07 andreynering

So the issue that I'm having is that I effectively cannot pass information from one task to another using any method. Is there any way to pass information from one task to another? If there is I don't see it, and to me that's a critical flaw in design if I may say so.

My specific use case is that I am building a container image with Buildah and Task, and I need the container's image ID to run operations on it, such as mounting it's file system and working with binaries installed on the container. As it stands I have no way to instantiate the container and then pass the ID to a task. The only way that I have to do this is to instantiate a container as a global var using SH, but this is less than ideal as it creates a container for every operation whether it's needed or not.

Thoughts? I'm of the opinion that the functionality detailed in this issue is critical if Task is going to replace Make.

weeping-somnambulist avatar Aug 03 '21 23:08 weeping-somnambulist

Are you defining the var on the called task? If so i think you want to take that out.

I find the order of preference to interpolation confusing. It feels like defining a var at the task level ought to behave as a default, but I think actually will override anything you try to pass through.

Eg

tasks:
  caller:
    cmds:
      - task: callee
        vars:
          MY_VAR: fizz

  callee:
    vars:
      MY_VAR: this will block the caller's value!
    cmds:
      - echo {{.MY_VAR}}

amancevice avatar Aug 03 '21 23:08 amancevice

However if you echo {{.MY_VAR}} from the caller task it returns nothing. No information is passed between the two tasks in your example.

version: '3'

tasks:
  caller:
    cmds:
      - task: callee
        vars:
          MY_VAR: fizz
      - echo {{.MY_VAR}}
      
  callee:
    vars:
      MY_VAR: this will block the callers value!
    cmds:
      - echo {{.MY_VAR}}

Output

⌬  task caller
task: [callee] echo this will block the callers value!
this will block the callers value!
task: [caller] echo 

weeping-somnambulist avatar Aug 03 '21 23:08 weeping-somnambulist

Ah yeah that makes sense! That would be a nice feature. What I have done in this case is use files to hold the value:


tasks:
  caller:
    cmds:
      - "jq -n '{ fizz: "buzz" }' > fizz.json"
      - task: callee
        vars:
          MY_VAR:$(jq . fizz.json)
      
  callee:
    cmds:
      - echo {{.MY_VAR}}

amancevice avatar Aug 04 '21 00:08 amancevice

@andreynering what about introducing a new VAR type, maybe called LateBindVars? Basically, wait to evaluate the value until absolutely necessary?

I'm not sure how this would interact with regular vars. Or if regular vars could depend on LateBindVars.

ghostsquad avatar Jan 02 '22 19:01 ghostsquad

Lazy vars in v4 would solve this problem (see #703)

ghostsquad avatar Apr 27 '22 03:04 ghostsquad