TravisCI build succeeds even when tests fail - bash

This is where I am running my tests in travis.yml:
# Run tests
script:
# Test application in Docker container
- ./tools/docker-test.sh
The shell script docker-test.sh looks like this:
#!/usr/bin/env bash
githash="$(git rev-parse --short HEAD)"
echo "-------------------------------------------------"
echo "| Running unit tests |"
echo "-------------------------------------------------"
docker create -it --name test eu.gcr.io/test/test:$githash
docker start test
docker exec test /bin/sh -c "go test ./..."
docker stop test
docker rm -fv test
The TravisCI build is a success even if the tests fail.
How can I get TravisCI to know if test have failed or not? I don't know if this is a problem with errors not being propagated from Docker, errors not being propagated from the shell script or TravisCI not knowing when go tests succeed or fail.

Your script is exiting with the status code of the last command docker rm -fv test.
You need to capture the status code of the test's, then clean up docker, then exit.
This code example is from a slightly different question over here but it's the same solution.
#!/usr/bin/env bash
set -e
# Set a default return code
RC=2
# Cleanup
function cleanup {
echo "Removing container"
docker stop test || true
docker rm -f test || true
exit $RC
}
trap cleanup EXIT
# Test steps
docker create -it --name test path
docker start test
docker exec test /bin/sh -c "go test ./..."
RC=$?

Related

bash run command without exiting on error and tell me its exit code

From a bash script I want to run a command which might fail, store its exit code in a variable, and run a subsequent command regardless of that exit code.
Examples of what I'm trying to avoid:
Using set:
set +e # disable exit on error (it was explicitly enabled earlier)
docker exec $CONTAINER_NAME npm test
test_exit_code=$? # remember exit code of previous command
set -e # enable exit on error
echo "copying unit test result file to host"
docker cp $CONTAINER_NAME:/home/test/test-results.xml .
exit $test_exit_code
Using if:
if docker exec $CONTAINER_NAME npm test ; then
test_exit_code=$?
else
test_exit_code=$?
fi
echo "copying unit test result file to host"
docker cp $CONTAINER_NAME:/home/test/test-results.xml .
exit $test_exit_code
Is there a semantically straightforward way to tell bash "run command without exiting on error, and tell me its exit code"?
The best alternative I have is still confusing and requires comments to explain to subsequent developers (it's just a terser if/else):
docker exec $CONTAINER_NAME npm test && test_exit_code=$? || test_exit_code=$?
echo "copying unit test result file to host"
docker cp $CONTAINER_NAME:/home/test/test-results.xml .
exit $test_exit_code
I believe you could just use the || operator? Which is equivalent to an "if − else" command.
Would the following address your use case? (otherwise feel free to comment!)
set -e # implied in a CI context
exit_status=0
docker exec "$CONTAINER_NAME" npm test || exit_status=$?
docker cp "$CONTAINER_NAME:/home/test/test-results.xml" .
exit "$exit_status"
or more briefly:
set -e # implied in a CI context
docker exec "$CONTAINER_NAME" npm test || exit_status=$?
docker cp "$CONTAINER_NAME:/home/test/test-results.xml" .
exit "${exit_status:-0}"
As an aside, if you are not interested in this exit status code, you can also do something like this:
set -e # implied in a CI context
docker exec "$CONTAINER_NAME" npm test || :
docker cp "$CONTAINER_NAME:/home/test/test-results.xml" .
For more details on the || : tip, see e.g. this answer on Unix-&-Linux SE:
Which is more idiomatic in a bash script: || true or || :?
Very simply save the return-code if command failed:
#!/usr/bin/env sh
# Implied by CI
set -e
# Initialise exit return code
rc=0
# Run command or save its error return code if it fail
docker exec "$CONTAINER_NAME" npm test || rc="$?"
printf '%s\n' "copying unit test result file to host"
# Run other command regardless if first one failed
docker cp "$CONTAINER_NAME:/home/test/test-results.xml" .
# Exit with the return code of the first command
exit "$rc"
You could use a kind of try catch, to get the exit code and use a simple switch case to run another commands depending on the error exit code:
(
exit 2
#here your command which might fail
)
exit_code=$?
case "$exit_code" in
0) echo "Success execution"
#do something
;;
1) echo "Error type 1"
#do something
;;
2) echo "Error type 2"
#do something
;;
*) echo "Unknown error type: $exit_code"
;;
esac

How to quote entrypoint argument when updating a docker service

I've a small script to update some services in my docker stack.
The problem is that I'm not able to update the entrypoint of a service.
For example, my script generates the following command :
docker service update --entrypoint 'go run main.go web' myservice:latest
If a run this command in my terminal it works like a charm but when the command is launched by my script I get the following error:
invalid argument "'go" for "--entrypoint" flag: EOF found when expecting closing quote
Here are the interesting lines in my script :
CMD="go run main web"
...
if [ -n "$CMD" ]; then
update="--entrypoint '${CMD}'"
fi
if [ -n "$update" ]; then
docker service update $update $fullname
echo "docker service update $update $fullname" // output => docker service update --entrypoint 'go run main.go web' myservice:latest
fi
Any help is welcome.
The problem is with your script. Using update as you are, you are running the following
docker service update --entrypoint \'go run main web\'
not
docker service update --entrypoint 'go run main web'
Use an array to store the arguments instead
CMD="go run main web"
if [ -n "$CMD" ]; then
update=(--entrypoint "$CMD")
fi
if [ -n "$update" ]; then # Really just checks ${update[0]}, but that's sufficient
docker service update "${update[#]}" "$fullname"
echo "docker service update ${update[*]} $fullname"
fi
Alternatively, you can test CMD directly to decide if you want to run the command with the --entrypoint option at all.
CMD="go run main web"
if [ -n "$CMD" ]; then
docker service update --entrypoint "$CMD" "$fullname"
echo "docker service --entrypoint $CMD $fullname"
fi

Get exit code from docker entrypoint command

I have a docker container that runs a script via the entrypoint directive. The container closes after the entrypoint script is finished. I need to get the exit code from the script in order to do some logging if the script fails. Right now I'm thinking of something like this
docker run container/myContainer:latest
if [ $? != 0 ];
then
do some stuff
fi
Is this proper way to achieve this? Specifically, will this be the exit code of docker run or of my entrypoint script?
Yes, the docker container run exit code is the exit code from your entrypoint/cmd:
$ docker container run busybox /bin/sh -c "exit 5"
$ echo $?
5
You may also inspect the state of an exited container:
$ docker container inspect --format '{{.State.ExitCode}}' \
$(docker container ls -lq)
5
Checking the value of $? is not needed if you just want to act upon the exit status of the previous command.
if docker run container/myContainer:latest; then
do_stuff
fi
The above example will run/execute do_stuff if the exit status of docker run is zero which is a success.
You can add an else and elif clause in that
Or if you want to negate the exit status of the command.
if ! docker run container/myContainer:latest; then
do_stuff
fi
The above example will run do_stuff if the exit status of docker run is anything but zero, e.g. 1 and going up, since the ! negates.
If the command has some output and if does not have a silent/quite flag/option you can redirect it to /dev/null
if docker run container/myContainer:latest >/dev/null; then
do_stuff
fi
Should not output anything to stdout
see help test | grep -- '^[[:blank:]]*!'
In some cases if some output is still showing then that might be stderr which you can silent with >/dev/null 2>&1 instead of just >/dev/null

Exit build in Jenkins when script fails

I am running Jenkins as a CI/CD pipeline for a project. To make things easier for my self, I have created a bash script to run the tests and send coverage report, here is my bash script:
#!/bin/bash
echo $GIT_COMMIT # only needed for debugging
GIT_COMMIT=$(git log | grep -m1 -oE '[^ ]+$')
echo $GIT_COMMIT # only needed for debugging
./cc-test-reporter before-build
yarn test --coverage
./cc-test-reporter after-build -t simplecov --exit-code $? || echo “Skipping Code Climate coverage upload”
And this is how I am running it in Jenkins:
sh "jenkins/scripts/load_env_variables.sh test"
Jenkins runs the script, however when the script fails, Jenkins does not exit, rather it continues:
Any help with this please?
Use "set -e" in script.
-e Exit immediately if a command exits with a non-zero status.

Docker run with if statement within Docker Bamboo Task

I would like to run a docker openjdk:8-jdk with the following command:
if [ "$GIT_BRANCH" = "master" ]; then ./gradlew publish; else echo Skipped because it is not master branch; fi
I tried to do the following:
docker run --rm openjdk:8-jdk "if [ \"$GIT_BRANCH\" = \"master\" ]; then echo hi; else echo bla; fi"
But I get the following error: executable file not found in $PATH": unknown.
Furthermore it is not possible for me that I use the if statement like that:
if ...
docker run ...
else
echo Skipped
Because I have to run it as a bamboo docker task.
Since the command above is not executed within bash, bash has to be started first like that:
docker run --rm openjdk:8-jdk /bin/bash -c "if [ \"$GIT_BRANCH\" = \"master\" ]; then ./gradlew publish; else echo Skipped because it is not master branch; fi"

Resources