Sharing `just` arguments between invocations
In a previous version --command-color was added to allow coloring the command that is run in the stdout output. This works well but it not transferred to inner calls to just:
inner arg:
just something {{ arg }}
something arg:
echo {{Â arg }}
just --color-command red inner "I am a teapot"
just something "I am a teapot" # <--- colored red
echo "I am a teapot" # <--- not colored red
I am a teapot
Looking at the manual, this is not something that is easily done right now. It can also cause problems with --yes: top level recipes will be automatically confirmed but not inner ones
I see at leastfour possible solutions:
- Allow configuring just through individual env vars: e.g,
JUST_CONFIRM="yes"orJUST_COMMAND_COLOR="red"which would be automatically read - Allow configuring just through a single env vars:
JUST_EXTRA_ARGS="--yes --command-color red"which would be automatically read - Add a function to inherit args in inner commands:
just just_args() something ...in the recipe above - Add a setting to inherit args in inner commands:
set inherit-just-args := true
I'm unsure which is the best. The env vars solutions will make it easy to share arguments, for example in CI scripts but could be surprising (maybe a log at the start, saying "using ... from env" ?). It's already something done by lots of programs though, so I don't think that's too bad.
Solutions 3 and 4 have the issue that they need to be set in each Justfile to work, which will be frustrating when adding a new one in a subdirectory for example. Solution 3 especially needs to be set on each invocation, which is quite invasive but offers lots of control.
- Allow configuring just through individual env vars: e.g,
JUST_CONFIRM="yes"orJUST_COMMAND_COLOR="red"which would be automatically read
+1 to this approach and it'd be consistent with existing behavior.
In the case of --command-color, if it would also set the hypothetical JUST_COMMAND_COLOR env var, this would solve https://github.com/casey/just/issues/1702 as a side effect. Given the rationale why --command-color was added, it anyway seems wise to have --command-color inherited by default.
Oh I didn't know about JUST_UNSTABLE, that is certainly a good point for solution 1, thanks!
I think that some combination of environment variables, and a setting, might be a good approach here. Automatically exporting and inheriting arguments would break backwards compatibility, so a setting would be necessary so that users can opt-in on a per-justfile basis. For example, if users used just --yes on the parent invocation, changing child invocations to behave as if --yes was set would be a change in behavior.
So, if something like set inherit were used, just would automatically export some subset of environment variables, and then child just processes would read them. The setting could be in parent justfiles, with something like set export-args, or in children, with something like set inherit-args.
This setting can be initially made unstable, so that we can tweak which settings are exported. I suspect that there might be some tricky edge cases.
I think that something like --yes or --quiet would be good to start with. The environment variable names should match the argument names, so for --yes, the environment variable would be called JUST_YES, and any value other than the empty string would be interpreted as true.
I labeled this as a good first issue, in case anyone wants to take a crack at it.
I'm starting to take a look at this and I have a question: should the setting be "global" set export-args-as-env := true or precise set-export-args-as-env := ["JUST_YES", "JUST_COLOR"] ? Or both maybe ?
or precise
set-export-args-as-env := ["JUST_YES", "JUST_COLOR"]?
:+1: Nice idea. +1 for the precise proposal. This syntax is intrinsically backwards-compatible with future additions to exported/exportable arguments, and it provides more functionality for justfile authors.
I think naming the setting export-args as casey proposed above would be equally clear while also being more concise.
I like the idea of explicitly specifying what you want to export. There's already a set export, so another name is probably better. And there are things other than args, like settings, which we want to export, so export-args isn't great.
An idea that might dovetail with this:
Add a function just() which is sugar for (just_executable() + ' --justfile ' + justfile() + ' ' + just_options() + ' -- ')
where just_options() returns the options passed in to the current invocation.
Then I can recurse with
recurse:
{{ just() }} recurse
while ensuring that
- No
PATHchange in the shell stopped me from invoking the binary, or invoked a different version - An override of the working directory is preserved
- Any other non-recipe args are preserved, including
--setoverrides.
Having written this out, I realize it sounds a lot like $(MAKE) and $(MAKEFLAGS), with the confusion that entails. But it may be an alternative to forwarding options through the environment.
That's another option but it has a problem: in a CI environment, it's easier to export JUST_YES=1; export JUST_COLOR=always and all present and future just calls will work on the first try as expected, whereas the {{ just() }} option means each new just call in the CI needs the arguments copied, which I don't think is nice to use
It's the same for local use too, I would like to be able to set JUST_COLOR and never have to worry about it again for normal use
An idea that might dovetail with this:
Add a function
just()which is sugar for(just_executable() + ' --justfile ' + justfile() + ' ' + just_options() + ' -- ')where
just_options()returns the options passed in to the current invocation.
Although that could be useful, it is not a good "alternative" to environment variables. In addition to what @poliorcetics said, it would be harder for recipes to use the options for something other than passing to recursive just invocations. Also, with the way just currently works, this function might be problematic where justfile() or just_executable() contain whitespace.
Another possible approach:
Export all variables to a single JUST_VARIABLES in some structural format (maybe JSON, it can be serialized or deserialized almost anywhere).
Provide a function var(<name>, <default>), which behaves like env(...), except that it reads from JUST_VARIABLES.
In justfile, when set inherit (or perhaps set export-variables):
- If
JUST_VARIABLESis not set, export all variables toJUST_VARIABLES; - Otherwise, update them.
Edit: We can also export each variable to different variables, like JUST_VARIABLE_foo, this should be more convenient to check or override. But this can create a lot of env variables.