Recently I attended a Sitecore Usergroup in London, with a talk about Continuous Integration by Andrew Thompson. Among other things, he was talking about SonarQube and how he implemented that in combination with TeamCity. I decided to try my hand on implementing it as well, but found the documentation (or findability of the documentation, more accurately) lacking.
Here are my finds:
I started with installing a local copy of it, with the integrated database. To do this I could simply follow the steps documented in the ‘Get Started in Two Minutes‘ guide.
As that was so easy I figured I’d implement this on our TeamCity server right away, but that was when things got a little more unclear. I tried following the installation guide as much as I could, but initially without the first step – Installing the Database, as I wanted to start off simple. Initially I’d install it with the embedded database (which would of course be a big no-no going forward, so it would have to change later on). Now, I hadn’t had any experience with anything like this before, so I wasn’t sure about the POM file or the properties file, and what I could do with them. A little reading up here told me it was a Project Object Model file, which as the documentation on POMs says: ‘It is a one-stop-shop for all things concerning the project’. Sample pom files for various languages can be found here. I used the sample C# file. A sample sonar.properties file can be found in the same project.
After I created my POM file and properties file I installed the SonarQube server on my TeamCity server. I installed this as a service using the “InstallNTService.bat” file and started the service by using the “StartNTService.bat” file. At the time, I wasn’t an administrator on the server, so I couldn’t initially, but after I had my access rights to the server changed I was able to execute both bat files. My first issue showed up here: I received an error about not being able to start the server because of the language (C#) plugins missing. This is also something the documentation addresses. After installing the C# plugins (which consists of downloading them and copying them into the <sonarfolder>\extensions\plugins folder) I tried running it again, but still no dice, this time I had an error about not being able to locate Java (although I can’t quite remember what the error was). The solution to this was fairly simple, add Java to the PATH environment variable.
This time I got the Sonar server started through the service.
Next step: I had to make sure that my code analysis would be executed from TeamCity, which as specified in the documentation consists of 4 steps:
- Make sure the ‘fail build if: at least one test failed’ is unchecked (this can be found in the Build Failure Conditions step in TeamCity).
- In the configuration for the Build Step select the runner type Maven with the goals ‘clean install sonar:sonar’.
As additional Maven command line parameters set ‘-Dmaven.test.failure.ignore=true’
- Create a build trigger (I’ve set mine to a daily build)
- In the Build Parameters, in the Environment Variables, add a variable called MAVEN_OPTS and set the value to ‘-Xmx512m’.
From TeamCity I now started the project – and it failed. I changed the goal in TeamCity from: Clean install sonar:sonar To: Clean install sonar:sonar –X Which adds extended logging. The issue I was having was that it was using the wrong language (Java) even though I specified sonar.language=cs in my properties file. Adding <sonar.language>cs</sonar.language> to the POM file resolved this. For some reason, it looks like my environment is completely skipping the properties file, which I am currently looking into (although I don’t have too much time to spend on this as it’s already working through the POM file).
Now to remove the database and use a SQL database instead. I found this extremely helpful article to set up Sonar which told me I had to create a new database (I called it simply “sonarqube”) with the collate option SQL_Latin1_General_CP1_CS_AS. The article also gives a seperate link to settings you need to change to enable using a SQL database with SonarQube rather than the default embedded database.
In short, it consists of the following changes:
- Create a new database (with collate option SQL_Latin1_General_CP1_CS_AS)
- Set sonar.jdbc.username to the user you want to use
- Set sonar.jdbc.password to the password of the selected user
- Change the sonar.jdbc.url to Jdbc:jtds:sqlserver://<database server>;databaseName=database;selectMethod=cursor;
- Change the sonar.jdbc.driverClassName to com.microsoft.sqlserver.jdbc.SQLServerDriver (this did not work for me – we’ll get to that in a second)
- Set sonar.jdbc.validationQuery: select 1 (sonar.jdbc.validationQuery wasn’t in my properties file at all, so I had to add this. As I understand it its an optional parameter)
- Set sonar.jdbc.dialect=mssql (which also wasn’t in my properties file, so added that too)
More information of course is available in the article itself.
Initially because I didn’t have the correct database access rights for my sonar user, but even after I gave the user dbo access I was getting nowhere starting http://localhost:9000/ – something that was working before I changed databases. My logfiles (located in <sonarfolder>\logs) gave me an error with a huge stack trace, starting with:
Cannot connect to database. Please check connectivity and settings (see the properties prefixed by ‘sonar.jdbc.’). org.apache.commons.dbcp.SQLNestedException: Cannot load JDBC driver class ‘com.microsoft.sqlserver.jdbc.SQLServerDriver’
INFO | jvm 1 | 2013/08/12 12:58:24 | java.sql.SQLException: No suitable driver
Fail to connect to database: Cannot create PoolableConnectionFactory (Connection is broken: “java.net.ConnectException: Connection refused: connect: localhost
<sonar.jdbc.url>jdbc:jtds:sqlserver://servername;databaseName=sonarqube;SelectMethod=Cursor;</sonar.jdbc.url> <sonar.jdbc.driver>net.sourceforge.jtds.jdbc.Driver</sonar.jdbc.driver> <sonar.jdbc.username>username</sonar.jdbc.username> <sonar.jdbc.password>password</sonar.jdbc.password>
After I added this to my POM file it worked successfully and I could start improving the code.