Task variable level overrides no longer work in recent releases
Since upgrading task to latest v3.37.x releases I am seeing variable overrides for included tasks functioning as no-ops. For example, given this task include:
includes:
staging:
taskfile: ./taskfiles/instance.yml
vars:
OSIRIS_ENV: staging
GOOGLE_CLOUD_PROJECT: whatever-staging
BASE_URL: https://api.staging.whatever.com
staging:bastion:
vars:
BASTION_INSTANCE_NAME: whatever-staging-bastion
GOOGLE_CLOUD_PROJECT: whatever-staging
taskfile: ./taskfiles/bastion.yml
The OSIRIS_ENV and GOOGLE_CLOUD_PROJECT remain at their default values rather than the explicitly overridden values.
- Task version: 3.37.2
- Operating system: macOS
- Experiments enabled: No
This is relating to import/included tasks. Where are the default values defined? Variables specified at the inclusion have a fairly low priority: https://taskfile.dev/usage/#variables
My own experiment show that this behavior is not working as expected. Global variables take precedence over variables defined at inclusion.
Taskfile
version: "3"
# should only be used if var not declared _anywhere_ else (BUG)
vars:
FOO: "FUBAR"
includes:
a:
taskfile: ./a/Taskfile.yml
vars:
FOO: "BAR"
b:
taskfile: ./a/Taskfile.yml
vars:
FOO: "RAB"
tasks:
one:
cmds:
- task a:two
- task b:two
a/Taskfile
version: "3"
# overrides variables defined on the inclusion of this Taskfile (OK)
#vars:
# FOO: "FOO"
tasks:
two:
# overrides variables defined on the inclusion of this Taskfile (OK)
# vars:
# FOO: "BAR"
cmds:
- echo {{.FOO}}
$ ~/go/bin/task one task: [one] task a:two task: [a:two] echo FUBAR FUBAR task: [one] task b:two task: [b:two] echo FUBAR FUBAR
I don't think this is covered by the tests (global vars or environment vars). Seems like a bug. But is it the problem you observe?
Yes @trulede, you are correct. These are top-level variables that previously I was able to override at inclusion time. Now the global variables are taking precedence over the variables set at inclusion time.
This is definitely a bug/regression that has been introduced in the last several versions. Task is not honoring the precedence contract described in https://taskfile.dev/usage/#variables
I'm using this tool for the first time now, so I cannot comment on how the behavior was before.
But I think I'm experiencing the same behavior. I have 2 taskfiles (let's call them parent and child). I have some global vars defined at the child, that work as defaults (or at least, that is my goal). At inclusion time, I was expecting to be able to override these defaults from the parent. However, it seems that if I define a global variable on the child I can no longer do that. The documentation states the following:
- Variables declared in the task definition
- Variables given while calling a task from another (See Calling another task above)
- Variables of the included Taskfile (when the task is included)
- Variables of the inclusion of the Taskfile (when the task is included)
- Global variables (those declared in the vars: option in the Taskfile)
- Environment variables
which is consistent with the behavior I'm getting (unfortunately 😅). I'm trying to use point 4, but because point 3 (i.e., the global vars on the child), my override gets undone.
In any case, UX wise, I think it would make more sense for variables overriden at inclusion to have higher priority than the ones defined as global variables.
@blakewatters I believe there is a work-around via the default function. For anything that is to be overridden, you can use:
{{ .var_name | default "default-value" }}
This worked for me:
# Taskfile.yml
version: '3'
includes:
child-with-var:
taskfile: ./Taskfile.child.yml
vars:
VAR: value-from-parent
child-without-var:
taskfile: ./Taskfile.child.yml
tasks:
default:
cmds:
- task: child-with-var
- task: child-without-var
# Taskfile.child.yaml
version: '3'
vars:
VAR: '{{ .VAR | default "value-from-child" }}' # This can get overridden.
tasks:
default: echo {{.VAR}}
Output:
task: [child-with-var:default] echo VAR is value-from-parent
VAR is value-from-parent
task: [child-without-var:default] echo VAR is value-from-child
VAR is value-from-child
Would this resolve your use-case?
I do see this tip here:
Vars declared in the included Taskfile have preference over the variables in the including Taskfile! If you want a variable in an included Taskfile to be overridable, use the default function: MY_VAR: '{{.MY_VAR | default "my-default-value"}}'.
(source)
This does sound like intended behaviour and not a bug. What is good about this approach is that it allows the included file to control which vars can be overridden from the outside and which ones cannot.
Hey @blakewatters,
@pbitty is right. Default is the way to go. You can find a previous issue here, where we discussed the behavior.