Reputation: 11071
I am making a presubmit script. It looks like this:
function presubmit() {
gradle test android
gradle test ios
gradle test server
git push origin master
}
I want the function to exit, if any of the tests fail so it won't push a bug to git. How?
Upvotes: 47
Views: 31488
Reputation: 20725
Also others have given ways that map one to one to your case, I think a more generic view is better. Also using the ||
and &&
for such is a cryptic way of writing scripts (read: prone to ending up with bugs).
I think the following is much easier to work with long term:
function presubmit() {
if ! gradle test android
then
return 1
fi
if ! gradle test ios
then
return 1
fi
if ! gradle test server
then
return 1
fi
git push origin master
}
The return from the last command is returned by the function so we do not need to have an if/then there.
In your specific case, to avoid the duplication, you could use a for loop like so:
function presubmit() {
for name in android ios server
do
if ! gradle test ${name}
then
return 1
fi
done
git push origin master
}
Now, you may instead want to look at a pre-push hook which would probably be much better since whether you run your script or not, the push won't happen unless the hook succeeds.
Upvotes: 0
Reputation: 10404
I would make script more granular:
#!/bin/bash
function test() {
gradle test android
gradle test ios
gradle test server
}
function push() {
git push origin master
}
# this subshell runs similar to try/catch
(
# this flag will make to exit from current subshell on any error inside test or push
set -e
test
push
)
# you catch errors with this if
if [ $? -ne 0 ]; then
echo "We have error"
exit $?
fi
We track error only inside test and push. You can add more actions outside of subshell where test and push run. You can also this way add different scope for errors (let consider it as try/catch)
Upvotes: 6
Reputation: 610
1. Use subshell ( .. )
with set -e
; to make it more concise, you can do this:
build() {( set -e # Fail early
build_cmd_step_1
build_cmd_step_2
build_cmd_step_3
...
)}
Then, the function will fail on the first failure and you can intercept the exit status:
build
exit_status=$?
if [ ${exit_status} -ne 0 ]; then
echo "We have error - build failed!"
exit "${exit_status}"
fi
2. Alternatively, the && \
chaining inside a function is also good (https://stackoverflow.com/a/51913013/1375784), though it might get bad if you have a bigger function.
Both methods can be good, depending on your use case (in some cases using subshells may cause some unwanted side effects)
Upvotes: 46
Reputation: 7989
The way I do it is to add && \
after every command in the function (except the last one).
function presubmit() {
gradle test android && \
gradle test ios && \
gradle test server && \
git push origin master
}
Upvotes: 21
Reputation: 784878
You can do this:
# declare a wrapper function for gradle
gradle() {
command gradle "$@" || exit 1
}
presubmit() {
gradle test android
gradle test ios
gradle test server
git push origin master
}
declare -xf presubmit gradle
Call the function in a subshell as:
( presubmit )
Upvotes: 5
Reputation: 689
Usually when I call a function and want an error message incase it fails I do this:
presubmit || { echo 'presubmit failed' ; exit 1; }
By adding the ||
flag, it will determine whether which expression is TRUE.
Hope this helps :)
Upvotes: 4