I've spent several frustrating days trying to get Jenkins to deploy my application remotely to my Tomcat 7.x app server. My build setup is pretty vanilla Java application built with Ant and Ivy. Overall I like Jenkins and I'm trying to learn how to use it for continuous deployment, but the lack of documentation explaining some of the plugins makes it extremely frustrating. This hopefully will explain some of the subtle configuration options better for these plugins. For this I've setup Jenkins with these plugins:
I have two jobs. One builds my application which uses a post build step to Publish artifacts to S3 bucket. The second job is used to remotely deploy the artifacts from the first job to the Tomcat 7.x server.
The 2nd job is a parameterized build with the following configuration:
Build selector for Copy Artifact name = BUILD_SELECTOR Execute Shell Command = rm -rf $WORKSPACE/build Copy S3 Artifact Project Name = MyApp Which Build = Specified by Build Parameter Parameter Name = BUILD_SELECTOR Artifact Copy = webappname-*.war Target Directory = $WORKSPACE/build
Few things to note. BUILD_SELECTOR is the name of the environment variable that holds the user's selected build. The artifact to copy setting is not a path it's just a pattern used to select the artifact. I execute the rm command to clean up the artifacts between successive builds.
The first problem I encountered was the 2nd job kept failing because it said there were not any artifacts from the 1st job. It is NOT documented anywhere that I could find, but once I went back to the 1st Job and marked the "Publish artifacts to S3 bucket" step as "Manage Artifacts". Once that was checked it finally recognized the artifacts and I got the following!
Copied 1 artifact from "MyApp" build number 301 stored in S3
But the next problem was the deploy plugin kept failing with a very obtuse error.
java.io.IOException: Error writing request body to server
I found out that if I removed my application from the Tomcat 7.x webapps directory then it would actually deploy! But if I tried to redeploy it it failed with that obtuse error. I was deploying my app to Tomcat's ROOT context so my configuration looked like this:
WAR/EAR = build/fuseanalytics-*.war Context = ROOT Container = Tomcat7x Manager User Name = none of your business Password = also none of your business Tomcat URL = http://somehost
So the clue was the following logging written out in the console output: "is not deployed."
Copied 1 artifact from "MyApp" build number 301 stored in S3 Deploying /var/lib/jenkins/workspace/MyApp/build/myapp-1.0-301.war to container Tomcat 7.x Remote [/var/lib/jenkins/workspace/DeployMyApp/build/myapp-1.0-301.war] is not deployed. Doing a fresh deployment.
So after looking through the Cargo code (what the deploy plugin is based on) I found out that Cargo has to use redeploy or undeploy if a webapp is already deployed. So why is it not working? It turns out Cargo cannot handle the Context of ROOT. The tomcat manager data doesn't specify the webapp deployed on ROOT! The work around is to change ROOT to '/' (without quotes) in Jenkins and viola! It works!