Hi,
In my latest endavour to implement automatic testing in my project I am getting stuck when I try to start a lucee server via commandbox.
I am in the process of implementing automatic test in my GitLab CI/CD with testbox and cypress.
My plan is to use 2 “services” as gitlab calls them to host a database that will be initialized with testdata and another as the primary webserver.
As I am using Commandbox locally for my development server and my test runs my thought was that it would be ideal to use the commandbox Docker image as a base for this.
GitLab CI Config
api-test:
stage: test
needs: []
image: ortussolutions/commandbox:alpine-3.9.2
inherit:
default: false
rules:
- if: $CI_PIPELINE_SOURCE == 'merge_request_event' || $CI_PIPELINE_SOURCE == "trigger" || $CI_PIPELINE_SOURCE == "web"
services:
- name: mariadb:latest
alias: testing-database
variables:
MYSQL_ROOT_PASSWORD: TestboxDatabaseAdmin
MYSQL_ROOT_HOST: '%'
MYSQL_LOG_CONSOLE: true
MYSQL_DATABASE: content-db
entrypoint:
- '/bin/bash'
- '-c'
- |
# wait for project clone/checkout
# i'm relying on git index to indicate the clone/checkout is done
until [ -f "$CI_PROJECT_DIR/.git/index" ]; do sleep 1; done;
# especially after the lock file has been removed
while [ -f "$CI_PROJECT_DIR/.git/index.lock" ]; do sleep 1; done;
# copy/setup database init scripts as you need
cp "$CI_PROJECT_DIR/_devTools/database-structure.sql" /docker-entrypoint-initdb.d/01-database-structure.sql
cp "$CI_PROJECT_DIR/_devTools/database-testdata.sql" /docker-entrypoint-initdb.d/02-database-testdata.sql
# pass control to the default image entrypoint
exec /usr/local/bin/docker-entrypoint.sh "$@"
# arg $0 should be explicitly passed when using 'bash -c' entrypoints
- '/bin/bash'
command:
- 'mariadbd'
- name: ortussolutions/commandbox:alpine-3.9.2
alias: testing-webserver
variables:
box_server_openBrowser: false
box_server_web_host: 0.0.0.0
box_server_web_http_port: 8080
box_server_env_DB_HOST: testing-database
box_server_env_DB_PORT: 3306
box_server_env_DB_CONNECTIONSTRING: jdbc:mysql://testing-database:3306/content-db?allowPublicKeyRetrieval=true&useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&useLegacyDatetimeCode=true
entrypoint:
- '/bin/bash'
- '-c'
- |
# wait for project clone/checkout
# i'm relying on git index to indicate the clone/checkout is done
until [ -f "$CI_PROJECT_DIR/.git/index" ]; do sleep 1; done;
# especially after the lock file has been removed
while [ -f "$CI_PROJECT_DIR/.git/index.lock" ]; do sleep 1; done;
# copy/setup WebRoot into app folder - > we wont manipulate any files this way
rm -rf /app/*
cp -a "$CI_PROJECT_DIR/." /app
# start the lucee server
box server start testing-server.json --verbose --console --debug
variables:
testingWebserver: "http://testing-webserver:8080"
script:
- ./_devTools/waitForServer.sh $testingWebserver
- box testbox run runner="$testingWebserver/tests/runner.cfm"
Testing-Server.json
{
"name":"Testing",
"openBrowser":true,
"openBrowserURL":"http://localhost:8761/tests/runner.cfm",
"debug":true,
"profile":"development",
"dockEnable":false,
"trayEnable":false,
"env":{
"APPNAME":"TEST",
"ENVIRONMENT":"testing",
"CFCONFIG_ADMINPASSWORD":"TestboxAdmin",
"COLDBOX_REINITPASSWORD":"TestboxReinit",
"COLDBOX_SESSION_TIMEOUT":15,
"ORM_DIALECT":"org.hibernate.dialect.MySQL5InnoDBDialect",
"ORM_LOGSQL":false,
"ORM_SECONDARY_CACHE":false,
"DB_DRIVER":"MySQL",
"DB_CLASS":"com.mysql.cj.jdbc.Driver",
"DB_BUNDLEVERSION":"8.0.24",
"DB_BUNDLENAME":"com.mysql.cj",
"DB_HOST":"localhost",
"DB_PORT":"8760",
"DB_CONNECTIONSTRING":"jdbc:mysql://localhost:8760/content-db?allowPublicKeyRetrieval=true&useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&useLegacyDatetimeCode=true",
"DB_DATABASE":"content-db",
"DB_USER":"root",
"DB_PASSWORD":"TestboxDatabaseAdmin",
"DB_DATASOURCE":"contentbox",
"JWT_SECRET":"....",
"LUCEE_EXTENSIONS":"FAD1E8CB-4F45-4184-86359145767C29DE"
},
"app":{
"cfengine":"lucee@5.4.5"
},
"web":{
"host":"127.0.0.1",
"directoryBrowsing":false,
"http":{
"port":"8761"
},
"rewrites":{
"enable":true
}
},
"JVM":{
"heapSize":"4G",
"javaVersion":"openjdk11"
}
}`
I noticed that the testbox runner was not able to contact the testing-webserver. I added a shell script that checks if the testing-webserver is available every 5 seconds and continues the processing after or fails if the lucee server has not become available after a certain time.
After this I discovered that the testing-webserver failed to start with the error:
Cannot run program “/usr/lib/CommandBox/serverJREs/openjdk11_jre_x64_linux_hotspot_jdk-11.0.23+9/bin/java”: error=2, No such file or directory
caused by: java.io.IOException
Cannot run program “/usr/lib/CommandBox/serverJREs/openjdk11_jre_x64_linux_hotspot_jdk-11.0.23+9/bin/java”: error=2, No such file or directory
caused by: java.io.IOException
error=2, No such file or directory
waitForServer.sh
#!/bin/bash
testingWebserver=${1:-http://testing-webserver:8080}
maxAttempts=${2:-30}
waitTime=${3:-5}
attemptCounter=0
echo "Waiting for webserver to respond"
until $( curl --output /dev/null --silent --head --fail $testingWebserver ); do
if [ "${attemptCounter}" -eq "${maxAttempts}" ]; then
echo "Max attempts to contact testing webserver reached!"
exit 1
fi
printf '.'
attemptCounter=$((attemptCounter+1))
sleep "$waitTime"
done
echo "Server responded, will continue now"
``
If I install openjdk before the server start via box server java install openjdk
I will get the same result.
After the installation of openjedk I checked via ls
if the path was existing, which it was.
I tried to reproduce the issue by creating a docker-compose file to run the servers on my local machine and have a chance to look into the logs.
However I was not able to reproduce the error his way.
docker-compose.yml
``
services:
testing-database:
image: mariadb:latest
container_name: testing-database
environment:
MYSQL_ROOT_PASSWORD: TestboxDatabaseAdmin
MYSQL_ROOT_HOST: ‘%’
MYSQL_LOG_CONSOLE: true
MYSQL_DATABASE: content-db
volumes:
- ./database-structure.sql:/docker-entrypoint-initdb.d/01-database-structure.sql
- ./database-testdata.sql:/docker-entrypoint-initdb.d/01-database-testdata.sql
testing-webserver:
depends_on:
- testing-database
image: ortussolutions/commandbox:alpine-3.9.2
container_name: testing-webserver
environment:
box_server_openBrowser: false
box_server_web_host: 0.0.0.0
box_server_web_http_port: 8080
box_server_env_DB_HOST: testing-database
box_server_env_DB_PORT: 3306
box_server_env_DB_CONNECTIONSTRING: jdbc:mysql://testing-database:3306/content-db?allowPublicKeyRetrieval=true&useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&useLegacyDatetimeCode=true
volumes:
- …/:/app/
ports:
- “8769:8080”
entrypoint:
- ‘/bin/bash’
- ‘-c’
- |
pwd
whoami
box server start testing-server.json --console --debug
command:
- “”
testbox-server:
depends_on:
- testing-webserver
image: ortussolutions/commandbox:jdk11-alpine-3.9.2
container_name: testbox-server
volumes:
- ./waitForServer.sh:/app/waitForServer.sh
environment:
testingWebserver: “http://testing-webserver:8080”
entrypoint:
- ‘/bin/bash’
- ‘-c’
- |
ping -c 4 testing-webserver
/app/waitForServer.sh http://testing-webserver:8080
box testbox run runner=“http://testing-webserver:8080/tests/runner.cfm”`
Background to my project:
The project contains a contentbox installation including testbox.
My feeling is that this is either a really dumb error on my end, or something specific with the way gitlab is working with the containers.