Comments (10)
This would definitely be useful, although I wonder what the syntax and implementation would look like.
One slightly weird idea which wouldn't require any new syntax would be to allow returning a specific exit code to indicate that further recipe lines should not run:
foo:
test -f a.out && exit 200
cc main.c
Here, returning 200 would indicate that the rest of the recipe should not run, but the recipe should still be considered to have run successfully.
This is nice because the implementation is extremely simple and there's no new syntax. However, if a recipe line ever returns 200 as a bona-fide exit code, just
would report success, when in fact the recipe has failed.
from just.
One possibility would be to put this behind a setting:
set skip-status-code := "200"
foo:
test -f a.out && exit 200
cc main.c
So the user is opting into this behavior, and will make sure none of their commands return 200 in the case of a bona-fide error. However, this would still be error prone, since in reality, users have no idea what status codes their commands return for errors.
from just.
Syntax wise I think its just a different way of combining dependent recipes. I think the error code is a step backwards of what I'm currently doing. Let me share a snippet of a mostly real example of how I wire up/layer to do aws centric tasks just using the dependency tree.
_ensure-aws acct:
@[[ $([[ -e ~/.aws/credentials ]] && date -ju -f "%Y-%m-%dT%H:%M:%SZ" $(awk '/\[/{prefix=$0; next} $1{print prefix $0}' ~/.aws/credentials | grep "\[$acct\]aws_expiration" | cut -d = -f2) +%s 2> /dev/null || echo 0) -gt $(($(date -j '+%s')+600)) ]] || clisso get $acct
_ensure-all-aws: (_ensure-aws "hub") (_ensure-aws "vendor1") (_ensure-aws "vendor2")
_pub_ip tag: (_ensure-aws "hub")
@AWS_PROFILE=hub AWS_REGION=$CLUSTER_REGION aws ec2 describe-instances --filters "Name=tag:Name,Values=$tag" "Name=instance-state-name,Values=running" --query "Reservations[*].Instances[*].PublicIpAddress" --output text | head -1
ssh-foo command="":
ssh -J user@$(just _pub_ip "bastion") ec2-user@$(just _priv_ip "foo") "{{command}}"
redo-foo-thing:
@just ssh-foo "{ big-long-command; }"
I can keep building up the recipe tree making these mostly reusable recipes. The main thing is the user doesn't know the difference between dependent recipes and recipes I'm actually just using as guards. Its a clutter that can make that top of my Justfiles very long, and without some kind of visualization or syntax a reader has a hard time piecing it back together. Also I dont think I can dynamically adjust arguments to dependent tasks in this form, whereas a guard I'd expect it to get access to the recipes arguments and be able to adjust downstream recipes from there.
Readability and dynamicism make me want the separate syntax of chef's guards. I'll also mention like Just recipes, chef's guards allowed multiple interpreters: https://docs.chef.io/resource_common/#guard-interpreters I'll also link for reference elixir's guards as they're a different, but similarly syntactically delightful form of dependent execution.
https://hexdocs.pm/elixir/main/patterns-and-guards.html#why-guards
from just.
Those examples are pretty complicated. Can you provide a simpler example, perhaps that just tests if a file exists or not, and the syntax you would propose for guards?
from just.
Alright. so this might be the kind of issue that i just close, because I went through all the syntax again that already exists and I can see theres very few elegant ways of doing it.
_file_exists file:
@[[ -f {{file}} ]]
test: build
not_if: (_file_exists "test_output.txt")
./test
I would imagine there are symmetrical not_if
and only_if
additions, and this would presume they have to be on a single line.
from just.
This syntax:
test: build
not_if: (_file_exists "test_output.txt")
./test
Is ambiguous, since it is currently already a valid justfile, with recipes test
and not_if
with dependency _file_exists
.
from just.
I appreciate your time looking at this.
from just.
I actually think this should be left open. I'm not sure what the right syntax or implementation would be, but I think it's useful.
from just.
Not sure I'm completely understanding this feature request, but might one possibility be something like this? -
_file_exists file:
@[[ -f {{file}} ]]
test_only_if: ?(_file_exists "test_output.txt") build
./test
test_not_if: ?!(_file_exists "test_output.txt") build
./test
just
would evaluate dependencies in order, same as it does now. When it reaches a dependency that's prefixed with ?
, that dependency recipe is treated as a condition check. If the condition check dependency recipe failed: don't run any more of the requested recipe's dependencies, don't run the requested recipe, but continue as if the requested recipe had succeeded.
Similarly, not_if
(requiring that the condition check recipe DOES fail) could be a ?!
prefix.
Advantage: flexibility. It automatically allows more than one condition check. And these condition checks can be inserted anywhere in the dependencies list, so some dependencies could run prior to a condition check if desired. Or the condition check could be in the list of subsequent dependencies, if it's gating whether something should run after the main recipe.
Disadvantage: this type of condition wouldn't be able to alter queued recipes' parameters on the fly -
dynamically adjust arguments to dependent tasks in this form, whereas a guard I'd expect it to get access to the recipes arguments and be able to adjust downstream recipes from there.
Although that might have workarounds (e.g. the condition recipe could write something to a file for queued recipes to read).
Potential catch: With the way just
seems to read justfiles, it might require extra attention to ensure confusing forms like the following are invalid:
# the ? is a prefix operator, it does NOT apply to "pre"
# it applies to the "file_exists" dependency
only_if: pre? (_file_exists "test_output.txt") build
./test
# not obvious at a glance whether `?` goes with "pre" or "check"
# or is some operator with a left-hand side and a right-hand side
# if writing clearly, these dependencies should be written as:
# pre ?check build
test_ambiguous1: pre ? check build
./test
test_ambiguous2: pre?check build
./test
Or maybe the fact this concern is even coming up indicates this syntax is a terrible idea in just
- if so, sorry for the noise.
from just.
Yah, having that kind of subtle relationship between what a dependency does and what the parent recipe does is probably tricky, especially as it relates to ordering. Also, I think guards can probably always be written like so:
guard:
if [ ! -f foo ]; then \
# do stuff \
fi
I think the main motivation of guards would be to avoid putting the whole recipe inside of a conditional. So I actually think that syntax like this would be nice:
guard:
?test ! -f foo
# do stuff
Where a ?
prefix stops running a linewise recipe early if a line fails, but does not fail the recipe.
But, you can always switch to a shebang recipe to allow early, non-failing return:
guard:
#!/usr/bin/env bash
test ! -f foo && exit 0
# do stuff
Which is nearly as good, so maybe there really isn't much of a hole to fill.
from just.
Related Issues (20)
- Run in existing shell OR create interactive child shell HOT 5
- Trouble loading .env file from path HOT 1
- Allow const expressions in settings
- Bug: Incorrect run just command in just file HOT 2
- [feature request] Installation via pip? HOT 6
- Improvements to cross-platform path environment variable manipulation
- Cannot have a dependencies when using module HOT 2
- Publish checksums of release binaries HOT 2
- Do subsequents of a recipe run "immediately" after the recipe (by specification)? HOT 1
- `completions::bash` test failing under Alpine since 1.28.0 HOT 6
- Fallback for submodules HOT 3
- justfile does not preserver the command exit code HOT 1
- just submodule -l HOT 3
- set working-directory := justfile_directory() HOT 5
- Add variable to have just require a program to be present on the system HOT 1
- Color-code `just` groups HOT 3
- Unknown start of token for simple just HOT 1
- "ignore-comments" does not completely ignore commented lines HOT 6
- Allow use of names for positional-args HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from just.