task icon indicating copy to clipboard operation
task copied to clipboard

Global variables and included taskfile

Open aliculPix4D opened this issue 2 years ago • 6 comments

  • Task version: v3.9.0
  • Operating System: ubuntu 20.04

Very similar issue: https://github.com/go-task/task/issues/618

Hi, first thank you for the great tool. I would like to report what my team and I consider a bug (unexpected behavior) and to check your opinion on the topic.

Consider the following setup:

  • first Taskfile in the root directory: Taskfile.yml
version: '3'

includes:
  imported: import/Taskfile.yml

vars:
  custom_value: root

tasks:
  print_var:
    cmds:
      - echo {{.custom_value}}
  • second in the sub directory: import and included from the root Taskfile
version: '3'

vars:
  custom_value: included

tasks:
  print_var:
    cmds:
      - echo {{.custom_value}}

Running the following commands:

>  task imported:print_var
task: [imported:print_var] echo included
included
> task print_var  
task: [print_var] echo included
included

While our expectation were more in line with the following:

>  task imported:print_var
task: [imported:print_var] echo included
included
> task print_var  
task: [print_var] echo root
root

where the root task would print the value set in root Taskfile.

Thanks for looking at this issue.

aliculPix4D avatar Apr 01 '22 09:04 aliculPix4D

For clarification, your expectation is that root vars take precedence over vars of the same name coming from an include?

ghostsquad avatar Apr 01 '22 15:04 ghostsquad

Try upgrading to 3.12 and check out this part of the docs:

https://taskfile.dev/#/usage?id=vars-of-included-taskfiles

See if that helps.

ghostsquad avatar Apr 01 '22 15:04 ghostsquad

For clarification, your expectation is that root vars take precedence over vars of the same name coming from an include?

Yes, I did not expect that variable custom_value: root configured in root Taskfile (the one that include all others) will be ignored just because some other included Taskfile had the variable with the same name configured.

Try upgrading to 3.12 and check out this part of the docs

Yes, we are aware of this new feature in 3.12 but it seems as a workaround for the real issue, hence we wanted to first check if the above is wanted behavior or do you consider it as a bug as we do?

aliculPix4D avatar Apr 04 '22 06:04 aliculPix4D

it seems as a workaround for the real issue, hence we wanted to first check if the above is wanted behavior or do you consider it as a bug as we do?

This is not a bug. It was a conscious design decision.

The reason why is that the goal is to allow you to essentially use included task files like composable pieces. Being able to create multiple namespaces and such using the same file (via an include).

The style guide and other documentation likely should be updated to show some examples and specific scenarios that you may encounter, and how best to structure your Taskfile's.

ghostsquad avatar Apr 05 '22 02:04 ghostsquad

But I don't want to leave you hanging with this answer. The examples in your original post, though very good minimal reproducible example files, don't demonstrate the use case you have. Would you mind providing more detailed information on your use case, and I can help guide you to a working solution/pattern?

ghostsquad avatar Apr 05 '22 03:04 ghostsquad

@ghostsquad thanks for your help! I am in the same team as @aliculPix4D and we are using a fork I did to fix a problem with signal propagation to subprocesses (see #479). At this point, I think it makes more sense for us to upgrade the fork to 3.12 (given the changes in var handling you mention) and then continue this discussion.

marco-m-pix4d avatar Apr 05 '22 07:04 marco-m-pix4d

@aliculPix4D @marco-m-pix4d How did you get on with 3.12? Are you still having issues, or can this be closed?

pd93 avatar Oct 15 '22 03:10 pd93

hello @pd93, we switched to using Task upstream (as opposed to our fork), because Task handles signal propagation better since 3.13.

Regarding this specific issue, @aliculPix4D could you please confirm wether we are still seeing this behavior, and if yes, would it be possible to "demostrate the use case we have" as requested in https://github.com/go-task/task/issues/696#issuecomment-1088218088 ? Thanks :-)

marco-m-pix4d avatar Oct 24 '22 07:10 marco-m-pix4d

First sorry for the late reply. I had a look at the issue again.

Here is my summary:

  1. We don't see this issue anymore in our case because we have implemented a workaround:
  • in local tests and pre-commit hook we ensure that sub task files (the one not in the root of the repository) do not declare variables
  • the consequence of our workaround is that no sub task file can be run independently on its own and we must run task from repository root
  1. going back to the Task examples given in this issue and our use cases.

Looking at: https://taskfile.dev/usage/#vars-of-included-taskfiles and trying to modifing my examples above to implement suggestions from documentation (using Task v3.17.0):

root Taskfile content:

version: '3'

includes:
  imported:
    taskfile: ./imported/Taskfile.yml
    vars:
      custom_value: included-root

vars:
  custom_value: root

tasks:
  print_var:
    cmds:
      - echo {{.custom_value}}

imported Taskfile content

version: '3'

vars:
  custom_value: included

tasks:
  print_var:
    cmds:
      - echo {{.custom_value}}
(Example 1:) This is problematic because root Task file and all other includes would use the variable value 
from the first included Taskfile.
➜  (from root)task print_var         
task: [print_var] echo included # should be 'echo root'
included # should be root

(Example 2:)  This is fine. From the root the variable is overridden
➜  (from root) task imported:print_var
task: [imported:print_var] echo included-root
included-root

(Example 3:)  This is fine because it enables you to run your sub Taskfile independently with its own 
variables.
➜  cd imported           
➜  (from imported) task print_var 
task: [print_var] echo included
included

which in my opinion even further shows that this ticket is needed and that the behavior described in the issue should be a bug and not a wanted behavior.

Why?

  • we should be able to run each sub Taskfile independently with only this Taskfile ( see Example 3)
  • we should be able to run each sub Taskfile from the root Taskfile ( see Example 2) and override only the variables that we want
  • the root Taskfile (and other sub Taskfiles, if you import more than 1) should use the values of variables declared in root file and not the default value of a variable loaded from the first include.

Our use case is not much different than these simple examples with echo. We use Task to drive our terraform deployments working with multiple workspaces and modules. We noticed the issue because we had the same variable TERRAFORM_CMD= aws-vault exec ... -- terraform` declared in two different files and the root one was always inheriting the value from first (or last?; I don't remember well) included Taskfile and not the root one.

aliculPix4D avatar Oct 31 '22 11:10 aliculPix4D

We're facing a similar issue.

The idea is to have a reusable Taskfile with a configurable version of a command line tool. In this example, a docker image tag is to be configured.

Taskfile.yaml includes Taskfile_docker.yaml and overrides the TAG variable with a bookworm value. Taskfile_docker.yaml uses the TAG variable to build another variable — CMD, which represents the final command to run. If TAG is not provided, the latest value is taken by default.

Unfortunately, it seems like Taskfile evaluates global variables in the included file independently from any variables provided by the including file.

# Taskfile.yaml
version: '3'

includes:
  docker:
    taskfile: Taskfile_docker.yaml
    vars:
      TAG: bookworm
# Taskfile_docker.yaml
version: '3'

vars:
  TAG: '{{.TAG|default "latest"}}'
  CMD: 'docker run debian:{{.TAG}}'

tasks:
  test:
    cmds:
      - '{{.CMD}}} echo "{{.TAG}}"'
❯ task docker:test
task: [docker:test] docker run debian:latest echo "bookworm"
bookworm

Notice debian:latest in the output instead of the desired debian:bookworm.

A workaround for this issue is to use environment variables in the root Taskfile to override variables in included Taskfiles. But this doesn't allow to override of a variable with different values in different included Taskfiles.

# Taskfile.yaml
version: '3'

env:
  TAG: bookworm

includes:
  docker: Taskfile_docker.yaml

Taskfile_docker.yaml stays the same.

❯ task docker:test
task: [docker:test] docker run debian:bookworm echo "bookworm"
bookworm

Notice debian:bookworm in the output.

Zebradil avatar Nov 29 '22 17:11 Zebradil