Keep deployments automated even when project versions change
Introduction
Part one focused on configuring your project to enable automated deployments to a Wildfly application server using Maven and Jenkins. Although the deployments will fail when a new version of the project is released, additional steps can be implemented to ensure that deployments continue even when the project version changes. This will be covered in this blog post (note the method discussed in this post is one of many ways of doing this).
Continuing Automated Deployments when Project Versions Change
If you are trying to deploy to Wildfly but the version of your project has changed you may encounter the following error:
[alert type=”error” class=”” id=””]ERROR [org.jboss.as.server] (management-handler-thread – 1) JBAS015870: Deploy of deployment “Project-1.5.0-SNAPSHOT.war” was rolled back with the following failure message:
{
“JBAS014671: Failed services” => {“jboss.deployment.unit.\”Projec-1.5.0-SNAPSHOT.war\”.INSTALL” => “org.jboss.msc.service.StartException in service jboss.deployment.unit.\”Project-1.5.0-SNAPSHOT.war\”.INSTALL: JBAS018733: Failed to process phase INSTALL of deployment
\”Project-1.5.0-SNAPSHOT.war\”
Caused by: org.jboss.msc.service.DuplicateServiceException: Service jboss.undertow.deployment.default-server.default-host.
/Project.session.distributable is already registered”},
“JBAS014771: Services with missing/unavailable dependencies” => [“jboss.deployment.unit.\”Project-1.5.0-SNAPSHOT.war\”.weld.weldClassIntrospector is missing
[jboss.deployment.unit.\”Project-1.5.0-SNAPSHOT.war\”.beanmanager]”]
}[/alert]
This means that the older version of the project is still deployed, and Wildfly cannot simply overwrite the deployment because their versions differ.
Create an Undeploy Job
To overcome this, we add an additional job in our build pipeline that will only execute if the project version of the deployed artifact differs from what is currently being built. This job will undeploy the older version’s deployment from the Wildfly application server.
The undeploy job should be configured to have the same String parameters (with appropriate default values) as the deploy job created in part one:
- deploy.force with a default value of true (if already deployed then do a redeploy; false will fail if already deployed)
- wildfly.hostname (the hostname of your Wildfly application server)
- wildfly.id (the id of the server in settings.xml to retrieve username and password from)
- wildfly.port (the Wildfly admin port)
Record Deployed Version
Before we configure what will trigger the undeploy build to be executed, we need to ensure that we keep track of the version that is currently deployed on the Wildfly application server.
The project version is automatically retrieved by Jenkins from the pom file of the code that is currently being built. It requires no additional configuration and can be referenced in Jenkins as ${PROJECT_VERSION}.
To keep track of the deployed version, download and install the EnvInject Jenkins plugin. This will allow us to save the deployed version in a file and load it as a Jenkins environment variable.
Create a file EnvFile.properties on your Jenkins master in JENKINS_HOME (/var/lib/jenkins by default on Linux) with the following content (change the version to whatever you have deployed):
[alert type=”info” class=”” id=””]DEPLOYED_VERSION=1.0.0-SNAPSHOT[/alert]
To load the deployed version as an environment variable in Jenkins that can be referenced in jobs as ${DEPLOYED_VERSION}, configure Jenkins and point it to the EnvFile.properties file in the global properties section. If you make use of Jenkins slaves you will additionally need to configure the individual builds that use the DEPLOYED_VERSION environment variable and point to the properties file path.
Trigger the Undeploy Job
The undeploy job is a blocking downstream build of the deploy build that we set up in part one. It is triggered when a precondition is met (deployed version does not match project version). Download and install the Parameterized Trigger Plugin for Jenkins for this step.
Configure the deploy build and add a pre-build conditional step that will run when the PROJECT_VERSION variable and the DEPLOYED_VERSION variable are not the same.
This conditional step will trigger the undeploy job with the necessary parameters passed to it. Tick the box that says “Block until the triggered projects finish their builds” because we want the undeploy job to finish before we try to deploy.
Update the Deployed Version in the File
If the undeployment was successful, the deployed version in EnvFile.properties needs to be updated so that the undeploy step will not trigger every time.
If, like Symbiotics, you use a Jenkins master-slave configuration you will need to update the file on the slave and copy it over to the Jenkins master.
[alert type=”info” class=”” id=””]#Save the current project version as the deployed version
sudo echo “DEPLOYED_VERSION=${PROJECT_VERSION}” > /var/lib/jenkins/EnvFile.properties
# Securely copy the new file from the slave to the master
sudo scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /var/lib/jenkins/nameOfJenkinsKeyFile.pem /var/lib/jenkins/EnvFile.propertiesroot@jenkins-master:/var/lib/jenkins[/alert]
If you do not use a Jenkins master-slave configuration, you can simply overwrite EnvFile.properties with the correct DEPLOYED_VERSION variable.
After the undeploy step has completed successfully, the deploy job can carry on with the deployment of the new version of the project can continue without any problems.