Static analysis is having a moment. Teams are moving to Jenkins after the Hudson split, Maven 3 is finally stable enough for daily work, and every second meeting brings up questions about coverage, complexity, and that vague thing we call code health. We all want fewer outages, fewer late night hotfixes, and a faster path to release. The question on the table is simple. Can Sonar help a regular team ship cleaner code without turning the day into a wall of warnings?
I have been rolling Sonar into different groups during the last months. Some are Java heavy. Some mix stacks. A few carry years of legacy. What follows is a practitioner view. What worked, what was noisy, and how to make it stick in a place where deadlines are not friendly. I will keep it grounded, show configs, and point out traps before you step in them.
Problem framing
Most teams have the same three problems with code quality.
- No shared truth. PMD reports in one folder. FindBugs somewhere else. Coverage stuck in a workspace. People talk past each other.
- Noise fatigue. Thousands of warnings. Nobody knows what to fix first. The people who care burn out. The rest mute the channel.
- Metrics with teeth. Managers want a number. Developers want context. Builds should fail for the right reasons, not because a rule does not fit our codebase.
Sonar is a server that pulls your metrics into one dashboard. It does not replace your build. It does not recompile your world. It consumes your compiled classes and the reports your tools already produce. Then it stores everything in a database and lets you browse by project, module, package, even down to a single class or file. You get trends, hot spots, and a place to talk.
The trick is rolling it out so it helps real work. Below are three cases I have put in the wild. Same server. Different paths in. You will notice a common pattern. Start simple. Make it visible. Tune the rules that do not fit you. Then add guardrails once people trust the signal.
Three case walkthrough
Case one. Maven Java shop with Jenkins and Subversion
This one is the easiest path. We installed Sonar on a small VM with MySQL. The server zip is clean. Unpack. Edit sonar.properties to point to the database. Start. You should see a login page at the server port. Create an admin account and keep moving.
On the build side we already had a Jenkins job that ran mvn clean verify. To feed Sonar we only needed to add the goal below. No POM changes required.
mvn clean verify sonar:sonar \
-Dsonar.host.url=http://sonar.mycompany.local \
-Dsonar.jdbc.url=jdbc:mysql://db.mycompany.local:3306/sonar \
-Dsonar.jdbc.username=sonar \
-Dsonar.jdbc.password=sonarSince we already used PMD and Checkstyle, Sonar picked up their reports. For coverage we turned on Cobertura in the POM because it plays nicely in this setup.
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<formats>
<format>xml</format>
</formats>
</configuration>
<executions>
<execution>
<goals>
<goal>clean</goal>
<goal>instrument</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>First pass produced a wall of issues. That is normal. We switched to the built in “Sun checks” style profile for Checkstyle and then cloned it to make a Team profile. We dropped rules that scold naming on tests and toned down a few long line warnings. We kept bug patterns from FindBugs at a higher severity. If something can crash prod, we want it in our face.
We did not fail builds on day one. We used Sonar’s alerts to email the team when new critical issues appeared. After two sprints we turned on a simple guard. If coverage trend goes down or if new critical bugs are added, the build marks unstable. People learned to watch the trends page every morning. The hotspots widget became part of stand up. This kept the signal loud and fair without stopping delivery.
Results. Fewer surprises after merges. Services with higher cyclomatic complexity showed up in red. We picked two modules each sprint and paid back risky code with tests and small refactors. Release notes told a nicer story and we spent less time arguing about taste.
Case two. PHP app with PHPUnit and Git
Sonar speaks more than Java as long as you feed it the right reports. For this app we used the PHP plugin, PHPUnit for tests, and Clover for coverage output. The team’s build was driven by a Makefile on a Linux agent. No Maven at all. No problem.
We created a small sonar project properties file at the repo root.
# sonar-project.properties
sonar.projectKey=com.company:storefront
sonar.projectName=Storefront
sonar.projectVersion=1.2.3
sonar.sources=src
sonar.tests=tests
sonar.language=php
sonar.php.tests.reportPath=build/logs/junit.xml
sonar.php.coverage.reportPath=build/logs/clover.xmlThe Jenkins job ran PHPUnit and generated the reports, then called the Sonar scanner. We used the basic launcher script that comes with the server download.
phpunit --log-junit build/logs/junit.xml --coverage-clover build/logs/clover.xml
$SONAR_HOME/bin/sonar.sh scan \
-Dsonar.projectBaseDir=$WORKSPACE \
-Dsonar.host.url=http://sonar.mycompany.localWe tuned rules in the PHP profile after the first import. Some string handling rules were very chatty given our code style. We kept SQL injection checks at top severity and flagged direct input usage without filtering. The team liked that we could click from a rule to all files that broke it. The coverage by file view showed gaps in core helpers that everyone assumed were covered.
After a two week trial we put the Sonar widget on our team page and started a Friday quick pass where we picked the top five new problems and fixed them on the spot. This made the dashboard feel like a tool we owned, not a manager scoreboard.
Case three. Legacy module with Ant, mixed quality, tight release window
This code base had no tests and Ant scripts older than some interns. The team worried that Sonar would shame them in public. We kept it simple. First step, get visibility with no pressure. We built with Ant and then called the Maven Sonar goal using the Maven Ant Tasks so we did not rewrite builds.
<taskdef uri="antlib:org.apache.maven.artifact.ant"
resource="org/apache/maven/artifact/ant/antlib.xml" />
<mvn:dependencies pathId="maven.classpath">
<dependency groupId="org.apache.maven.plugins"
artifactId="maven-surefire-plugin"
version="2.8.1"/>
</mvn:dependencies>
<target name="analyze">
<mvn:execute goal="sonar:sonar">
<arg value="-Dsonar.host.url=http://sonar.mycompany.local"/>
</mvn:execute>
</target>We turned off rules that nag formatting and focused on the handful that catch real defects. Null pointer risks. Bad equals hashCode. Dodgy date ops. No coverage yet. No build gates. We only posted a chart on a hallway screen with trends for new critical issues and complexity. Fast feedback with no shame.
Three sprints in, the team added unit tests around the hottest classes and used Cobertura to track progress. We then added a single guard in Jenkins. If new critical issues go up compared to last build, mark unstable. That was enough. No drama. One control point. People fixed what they added and ignored old cruft until they touched that code.
Objections and replies
It will slow our builds. On a medium Java project the extra sonar step usually adds a couple of minutes since analysis runs after tests and compilation. If your build agents are busy, run sonar on a nightly job at first and hook it into the main job once you have some headroom. You can also skip heavy analyzers for quick jobs and keep the full suite for night runs.
We tried static analysis before and got buried. The secret is to own your rule profile. Clone the default. Cut rules that spark arguments and keep the ones with a clear failure story in real life. Set severities that match your appetite. Save the strict profile for libraries where you care about API polish. For apps, go for crash and exploit prevention first. You can raise the bar later.
Management will turn this into a scoreboard. The fix is trends and context. Put the last thirty days of new critical issues on the wall. Add coverage trend. Invite managers to stand up once a week and point at a specific hot spot and the plan to close it. Sonar lets you attach comments to issues. Use that place to record intent. Numbers alone do not tell the story. The conversation does.
It will shame old code. Make a baseline and focus on new work. That is it. In Sonar you can filter by date. Make a team rule. You do not leave the campground worse than you found it. If you touch a class, clean the parts you changed. Nobody gets punished for a decade of history. This builds trust faster than any policy memo.
The server is one more thing to run. True. Keep it small first. MySQL works fine for a pilot. The app is a simple zip with a start script. Back up the database nightly. If you like it, move to a bigger box and a sturdier database later. LDAP works, so you can wire it to your directory and keep access simple.
Action oriented close
Here is a short plan you can start this week without asking for a task force.
- Spin up Sonar. One VM. MySQL or PostgreSQL. Unpack. Configure. Start. Add LDAP if you need it.
- Pick one project. Not the hardest. Not the toy. Wire Jenkins or your build job to run tests and then run sonar.
- Choose a sane profile. Clone the default and cut the noisy rules. Keep the ones that catch real defects at higher severity.
- Make it visible. Put the project dashboard on a wall screen. Add hotspots and trends. Make it part of stand up.
- Do a two week trial. No build breaks. Only email alerts for new critical issues and a quick Friday fix session.
- Add gentle guards. After people trust the dashboard, mark builds unstable when new critical issues rise or when coverage drops in core modules.
- Rinse and repeat. Bring in a second project. Share the profile. Keep tuning. Write down the few rules you will not bend and why.
For teams that already live in Maven land, the shortest path is:
# Jenkins Execute Shell step
export MAVEN_OPTS="-Xmx768m"
mvn -U clean verify sonar:sonar \
-Dsonar.host.url=http://sonar.mycompany.localFor teams without Maven, drop a sonar project properties file in the repo and call the scanner after your usual build. Feed it the reports you already generate. Sonar is a glue layer and a memory. It gives you one place to see truth and one language to talk about it.
Static analysis can feel like a lecture. Do not let it. Use Sonar to catch bugs before prod, shine a light on the risky corners, and build a habit of fixing what you add. Keep the rules you believe in. Cut the noise. Watch the trend. Your future self will send coffee.
One last tip. Celebrate wins. When a module drops its critical issues to zero, make noise. When coverage in a hard piece of code jumps ten points, post a screenshot. Not for vanity. For momentum.
If you want a checklist, ping me and I will share the profile we use for services, the one we use for libraries, and the Jenkins job templates that make this painless. Until then, try the steps above. You will know in a week if Sonar is for you. My bet is that it will stick.