Jenkins build pipelines and PHP Unit tests and what Docker can do for you

Jenkins build pipelines and PHP Unit tests and what Docker can do for you

Stage prepare

The prepare stage is for setting variables depending on the Jenkins job parameter (if necessary), sending a notification to my Slack channel and, if configured, an email that a build starts and do all the stuff to checkout the source code into the workspace.

State build

The build stage is very simple. I just iterate through all PHP files and templates to see if there are some errors php -l reveals. If errors are found I use the same mechanisms described below to catch the errors and break the build immediately.

Stage run-docker-container

This stage is where I start my database Docker containers for my PHP Unit Tests.

try {
     registry = String.valueOf(DOCKER_REGISTRY) + ":" + String.valueOf(DOCKER_REGISTRY_PORT)
     httpRegistry = "http://" + String.valueOf(DOCKER_REGISTRY) + ":" + String.valueOf(DOCKER_REGISTRY_PORT)

     docker.withRegistry(httpRegistry, "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx") {

         dbImgObj = docker.image(registry + '/mariadb:5.5.41.2')
         dbPgImgObj = docker.image(registry + '/postgresql:9.2.23.16')
         dbContainer = dbImgObj.run('--name=mysqltestdb -p 33060:3306 -e MYSQL_ROOT_PASSWORD=rootpw -e MYSQL_DATABASE=testdb -e MYSQL_USER=test -e MYSQL_PASSWORD=test')
         dbPgContainer = dbPgImgObj.run('--name=pgtestdb -p 54320:5432 -e DBNAME=test -e DBUSER=test -e DBPASS=test')
         mysqlPort = (dbContainer.port(3306).split(':'))[ 1]
         pgPort = (dbPgContainer.port(5432).split(':'))[ 1] 
         echo "MySQL running on port " + mysqlPort
         echo "Postgres running on port " + pgPort
     }

     sleep 5 // be gentle and give the containers time to settle

     withEnv(['MYSQLPORT=' + mysqlPort]) {
          sh 'cat ./mysql-schema.sql | /usr/bin/mysql --host=0.0.0.0 --port=${MYSQLPORT} --user=test --password=test test'
     }

     withEnv([ 'PGPORT=' + pgPort, 'PGPASSWORD=test' ]) {
          sh 'cat ./pg-test-schema.sql | psql -q -h 127.0.0.1 -p ${PGPORT} -U test'
     }

} catch(any) {
     currentBuild.result = 'FAILURE'
     notifyEmail('FAILED')
     dbContainer.stop()
     dbPgContainer.stop()
     throw any //rethrow exception to prevent the build from proceeding
}

The values for the Docker registry and the registry port are stored as global parameters in my Jenkins installation. As the registry is on the same host as my Jenkins I use http to access the registry. My registry is password protected. To connect I need the credentials stored in my Jenkins.

docker.withRegistry(httpRegistry, "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")

The code above connects to the registry using the credentials stored in Jenkis with the according credentials id.

dbImgObj = docker.image(registry + '/mariadb:5.5.41.2')

This snippet pulls a MariaDB image from my Docker registry.

dbContainer = dbImgObj.run('--name=mysqltestdb -p 33060:3306 -e MYSQL_ROOT_PASSWORD=rootpw -e MYSQL_DATABASE=testdb -e MYSQL_USER=test -e MYSQL_PASSWORD=test')

This snippet starts the MariaDB Docker container and passes environment variables and a port mapping to the container. Due to the environment variables a database will be created within the Docker container during the container start. The same is done for the PostgtreSQL database.

withEnv(['MYSQLPORT=' + mysqlPort]) {          
    sh 'cat ./mysql-schema.sql | /usr/bin/mysql --host=0.0.0.0 --port=${MYSQLPORT} --user=test --password=test test'     
}

The above code creates the database schema in the MariaDB container. withEnv sets environment variables which can be used inside the block.

The catch block is used to stop the Docker containers and send a notification if anything went wrong.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert