Running script conditionally does not work in travis.yml, why? - bash

The following causes travis to not build at all. When I try to validate the travis.yml file, it complains that the line just above the if statement is missing a - character at column 3, but the error has to do with the if statement below.
Do I have to move the if statement out to a script?
# Deploy
after_success:
- ./tools/docker-push-container.sh
- if [ $TRAVIS_BRANCH == "master" && $TRAVIS_PULL_REQUEST == "false" ]; then
./.travis/success_message.sh
fi

You're making some assumptions about YAML syntax that are causing you problems. If you "exend" a line of YAML by indenting subsequent lines, like this:
- The quick brown fox
jumped over the
lazy dog.
It is exactly like you instead wrote this:
- The quick brown fox jumped over the lazy dog.
This means that your shell fragment, which you've written as:
- if [ $TRAVIS_BRANCH == "master" && $TRAVIS_PULL_REQUEST == "false" ]; then
./.travis/success_message.sh
fi
Actually becomes:
if [ $TRAVIS_BRANCH == "master" && $TRAVIS_PULL_REQUEST == "false" ]; then ./.travis/success_message.sh fi
And if you try run that line in the shell, you get:
sh: -c: line 1: syntax error: unexpected end of file
If you want to include a multi-line shell script in your YAML document, your best bet is probably to use the verbatim block operator, |, like this:
- |
if [ $TRAVIS_BRANCH == "master" && $TRAVIS_PULL_REQUEST == "false" ]; then
./.travis/success_message.sh
fi
Which will result, as intended, in:
if [ $TRAVIS_BRANCH == "master" && $TRAVIS_PULL_REQUEST == "false" ]; then
./.travis/success_message.sh
fi
Alternatively, you could just make proper use of semicolons:
- if [ $TRAVIS_BRANCH == "master" && $TRAVIS_PULL_REQUEST == "false" ]; then
./.travis/success_message.sh;
fi
Note the new ; before the terminal fi. This results in:
if [ $TRAVIS_BRANCH == "master" && $TRAVIS_PULL_REQUEST == "false" ]; then ./.travis/success_message.sh; fi
...which is perfectly valid shell syntax.

I tried the above solution by larsks but, it did not work for me and could be because in bash when you use && and || you need to separate the conditions.
I had the following (according to above solution)
- if [ $TRAVIS_PULL_REQUEST == false && $TRAVIS_BRANCH == "development" ]; then
echo "# Bump version and flyway migrate db";
else
echo "Skip version increment!";
fi
And I also checked the .travis.yml in Travis Lint and it shows as valid but, according to bash the above can be separated as shown below, also mentioned in this SO Question and I changed to following
- if [ $TRAVIS_PULL_REQUEST == false ] && [ $TRAVIS_BRANCH == "development" ]; then
echo "# Bump version and flyway migrate db";
else
echo "Skip version increment!";
fi
And travis build worked. It kind of make sense because above is valid way to use && and || in bash. Just sharing in case someone else come across a similar issue.

Raf's solution worked for me with separating the conditionals with []
[ $TRAVIS_PULL_REQUEST == false ] && [ $TRAVIS_BRANCH == "develop" ];

None of the suggested workarounds worked for me, I used this instead:
- if [[ ( "$TRAVIS_OS_NAME" == "osx" ) && ( "$TOXENV" == "py36" ) ]]; then brew update; fi

Related

How to execute an if condition within a yaml in gitlab ci

I have a script and a condition where the branch name changes based on which branch you're using.
test:ui:with_sauce:
...
script:
- export MASTER_URL=https://masterurlexample.io
- export TEST_PREVIEW_APP=$CI_COMMIT_REF_SLUG
- cd $MAVEN_DIRECTORY
- if [ "$CI_COMMIT_BRANCH" == "master" || "$EMULATE_BRANCH" == "master" ]; then
export TEST_PREVIEW_APP=$MASTER_URL;
fi;
- echo "Testing on $TEST_PREVIEW_APP"
- echo "starting test"
- sleep 30
- mvn -U $MAVEN_CLI_OPTS ...
When this job runs I don't believe the condition doesn't execute.
/bin/bash: line 210: [: missing `]'
/bin/bash: line 210: : command not found
Not sure if it's looking for specific quotes around the variables.
Either write the expression in a single line or use a multiline string - |.
There's also a small issue with your bash (you need [[ and ]])
- |
if [[ "$CI_COMMIT_BRANCH" == "master" || "$EMULATE_BRANCH" == "master" ]]; then
export TEST_PREVIEW_APP=$MASTER_URL
fi
- ...
or
- if [[ "$CI_COMMIT_BRANCH" == "master" || "$EMULATE_BRANCH" == "master" ]]; then export TEST_PREVIEW_APP=$MASTER_URL; fi

shell script if condition giving error message in openshift platform . if[ == ] : not found [No such file or directory ]

I've implemented script like below:
podName=someValue ; // Here value is dynamic (empty or non empty)
if[ $podName == " "] then
echo "Empty"
Even though I got empty an output but still could see:
if[ == ] : not found [No such file or directory ]
error message while running the script.
Seems like there is a small formatting issue which is causing this error. This should be the correct code.
podName=someValue
if [ "$podName" == " " ]; then
echo "Empty"
fi
You can check if the string is empty in bash / sh like this (some containers don't have bash shell):
podName="someValue"
if [ -z "$podName" ]; then
echo "Empty"
fi
or:
podName="someValue"
if [ "$podName" = "" ]; then
echo "Empty"
fi
The following syntax works only in bash [ "$podName" == "" ]

complicated bash functions returning boolean

I want to do something like this:
function one {
if [ "$1" == "hello" ]; then
return true
fi
return false
}
if [ one hello -o one goodbye ]; then
echo "Well, that's weird."
fi
As written, I know this doesn't work. Bash won't let you return boolean values. You can return 0 or 1. But bash doesn't seem to like using 0 or 1 as boolean expressions. So instead I have to return 0 instead of true and 1 for false. I can live with that. But then my if becomes:
if [ one hello -eq 0 -o one goodbye -eq 0 ] ...
Which I can do, but it's awkward. But THAT doesn't work, either, because test doesn't want to call my function with an argument.
if [ `one hello` -eq 0 -o `one goodbye` -eq 0 ] ...
Finally, I think that version works. But it's fugly.
Is there an elegant way to:
Have a bash function that returns true/false
And it takes arguments
And then it gets used in a complex if-statement (there's some combination of -o / -a between the [] )
I'd really like to have some way of writing:
if [ myfunc1 $somearg -a $myfunc2 $someotherarg ]; then ...
For now, I'm doing it the fugly way.
You don't really write predicates like this. Instead, you set the exit status to 0 if a function succeeds, or non-zero value if it fails. The if statement then checks the exit status directly.
one () {
if [ "$1" = "hello" ]; then
return 0
fi
return 1
}
if one hello || one goodbye; then
echo "Well, that's weird."
fi
Since [ itself is a command that has a 0 exit status when the test is true and 1 if false, you can define one as simply
one () {
[ "$1" = "hello" ]
}
If no return statement is encountered, the exit status of a function is the exit status of the last command to execute.
Functions don't return true or false. Instead, they succeed or fail. if checks to see if a command succeeded or not. [ is a very common command that is used in shell scripts, but it misleads many into believing it is part of the grammar. It is not. You can simply write:
if one hello || one goodbye; then
echo "Well, that's weird."
fi
You don't want to use -a or -o. (Those are typically passed as arguments to [, but are effectively deprecated in that usage.) Instead, use the shell operators && and ||.
The fun thing about the strings "true" and "false" is that they are also shell builtin commands that have the expected exit status:
function one {
[[ "$1" == "hello" ]] && echo true || echo false
}
a=$(one hello)
b=$(one goodbye)
if $a || $b; then ...
But, don't do this. Keep it simple as other answers advice.
Like this?
one () {
if [ "$1" = "hello" ]; then
echo true; return 0
fi
echo false; return 1
}
$ one hello && one bye || one hello
true
false
true
Use the builtin commands, /bin/true and /bin/false:
/bin/true always returns 0.
/bin/false always returns 1.
function one {
[[ "$1" == "hello" ]] && /bin/true || /bin/false
}
if one hello || one goodbye; then
# do stuff…
fi;
Because they’re builtins under the /bin (/usr/bin) directory, which will likely be in your $PATH, you can simply call true or false:
function one {
[[ "$1" == "hello" ]] && true || false
}
if one hello || one goodbye; then
# do stuff…
fi;
Some of the answers above almost got it. Though, you wouldn’t want to echo the words, “true” or “false,” as strings—that does nothing in relation to the question. You want to call the commands that were made for this very purpose.

How can I ensure the relevant command is run based on arguments passed in BASH?

I'm writing my first bash script that will do some visual testing using wraith. I've stripped down the code to make it easier to read.
What I'm trying to write:
- The BASH command accepts an argument - 1, 2 or 3. i.e. regressiontest 1
- server will be assigned the argument passed
- alias config will be assigned to wraith capture configs/capture-staging-1.yaml, wraith capture configs/capture-staging-2.yaml or
wraith capture configs/capture-staging-3.yaml
- The echo statement is written to a txt file.
The script works as expected. The only issue is:
If run regressiontest 1, all good, runs wraith capture configs/capture-staging-1.yaml as expected.
I run regressiontest 2, I would expect it to run wraith capture configs/capture-staging-2.yaml but seems to run wraith capture configs/capture-staging-1.yaml again.
It seems to be running using the previous config file. If I close and open terminal again, it works as expected but if I run the same command with a different argument consecutively it seems to always run the first command I use.
What am I doing wrong?
I'm new to BASH scripts and am having trouble googling to find an answer
function regressiontest {
regressionfolder=~/path/to/folder
cd $regressionfolder
alias config
if [ $# -eq 0 ]; then
echo "No arguments provided - USAGE: regressiontest <server>"
return 0
else
server=$1
fi
if [ $server != 1 ] && [ $server != 2 ] && [ $server != 3 ]; then
echo "Visual Regression Testing argument invalid - USAGE: regressiontest <server>"
return 0
elif [ $server == 1 ]; then
server="1"
alias config='wraith capture configs/capture-staging-1.yaml'
elif [ $server == 2 ]; then
server="2"
alias config='wraith capture configs/capture-staging-2.yaml'
elif [ $server == 3 ]; then
server="3"
alias config='wraith capture configs/capture-staging-3.yaml'
fi
echo "https://website-staging-$server/" > data/server.txt
config
}
Any help would be much appreciated.
Thanks, All
Moe
You are thinking right, but making things harder than need be. Your initial part of the script is fine, though I would validate that the cd succeeds, e.g.
regressionfolder=~/path/to/folder
cd "$regressionfolder" || {
printf "error: unable to change to %s\n" "$regressionfolder" >&2
return 1
}
(note: a return of 1 generally indicates error and always double-quote your variables)
After your check on "$server" != 1 ... all you need to do is set your alias with $server as the number. No additional if ... elif ... are required, e.g.
if [ "$server" != 1 ] && [ "$server" != 2 ] && [ "$server" != 3 ]; then
echo "Visual Regression Testing argument invalid - USAGE: regressiontest <server>"
return 1
fi
alias config="wraith capture configs/capture-staging-$server.yaml"
config
}
(note: always double-quote variables withing [...])
Eliminate the alias
There is no need for the alias, you can simply run:
wraith capture configs/capture-staging-$server.yaml
Putting it altogether, you could do something similar to:
function regressiontest {
regressionfolder="$HOME/path/to/folder"
cd "$regressionfolder" || {
printf "error: unable to change to %s\n" "$regressionfolder" >&2
return 1
}
if [ $# -eq 0 ]; then
echo "No arguments provided - USAGE: regressiontest <server>"
return 1
else
server=$1
fi
if [ "$server" != 1 ] && [ "$server" != 2 ] && [ "$server" != 3 ]; then
printf "Visual Regression Testing argument invalid - "
printf "USAGE: regressiontest <server>\n"
return 1
fi
wraith capture "configs/capture-staging-$server.yaml"
}
(note: also the use of "$HOME" instead of ~. While ~ will expand on the command line, you will quickly run into problems using it within scripts)
Use a case Statement
A shorter more condensed version of your function using case ... esac would probably be a bit better, e.g.
function regressiontest {
regressionfolder="$HOME/path/to/folder"
cd "$regressionfolder" || {
printf "error: unable to change to %s\n" "$regressionfolder" >&2
return 1
}
case "$server" in
[123] ) wraith capture "configs/capture-staging-$server.yaml";;
* ) printf "Visual Regression Testing argument invalid - "
printf "USAGE: regressiontest <server>\n"
return 1;;
esac
}
I don't think you want to declare aliases, but store commands for later execution; just remove the "alias" from alias config='…' and at the end call it via $config.

Understanding script to check if file exists or not

I have below command to check if file exists or not and create it if it not available:
if test "${LOG_FILE:=}x" != "x"; then
touch $LOGAP
exit_code=$?
fi
Please help me in understanding this script, how the test condition "${LOG_FILE:=}x" != "x" is used for checking if exixts or not. I am using bash shell.
Basic idea
The script checks if $LOG_FILE variable is set. If it is, it touches the file with name stored in $LOGAP.
Explanation
Let's split it:
test == if
So
if test "${LOG_FILE:=}x" != "x"; then
is the same as
if [ "${LOG_FILE:=}x" != "x" ]; then
Let's do one test:
LOG_FILE="FILE_TEST"
echo "${LOG_FILE:=}x"
will output
FILE_TESTx
So what it is done is a checking of variable LOG_FILE being set or not. If it is set,
[ "${LOG_FILE:=}x" != "x" ]
will be
[ "FILE_TESTx" != "x" ]
which is true.
If LOG_FILE is not set,
[ "${LOG_FILE:=}x" != "x" ]
will be
[ "x" != "x" ]
which is false.
That is to say x is something to start with. You could change it to
[ "${LOG_FILE:=}HELLO_MY_NAME_IS_BLABLA" != "HELLO_MY_NAME_IS_BLABLA" ]
Finally, you have a
touch $LOGAP
which will touch (create a file if not created, update modified date if already exists). It also requires the variable $LOGAP to be set.
Have to say that the fastest way to check if a file exists is this:
if [ ! -f /tmp/foo.txt ]; then
...
fi

Resources