Posts tonen met het label hudson. Alle posts tonen
Posts tonen met het label hudson. Alle posts tonen

maandag 20 januari 2014

Analyzing the Industrial SQL Connector for Mylyn with SonarQube

Last year we set up Hudson to build the Industrial SQL Connector for Mylyn, a DIY connector project to connect Mylyn to a local SQL database for which I'm a committer. This blog post I will explain how I set up static code analysis on the same project using SonarQube. Installing and setting up SonarQube is better explained elsewhere, like http://www.sonarqube.org, but then setting up a set op eclipse plugin projects to be analyzed is more specific.

Preparation:

  • Install SonarQube following instructions here.
  • Then install the Sonar plugin into Hudson using Update Center and configure it following these instructions
  • Lookup how to build the Industrial SQL Connector for Mylyn with Hudson here

Configuring the Industrial SQL Connector for Mylyn for analysis

Whether you want to analyze projects with the Maven sonar:sonar target or use the Hudson Invoke Standalone Sonar Analysis build step in both cases you need to create a sonar-project.properties file. As a matter of common sense I always put this file in the same project as the project with the maven master POM, in this case com.industrialtsi.mylyn.maven.
# required metadata
sonar.projectKey=com.industrialtsi.mylyn
sonar.projectName=Industrial SQL Connector for Mylyn
sonar.projectVersion=0.9.10-SNAPSHOT

# optional description
sonar.projectDescription=Industrial SQL Connector for Mylyn

# path to source directories (required)
#sonar.sources=src THIS IS SPECIFIED PER MODULE

# path to project binaries (optional), for example directory of Java bytecode
#sonar.binaries=target/classes THIS IS SPECIFIED PER MODULE

# optional comma-separated list of paths to libraries. Only path to JAR file is supported.
#sonar.libraries=lib/*.jar THIS IS SPECIFIED PER MODULE

# The value of the property must be the key of the language.
sonar.language=java

# modules one for each area of functionality, only plugin and fragment projects
sonar.modules=core,derby,jpa,memory,ui

# setup project base dir
core.sonar.projectBaseDir=com.industrialtsi.mylyn.core
derby.sonar.projectBaseDir=com.industrialtsi.mylyn.demo.derby
jpa.sonar.projectBaseDir=com.industrialtsi.mylyn.demo.jpa
memory.sonar.projectBaseDir=com.industrialtsi.mylyn.demo.memory
ui.sonar.projectBaseDir=com.industrialtsi.mylyn.ui

#set up source folders 
core.sonar.sources=src
derby.sonar.sources=src
jpa.sonar.sources=src
memory.sonar.sources=src
ui.sonar.sources=src

# set up binary folders
core.sonar.binaries=target/classes
derby.sonar.binaries=target/classes
jpa.sonar.binaries=target/classes
memory.sonar.binaries=target/classes
ui.sonar.binaries=target/classes

# set up libraries folders, where jars reside
core.sonar.libraries=
derby.sonar.libraries=lib/*.jar
jpa.sonar.libraries=lib/*.jar
memory.sonar.libraries=
ui.sonar.libraries=
Then we commit this file to the repository so Hudson can retrieve it.

Configuring Hudson to analyze the project

We go to the Hudson Job tab and press configure. Under Build we add a step Invoke Standalone Sonar Analysis and configure it as follows: Sonar hudson config

Building and examining the results

We make Hudson build the project and then go over to the SonarQube pages for the results, note that I have created a custom set of my favorite widgets for this: Sonarqube 1 The Technical Debt widget tell us the technical debt in days, and also a percentage split of the main problems. Lack of coverage explains half the debt, with design, comments and complexity as other issues. There are very few violations and duplications, the happy result of running with Checkstyle, Findbugs and PMD inside Eclipse during the development. I always add a Most Violated Rules widget to the project dashboard. Exposing internal representation is the most common here as the very bad package cycles. Sonarqube 2 The "Most Violated Resources" widget instantly tells me that the objects used to ferry query parameters around are the main problem area. I have a tagged sonar-project.properties file so I will be able to see progress in the future on lines of code, technical debt and documented API. Sonarqube 3 Issues are mostly Critical and Major, so need to be fixed urgently. 1% duplications is not that serious, even though 0% is best of course. Test coverage is more serious as we've seen above that lack of Test Coverage accounts for half of technical debt. This maybe because the build is not yet configured to execute tests. Sonarqube 4 The complexity stats show mainly whether design is good, a method should do one thing, a class should have one responsibility. The LCOM4 measure of 1.0/class is quite positive. Sonarqube 5 The main problem in these is the startling 40.5% of package tangle index and more than 10 cycles! This needs to be looked at with highest priority.

Action Plan

So this short exercise (total time to setup 1,5 hours) revealed quite a lot of potential problems in the code base! How then to tackle and resolve these problems?
  1. Ensure that the unit tests are executed and measured! Without unit tests we cannot begin to refactor safely.
  2. Fix the Critical Issues in the code, but only when adequately covered by unit tests
  3. Investigate and fix the Package Cycles problems, but again only when adequately covered by unit tests
  4. Fix the Major Issues in the code, but only when adequately covered by unit tests
  5. Fix the Code Duplications problems
I will report on my findings here. For unit test coverage I'm going to use Jacoco, which works well inside Eclipse using the Eclemma plugin, is preferred by SonarQube and can also be integrated with Tycho/Maven.

donderdag 22 augustus 2013

Building the Industrial SQL Connector for Mylyn with Hudson

To get early warning when changes in Eclipse, Mylyn or EclipseLink break the build of Industrial SQL Connector for Mylyn, I have set up a build on my home Hudson CI server. When you want to use this connector you can do the same following the steps below.

Prerequisites

You will need a Hudson CI server set up, follow instructions here. You will also need maven installed from here or use the integrated version.

Create a new Hudson Job

01 createjob

After pressing OK you will see:

02 jobcreated

Configure and test SVN checkout

Enter the anonymous SVN checkout url from EclipseLabs : http://svn.codespot.com/a/eclipselabs.org/industrial-mylyn/trunk/. Also configure the build triggers, now set for 30 minutes past hour on weekdays. Can probably be less, but CI is supposed to be well continuous

03 configuresvn

After saving this configuration, press Build Now

04 testbuild

05 allcheckedout

When it's done, check the Workspace. It should look like this:

06 workspaceview

Configure the Maven/Tycho build and test it.

Next step is to add building the checked out code. Industrial SQL Connector for Mylyn comes preconfigured for a Maven/Tycho build so that is easy. Add the Build Step named Invoke Maven 3

07 addmaven3build

We need some advanced options so click the Advanced button. Most important is that the root pom file is not in the root directory but in com.industrialtsi.mylyn.maven/

08 configuremaven3build

Press Build Now again.

09 testbuildagain

Build success

When all is well you should see this, Finished: SUCCESS

10 testbuildsuccess

Results are all in the Workspace, so a bit hard to find:

11 testbuildresults

Publishing artifacts

You can archive and publish the artifacts produced by Maven by configuring the build.

12 archiveresults

This produces the following Job display:

13 resultspublished

Sunshine!

14 sunshine

donderdag 24 januari 2013

Starting Hudson automatically on Mac OSX.

With yesterdays release of Hudson 3.0.0 by the Eclipse Foundation a step forward was taken again in creating an open source toolchain under proper governance. Hudson is an extensible continuous integration platform allowing you to build, inspect and test code whenever you commit changes to your repository. The new release brings a reduction in footprint of 50% so you can also set it up to run on your local machine. After downloading and installing Hudson following the instructions on www.eclipse.org/hudson you that it is easy to start from the terminal using
> java -jar hudson.war

First try: launchd script

But this quickly becomes tiresome, so there must be a better way. On Mac OSX this is launchd, the launch service. Another important thing is that I don't want all the builds to clutter up my home directory so I want to have the HUDSON_HOME direct to somewhere else. Create a directory /usr/local/hudson and move hudson.war into it.
> sudo mkdir /usr/local/hudson
> mv hudson-3.0.0.war /usr/local/hudson/
> cd /usr/local/hudson/
> sudo chgrp admin hudson-3.0.0.war
> ln -s hudson-3.0.0.war hudson.war
I then created a file in /Library/LaunchDaemons named org.hudson-ci.agent.plist with the following contents (skip this step if you're in a hurry):
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<!-- Move HUDSON_HOME to /Volumes/yourdisk/hudson_home/ -->
	<key>EnvironmentVariables</key>
	<dict>
		<key>HUDSON_HOME</key>
		<string>/Volumes/yourdisk/hudson_home/</string>
	</dict>
	<key>Label</key>
	<string>org.hudson-ci.agent</string>
    <key>RunAtLoad</key>
    <true/>
    <key>KeepAlive</key>
	<key>ProgramArguments</key>
	<array>
	  <string>java</string>
	  <string>-jar</string>
	  <string>/usr/local/hudson/hudson.war</string>
<!-- prevent Hudson from becoming visible in the Finder & Dock -->
	  <string>-Djava.awt.headless=true</string>
	</array>
	<key>StandardErrorPath</key>
	<string>/Library/Logs/hudson-err.log</string>
	<key>StandardOutPath</key>
	<string>/Library/Logs/hudson-out.log</string>
</dict>
</plist>

Trouble!

When I had used this for a couple of days I noticed something strange. All Jobs would suddenly disappear. The reason turned out to be that sometimes during startup the Volume where HUDSON_HOME was now located wasn't available yet. The result is that another directory is created inside /Volumes/ where a new path to HUDSON_HOME is created. Launchd allows for some very clever extra checks like PathState but in the end I settled for something simpler.

Solution

Just delay startup of Hudson for a few seconds.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<!-- Move HUDSON_HOME to /Volumes/yourdisk/hudson_home/ -->
	<key>EnvironmentVariables</key>
	<dict>
		<key>HUDSON_HOME</key>
		<string>/Volumes/yourdisk/hudson_home/</string>
	</dict>
	<key>Label</key>
	<string>org.hudson-ci.agent</string>
    <key>RunAtLoad</key>
    <true/>
    <key>KeepAlive</key>
	<dict>
		<key>PathState</key>
		<dict>
			<key>/Volumes/yourdisk/hudson_home/</key>
			<true/>
		</dict>
	</dict>
	<key>ProgramArguments</key>
	<array>
	  <string>/Library/Java/Hudson/start_hudson.sh</string>
	</array>
	<key>StandardErrorPath</key>
	<string>/Library/Logs/hudson-err.log</string>
	<key>StandardOutPath</key>
	<string>/Library/Logs/hudson-out.log</string>
</dict>
</plist>
and the following in the start_hudson.sh script:
#!/bin/tcsh
set hudsonVolume = "/Volumes/yourdisk"
# introduce delay of 120 secs
sleep 120

if (! -e $hudsonVolume ) then
  exit 0
endif
growlnotify -n Hudson -m "Hudson starting..." 
# start it
/usr/bin/java \
  -jar /usr/local/hudson/hudson.war \
  -Djava.awt.headless=true \
  --httpPort=9090
This has been running now for a couple of weeks and now my builds and inspections run automatically.

maandag 7 juni 2010

Getting started with Hudson & Eclipse

Why automated build?

After reading these two blog posts by Andrew Niefer here and here I understand that there is simply no way to build a custom updatable RCP application manually from Eclipse. The export options are too limited so I opened bug 316059 to make this exporting easier.

Why Hudson?

As the Eclipse building infrastructure itself is employing Hudson I expect that automating the build of RCP applications will be possible with Hudson. The first step is to download Hudson from hudson-ci.org. I installed it on my Mac in /usr/local/hudson/.

LaunchAgent

I don't like starting up Terminal to manually start it everytime so I created a LaunchAgent for it. Place the following plist xml in file /Library/LaunchAgents/org.hudson-ci.agent.plist and Hudson will start automagically every time on login.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>org.hudson-ci.agent</string>
<key>OnDemand</key>
<false/>
<key>ProgramArguments</key>
<array>
<string>/usr/bin/java</string>
<string>-jar</string>
<string>/usr/local/hudson/hudson.war</string>
<string>--httpPort=9090</string>
</array>
<key>StandardErrorPath</key>
<string>/Library/Logs/hudson-err.log</string>
<key>StandardOutPath</key>
<string>/Library/Logs/hudson-out.log</string>
</dict>
</plist>

I employ one POJO jar in my RCP app and I managed to set this up in a few hours to extract from CVS, run checkstyle, findbugs, junit tests, emma tests code coverage and do final build. Next time I'll cover building a an Eclipse feature and update site.

Moving HUDSON_HOME (Added on 2010 06 11)

After some time I noticed that my home directory was increasing in size, leading to rapid and longer TmeMachine backups. I like the backups of my development tools to be different and under my direct (script) control so I needed to move the Hudson home directory. Luckily this can be done easily!

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<!-- Moving HUDSON_HOME to /_some_other_volume_/Hudson/ -->
<key>EnvironmentVariables</key>
<dict>
<key>HUDSON_HOME</key>
<string>/_some_other_volume_/Hudson/</string>
</dict>
<key>Label</key>
<string>org.hudson-ci.agent</string>
<key>OnDemand</key>
<false/>
<key>ProgramArguments</key>
<array>
<string>/usr/bin/java</string>
<string>-jar</string>
<string>/usr/local/hudson/hudson.war</string>
<string>--httpPort=9090</string>
</array>
<key>StandardErrorPath</key>
<string>/Library/Logs/hudson-err.log</string>
<key>StandardOutPath</key>
<string>/Library/Logs/hudson-out.log</string>
</dict>
</plist>

Now copy everything using terminal:

$ cp -pR .hudson/ /_some_other_volume_/Hudson/
and restart Hudson.

$ ps -lA | grep hudson
501 _XXXX_ 565 4004 0 47 0 2972192 212840 - ↵
→ S a9a87e0 ?? 0:40.14 ↵
→ /usr/bin/java -jar /usr/local/hudson/hudson.war --httpPort=9090
$ kill _XXXX_
$ sudo launchctl list


Then try in your browser: And now everything appears to be located in the new location!