task
task copied to clipboard
Improve how we handle ENV priority (OS vs. .env files vs. Taskfile ENVs). Have a setting or this?
I find it very difficult to use task, as I cannot override environment variables if they are declared in the user's shell beforehand. Here's an example:
version: "3"
tasks:
ham:
env:
HAM: "ham"
cmds:
- echo "$HAM"
at 17:31:04 ❯ t ham
task: [ham] echo "$HAM"
ham
at 17:31:06 ❯ HAM=BONE t ham
task: [ham] echo "$HAM"
BONE
I know this has been posted before, even probably by me. The use of VAR
is not really a good workaround because specifically the commands I'm running are expecting an environment variable, not a command line parameter.
I understand this is a backwards incompatible change, so if there was a top-level set of "feature flags" that I could enable/disable to control behavior, that would be useful.
Hi @ghostsquad,
I feel your frustration and I'm open to discuss changes to how we do this. Probably the ideal scenario would be to have some kind of setting, for which we would flip the default value only on v4, for backwards compatibility as you mentioned.
We currently have multiple levels of ENVs:
- OS environment
- .env files
- Taskfile global ENVs
- Task specific ENVs
So we need to think in a way that make it easy for the users to understand how it works, and if we have a setting, what that would change exactly.
Currently, we follow the priority as the list above. That's kinda a convention between different tools out there. For example: .env libs usually don't override existing ENVs from the OS, and Task follows that.
On the other hand, if we inverted the priority list above, it'd make it more consistent with how variable work currently, where something like FOO: '{{.FOO | default "bar"}}'
is required if the user want the variable to be overridable.
I'm more than open for opinion so we can make a plan. 🙂
As a workaround, while we don't improve it, you need to call commands like this currently:
env FOO=bar echo $FOO
Basically making it part the command itself.
As a workaround, while we don't improve it, you need to call commands like this currently:
env FOO=bar echo $FOO
Basically making it part the command itself.
This is very redundant, and I prefer not to do this. Especially when there are many ENV vars, and when ENV vars need to be passed from task to task.
Regarding order of priority, least specific to most specific, similar to Make. In this way, Task specific ENVs take highest priority.
Sometimes I think of tasks as functions, and it does seem to make more programatic sense to have the order of priority be least specific to most specific. Like the scoping of vars as if you were writing some javascript
var msg = "global"
function scope() {
var msg = "scoped"
console.log(msg) // "scoped"
}
scope()
console.log(msg) // "global"
I expect the task env to override the shell environment variables. The current behaviour is confusing.
I expect the task env to override the shell environment variables. The current behaviour is confusing.
I agree. If you need access to the shell environment, there's always the function from slim sprig {{ env }}
.
I believe there are use-case for both, perhaps a suggest:
- have a default priority
- allow overriding the priority list per task, and globally
version: v4
priority:
- os
- taskfile
- .env
env:
HELLO: "good morning"
task:
run:
priority:
- taskfile
- os
- .env
cmd:
- echo: "$HELLO"
start:
cmd:
- echo: "$HELLO"
running:
export HELLO="good afternoon"
task run # -> prints "good morning"
task start # -> prints "good afternoon"
+1
Make
I think does this correctly. Each variable defines it's own behavior.
# https://www.gnu.org/software/make/manual/html_node/Immediate-Assignment.html
FOO = bar
# https://www.gnu.org/software/make/manual/html_node/Conditional-Assignment.html
FOO ?= bar
# https://www.gnu.org/software/make/manual/html_node/Simple-Assignment.html
FOO := bar
# https://www.gnu.org/software/make/manual/html_node/Recursive-Assignment.html
foo = $(bar)
bar = $(ugh)
ugh = Huh?
In this case, each variable itself is in control of this decision.
The next problem is that Task
is becoming exceedingly verbose as compared to Make
. In some ways, this is fine (this is similar to Golang), but in other ways, it also creates a ton of boilerplate. The ideal is a balance between explicit, easy to read, and cryptically sparse.
I expect the task env to override the shell environment variables. The current behaviour is confusing.
Funny, as of 3.2 I'm seeing the opposite, envs and vars set in the taskfiles are always taking priority and this is exactly the behaviour I want to get away from. I'd expect the taskfiles to define some defaults which users can then override with OS level env vars or .env
files.
I can't imagine any situation where user can't redefine and set variables when running a task. My team have evaluated task
on a project and we're going back to Makefiles due to this inflexibility with being able to have overridable defaults
Hey @benc-uk, have you tried the default
template function? That's how we usually suggest to handle it considering how Task work today.
tasks:
echo:
vars:
MESSAGE: '{{.MESSAGE | default "my default message"}}'
cmds:
- echo "{{.MESSAGE}}"
Cool that helps, it's a little verbose but works for now
Hopefully v4 brings some changes in this area