dockerbruno

Script is interrupted after Bruno tests are done


Here is our integration-tests.sh script:

    #!/bin/sh

set -e

if [ "$1" = "build" ]; then
    docker build -f ../docker/cir/Dockerfile -t registry.{url}/cir2 ..
    docker build -f ../docker/db-restorer/Dockerfile -t registry.{url}/cir-db-restorer ../docker/db-restorer
    docker build -f ../tests/scripts/Dockerfile -t registry.{url}/pester.tests ../tests/scripts
    docker build -f ../tests/bruno/Dockerfile -t registry.{url}/cir-bruno-tests ../tests/bruno
fi

key=$(uuidgen)

echo ""
echo "Creating network..."

docker network create bridge-$key

echo ""
echo "Starting MSSQL server..."

mkdir -p /mnt/dock-temp/mssql-$key
chmod 777 /mnt/dock-temp/mssql-$key
mkdir -p /mnt/dock-temp/mssql-$key-backups
chmod 777 /mnt/dock-temp/mssql-$key-backups

docker run \
    -d \
    --name mssql-$key \
    --hostname mssql \
    --privileged \
    --restart always \
    --pull always \
    --network bridge-$key \
    -e "ACCEPT_EULA=Y" \
    -e "MSSQL_SA_PASSWORD=$key" \
    -e "MSSQL_COLLATION=utf8_general_ci" \
    -v /mnt/dock-temp/mssql-$key:/var/opt/mssql \
    -v /mnt/dock-temp/mssql-$key-backups:/var/backups \
    registry.{url}/mssql

# sleep 30

echo ""
echo "Restoring DB backup from google drive..."

docker run \
    --rm \
    --network bridge-$key \
    -v /mnt/dock-temp/mssql-$key-backups:/var/backups \
    -e "DB_CIR_BACKUP={url}" \
    -e "MSSQL_PASSWORD=$key" \
    registry.{url}/cir-db-restorer

echo ""
echo "Starting CIR2..."

docker run \
    -d \
    --name cir2-$key \
    --hostname cir2 \
    --network bridge-$key \
    --restart always \
    -e "DATABASE__CONNECTIONSTRING=Server=mssql; Database=CIR; user id={user}; password=$key; Encrypt=False; App=CIR2" \
    -e "ASPNETCORE_ENVIRONMENT=Development" \
    registry.{url}/cir2

echo ""
echo "Running Integration Tests..."

docker run \
    --rm \
    --network bridge-$key \
    -e "REQUEST_DELAY=0" \
    -e "API_URI=http://cir2/api/v1" \
    -e "DB_CON_STRING=Server=mssql; Database=CIR; user id={user}; password=$key; Encrypt=False; App=CIR_TESTS" \
    registry.{url}/pester.tests

echo ""
echo "Running Bruno Tests..."

docker run \
   --rm \
   --network bridge-$key \
   -e "API_URI=http://cir2/api/v1" \
   registry.{url}/cir-bruno-tests


**<--- Here is where script break and exit --->**


echo ""
echo "Cleaning..."

docker stop cir2-$key 2>/dev/null || true
docker rm cir2-$key 2>/dev/null || true
docker stop mssql-$key 2>/dev/null || true
docker rm mssql-$key 2>/dev/null || true

sleep 5

rm -f -r /mnt/dock-temp/mssql-$key-backups
rm -f -r /mnt/dock-temp/mssql-$key

docker network rm bridge-$key

After Bruno tests are done script simply exit and stop and do not continue on line "Cleaning..." enter image description here

And here is Dockerfile for Bruno tests

FROM alpine:latest

ENV API_URI ""

RUN apk add --no-cache \
    nodejs npm

RUN npm install -g @usebruno/cli

COPY /BrunoTests/ /BrunoTests/
WORKDIR /BrunoTests
CMD ["bru", "run", "--env", "Env Cir", "--output", "result.json"]

So basically I would like that my script integration-tests.sh continue even after bruno tests are done and basically continue with commands after. If you need more information please let me know.


Solution

  • When you docker run a container in the foreground (without the -d option), the exit status of docker run is the same as the exit status of the main container command. In your script, you set -e, and so if any command exits with a non-zero status, the script will immediately exit. That matches the behavior you're seeing here.

    More specifically, the command you're trying to run is a test runner. It's very reasonable for a test runner to exit with success (status 0) if all of the tests ran successfully, and failure (any other status) if there is a failure.

    There are several common workarounds for this. In your script, you can ignore the failure

    docker run ... \
      "registry.{url}/cir-bruno-tests" \
      || true
    

    In a comment, you suggest doing something similar in an entrypoint wrapper script, and in principle this would work too.

    #!/bin/sh
    
    # Run the main container command
    "$@"
    
    # But ignore its exit status and always return success
    exit 0
    

    However, also see BashFAQ/105, "Why doesn't set -e (or set -o errexit, or trap ERR) do what I expected?" set -e has some subtleties that you may not expect. You may be better off specifically checking the error status of things that you expect to fail (docker network create; if [ "$@" != 0 ]; ...; fi) which will help you clean up consistently.

    I might suggest removing the set -e, letting the test runners exit with failures, and specifically checking the other commands' success or failure state.

    (It's also worth noting that the overall structure of this just creates Docker networks and runs containers with some dependencies, which is extremely similar to what Docker Compose does. Rewriting this script into a single Compose file might be more manageable, and Compose will handle the various failure cases for you.)