Friday, June 26, 2015

Automating code coverage and static analysis with Jenkins, JaCoCo, and SonarQube

So now that I had a Maven build running in Jenkins (as outlined in a previous post), I wanted to get some static analysis and code coverage data as part of the build.  So I started looking into SonarQube, and it looked like a good product.  Fired up another VM, found some instructions (and more instructions) and native packages for Ubuntu, and the set up part was relatively painless (relatively being the operative word...).  The hard part was getting it to work with Jenkins.



Basic SonarQube Setup in Jenkins


First attempt to run Sonar from Jenkins failed because it couldn't find Maven.  Turned out I hadn't specified which version of Maven to use (so it defaulted to "Inherit from project"), but there wasn't one defined at the project level.  So I just had to specify which Maven install to use:



Of course, before I could specify which version of Maven for SonarQube to use, I had to actually set up a Maven Installation in Jenkins, which is done from the "Manage Jenkins" -> "Configure System" menu:


MySQL Setup


The next build failed with this error:

[ERROR] Failed to execute goal org.codehaus.mojo:sonar-maven-plugin:2.6:sonar (default-cli) on project conference: Unable to determine database dialect to use within sonar with dialect null jdbc url http://sonarqube-kc85jsb4.cloudapp.net:3306 -> [Help 1]

I misunderstood what the SonarQube installation in Jenkins wanted for "Database URL" and just entered in the server URL with the MySql port... which could have been avoided had I opened up the help drop down, which includes an example for MySql.... sheesh... So this is what it was supposed to look like (again in Manage Jenkins -> Configure System):


So at this point it seemed everything should be copacetic, but I was still getting an error, this time it was more vague though:

[ERROR] Failed to execute goal org.codehaus.mojo:sonar-maven-plugin:2.6:sonar (default-cli) on project conference: Fail to connect to database: Cannot create PoolableConnectionFactory (Communications link failure

"Wtf does that even mean??" I was asking myself.  Did some googling, stackoverflow says it's a failure of the communication link which means I'm not even talking to the service at all.  So I start checking things.  Is the mysql server service running? yes.  Is there an endpoint defined in Azure? yep.  Can I connect with Toad from my desktop? nope, same connection error.  Well at least it isn't a Jenkins thing.  So maybe it's some weird configuration thing... I go down that rat hole for a while, fiddling with ports and urls.  Finally I get the bright idea to use nmap to see if the ports look open.  Because I didn't want anybody asking questions about why I was running nmap over the corporate network, I ssh'ed into the Jenkins VM and ran it from there.  Results looked like this:


"Hmmmm, that's weird, shouldn't the mysql port be open?" I ask myself. So I google it and find this forum post:  http://askubuntu.com/questions/272077/port-3306-appears-to-be-closed-on-my-ubuntu-server ... well there you have it.  Commented out the offending line in the mysql configuration, restarted and voila, now it was connecting.  Course the first time it connected I realized that I hadn't actually granted the "jenkins" user access to the sonar tables, but that was easily fixed with GRANT ALL.  Green ball, whoohoo!

JaCoCo Setup


I was loving the SonarQube dashboard but I was disappointed that I wasn't getting the code coverage data. It looked like this:


 I knew JaCoCo was included in the POM, but it wasn't doing anything.  Turned out I needed to add "executions" to the xml definition (an alternative is to pass a maven target, but I couldn't really get that working).  This youtube video helped me to see the light, as he walked through exactly how to set up JaCoCo in the POM file.  I'd found another article that was trying to do some fancy stuff with changing where reports landed and it was totally unnecessary for what I needed.  I had to fight with it a bit on versions.  First it was telling me it couldn't find the plugin:

[ERROR] Plugin org.jacoco:jacoco-maven-plugin:0.7.6-SNAPSHOT or one of its dependencies could not be resolved: Could not find artifact org.jacoco:jacoco-maven-plugin:jar:0.7.6-SNAPSHOT -> [Help 1]

Then when it found it, it was giving me compatibility issues:

[ERROR] Failed to execute goal org.codehaus.mojo:sonar-maven-plugin:2.6:sonar (default-cli) on project conference: Unable to read /var/lib/jenkins/jobs/Push-to-Dev/workspace/target/jacoco.exec: Incompatible version 1007. -> [Help 1]

"AAAARRRG!  WHAT THE HELL!!!" ... deep breaths... Quick google search found me an answer on SO: jacoco-sonarqube-incompatible-version-1007.  So I spent some time tinkering with the version number (found out that while you used to be able to specify version ranges or just RELEASE, Maven 3 no longer supports those).  It kept breaking for a while till I set the version to 0.7.4 and deleted the report from the workspace through Jenkins... apparently it wasn't being overwritten and the incompatible version was sticking around.  Now the SonarQube Dashboard was looking FABULOUS:


No comments:

Post a Comment