task
task copied to clipboard
Global variables and included taskfile
- 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.
For clarification, your expectation is that root vars take precedence over vars of the same name coming from an include?
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.
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?
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.
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 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.
@aliculPix4D @marco-m-pix4d How did you get on with 3.12? Are you still having issues, or can this be closed?
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 :-)
First sorry for the late reply. I had a look at the issue again.
Here is my summary:
- 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
- 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.
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.