Configuring SonarQube with Jenkins while running Maven builds sounds like it should be a breeze but, I at least, found myself scratching my head wondering how to make it work. I’d got SonarQube installed and running and I had Artifactory installed and ready to go. Jenkins was running builds fine but getting SonarQube with Jenkins working was proving a little more difficult.
The problem was with the way SonarQube was performing the analysis, it wasn’t using the same Maven repository as my Jenkins run project build and therefore wasn’t able to access a couple of internal resources that were required. The error message I was getting was:
[ERROR] Failed to execute goal on project FOO: Could not resolve dependencies for project com.example:foo:jar:2.3.4: The following artifacts could not be resolved: <...some_artefacts...>
Looking a little way up the build log it was clear what the problem was, Maven had tried to get all the artifacts from “http://repo.maven.apache.org” not my internal Artifactory server.
My configuration for the main build and test of the project was to download the required artefacts from Artifactory. The setting is under “Build Environment” and is called “Resolve artifacts from Artifactory”. I had picked the Artifactory server configured in the main Jenkins settings and indicated which repositories should be used (libs-release and libs-snapshot). For some reason these settings were not being propagated to the SonarQube build. Digging though the logs a bit more I found the build command for SonarQube:
[workspace] $ /usr/share/maven/bin/mvn -f /var/lib/jenkins/jobs/FOO/workspace/pom.xml -e -B sonar:sonar -Dsonar.jdbc.url=jdbc:mysql://123.123.123.123:3306/username?autoReconnect=true&useUnicode=true&characterEncoding=utf8 *** *** -Dsonar.host.url=http://sonar.example.com/ *** ***
This appears to have been launched as a completely independent child of Jenkins rather than as a Maven build run by Jenkins – I’m not sure exactly how the build process is run by Jenkins but the logs seem to indicate that during a build Jenkins provides a lot more settings to Maven (or it can at least). The best solution I can come up with is to modify the settings.xml file used by the SonarQube analysis build in order to tell it where to look for the Aritfactory server. This is what I do on my development machine so it seems like a fair solution, the problem is figuring out which file to modify.
There are potentially two settings.xml files, one is global and one is user level. On my development machine I modify the user level file which is found in ~/.m2/settings.xml. That would be ideal to fix this problem only I’m not sure what user the SonarQube process is running as. I presume that it’s running as the “jenkins” user created when Jenkins is installed but that is not a log in account and therefore doesn’t have a home directory. That leaves me with the global settings file.
The default global settings.xml file is essentially empty with the exception of a few place holders for plugins, proxies, servers, etc. Open up a command prompt and modify the settings.xml file:
cd /etc/maven/ sudo nano settings.xml
Make the servers section look like this:
<servers> <server> <username>username</username> <id>central</id> </server> <server> <username>username</username> <id>snapshots</id> </server> </servers>
The id elements of the entries here should match the id entries of repositories in the profile block below. If you want to deploy artefacts to the Artifactory server automatically you can add additional server entries with a username and password which should be whatever is required to access your Artifactory server. I would suggest you set up an account on the Artifactory server specifically for your Jenkins server to use. An example is shown below, I suggest you choose better names than me though as “Snapshots” and “snapshots” could easily be confused.
<server> <id>Releases</id> <username>username</username> <password>password</password> </server> <server> <id>Snapshots</id> <username>username</username> <password>password</password> </server>
Now add the following profile to the profiles section:
<profile> <repositories> <repository> <snapshots> <enabled>false</enabled> </snapshots> <id>central</id> <name>libs-release</name> <url>http://example.com/artifactory/libs-release</url> </repository> <repository> <snapshots /> <id>snapshots</id> <name>libs-snapshot</name> <url>http://example.com/artifactory/libs-snapshot</url> </repository> </repositories> <pluginRepositories> <pluginRepository> <snapshots> <enabled>false</enabled> </snapshots> <id>central</id> <name>plugins-release</name> <url>http://example.com/artifactory/plugins-release</url> </pluginRepository> <pluginRepository> <snapshots /> <id>snapshots</id> <name>plugins-snapshot</name> <url>http://example.com/artifactory/plugins-snapshot</url> </pluginRepository> </pluginRepositories> <id>artifactory</id> </profile>
These settings tell Maven about the Aritfactory server but to get Maven to always use this server we finally need to add this line to the active profiles section of settings.xml. On my system this was commented out probably because you generally wouldn’t want always on globally active profiles.
<activeProfiles> <activeProfile>artifactory</activeProfile> </activeProfiles>
At this point you should have SonarQube with Jenkins up and running. All is not quite happy in my build process yet though as I appear to have an issue with the way the subversion client is checking out the project, a problem for another day though I think.