[GRADLE-2002] Getting Sonar to reuse Cobertura reports in a multi-project analysis Created: 14/Dec/11  Updated: 04/Jan/13  Resolved: 14/Dec/11

Status: Resolved
Project: Gradle
Affects Version/s: 1.0-milestone-6
Fix Version/s: 1.0-milestone-7

Type: Improvement
Reporter: Gradle Forums Assignee: Peter Niederwieser
Resolution: Fixed Votes: 0


 Description   

I have a multi-project gradle build that I am trying to integrate with Sonar. Each subproject has an existing cobertura coverage file that I try to inform Sonar of, but the coverage doesn't appear in Sonar unless I apply the Sonar plugin on each subproject. Unfortunately, this makes each subproject a top-level project in Sonar and I don't benefit from a roll-up of all the metrics. Is there a way to apply the plugin on the root project and have all the subprojects send their code coverage analysis to Sonar?

Here's an excerpt of the build.gradle file from the root project:

apply plugin: 'sonar'

subprojects {
sonar {
project

{ sourceEncoding = "UTF-8" }

}
}

And here is what appears in the build.gradle file for each subproject:

sonar

{ project.dynamicAnalysis = "reuseReports" project.coberturaReportPath = file("$buildDir/reports/cobertura/coverage.xml") project.testReportPath = file("$buildDir/test-results") }

 Comments   
Comment by Gradle Forums [ 14/Dec/11 ]

I placed the sonar closure at the top-level of the root project, and the sub-projects were grouped in Sonar as desired, with one top-level project and multiple components.

Comment by Gradle Forums [ 14/Dec/11 ]

I did that initially and I can get the sub-projects grouped in Sonar, but they don't have the Cobertura coverage metrics. Do the subprojects in your build use cobertura? If so, do you mind sharing the Sonar closure you're using?

I should also mention that the Cobertura coverage is defined on the subprojects, so there is no aggregate coverage metric for the overall project, just the subprojects.

Comment by Gradle Forums [ 14/Dec/11 ]

Oh, I didn't realize you had already achieved grouping and that the only issue is Cobertura.

My top-level Sonar closure has only server{} and database{} sub-closures. I am not using Cobertura yet, so I guess posting it won't be particularly useful. I am using Gradle 1.0-milestone-5 and Sonar 2.11.

I do want to integrate Cobertura eventually; I'd be interested to know about your approach. A quick search yielded this option: [1]https://github.com/valkolovos/gradle_...
----------------------------------------------------------------------------------------
[1] https://github.com/valkolovos/gradle_cobertura/wiki

Comment by Gradle Forums [ 14/Dec/11 ]

I have the exact same problem and would like to solve this as well.

It seems that the sonar task finds the coverage.xml files (I can tell because it complains about some of the subprojects not having them) but no code shows coverage on the sonar server.

Comment by Gradle Forums [ 14/Dec/11 ]

For Cobertura, I went with something like the approach outlined in the Gradle Cookbook.

I did figure out how to resolve the problem I was having after much experimenting. The top level closure in the root build.gradle needs to look something like this:

sonar {
project {
// Other settings here
sourceEncoding = "UTF-8"
dynamicAnalysis = "reuseReports"
}
}

Then later in the same file I configure the subprojects I want to analyze with Sonar and other tools:

def projectsToAnalyze() {
subprojects.findAll

{ project -> project.name != 'generated-sources' }

}

configure(projectsToAnalyze()) {
sonar {
project.dynamicAnalysis = "reuseReports"
project.coberturaReportPath = file("$buildDir/reports/cobertura/coverage.xml")
project.testReportPath = file("$buildDir/test-results")
}
}

It isn't enough to have the subprojects tell Sonar to reuse the cobertura reports, the root has to do so as well.

Comment by Gradle Forums [ 14/Dec/11 ]

Hi, I am having the same problem!

Ben, I tried your suggestion, but the output stays the same (no coverage and tests in Sonar).
Maybe you can help me?

I have the following:

sonar {
server {
url = ...
}

database {
url = ...
driverClassName = ...
username = ...
password = ...
}

project {
sourceEncoding = "UTF-8"
reuseReports = "reuseReports"
}
}

configure(subprojects) {
sonar {
project {
coberturaReportPath = file("$reportsDir/tests/coverage.xml")
testReportPath = file("$reportsDir/tests/junitreports") // for testng
reuseReports = "reuseReports"
}
}
}

The paths are correct, because when configuring sonar on subproject level it works (but then I do not have 1 complete project in Sonar as you indicated in the issue)

Hope you can help!

Regards,
Bas Jansen

Comment by Gradle Forums [ 14/Dec/11 ]

This is weird!

When adding skip=true to the project block in the subprojects, it actually skips those projects.

So the configuration is set in the right way, but the report paths are not read by Sonar.

Looks like a bug to me....

Comment by Gradle Forums [ 14/Dec/11 ]

My build script looks much the same except that my project blocks for both the main project and the subprojects use the 'dynamicAnalysis' as the key and 'reuseReports' as the value like so:

sonar {
project {
dynamicAnalysis = "reuseReports"
}
}

The same appears in the subproject configuration block.

Comment by Gradle Forums [ 14/Dec/11 ]

reuseReports is the default, so I don't believe this makes a difference. sonar.project{} exists per project, even if you only apply the plugin to the root project (which is usually the right thing to do). This means that settings like sourceEncoding should be set for all projects to be analyzed, not just the root project.

Comment by Gradle Forums [ 14/Dec/11 ]

What matters is where you apply the plugin. Usually the plugin should only be applied to the root project. This will still give you a sonar.project {} block per project. It doesn't matter whether you configure these blocks from a parent project's build script (with subprojects {}) or individually.

Comment by Gradle Forums [ 14/Dec/11 ]

It's dynamicAnalysis = "reuseReports", but that's the default anyway. Everything within sonar.project {} is per project. Therefore, settings like sourceEncoding should be set for all projects to be analyzed. Instead of _configure(subprojects)

{...}_ you can just say _subprojects {...}

_.

Comment by Gradle Forums [ 14/Dec/11 ]

This is the default so it won't make a difference. Have a look at the GroovyDoc which documents all properties and their defaults.

Comment by Gradle Forums [ 14/Dec/11 ]

My guess is that Sonar doesn't handle Cobertura reports correctly when it comes to multi-project analysis. The Gradle Sonar plugin just passes the information on. If it works in the single-project case it's rather unlikely (though of course not impossible) that it is a bug in the plugin.

Comment by Gradle Forums [ 14/Dec/11 ]

Oh no.. I must have overlooked that typo. Many thanks!

I did some more experimenting and it seems that ONLY when I configure dynamicAnalysis = "reuseReports" on the root, the subprojects will report tests results and coverage.

So now my implementation is:

sonar {
server {
...
}

database {
...
}
project {
dynamicAnalysis = "reuseReports"
sourceEncoding = "UTF-8"
}
}

subprojects {
sonar {
project {
coberturaReportPath = file("$reportsDir/tests/coverage.xml")
testReportPath = file("$reportsDir/tests/junitreports")
dynamicAnalysis = "reuseReports"
}
}
}

Still feels like a workaround...

Many thanks guys for your help!

Comment by Gradle Forums [ 14/Dec/11 ]

I wanted to add thanks to Ben Packs help I got this working too.

It does seem that dynamicAnalysis='reuseReports' is required.

Comment by Gradle Forums [ 14/Dec/11 ]

I'll have a look at this. Nevertheless, you should set sourceEncoding on all projects.

Comment by Gradle Forums [ 14/Dec/11 ]

Ok, thanks for that hint!

Let me know if you need a tester

Comment by Gradle Forums [ 14/Dec/11 ]

Turns out that dynamicAnalysis only defaulted to reuseReports for projects that have the java plugin applied (which typically isn't the case for the root project). This is fixed now. Thanks for the pointers!

Generated at Wed Jun 30 12:10:07 CDT 2021 using Jira 8.4.2#804003-sha1:d21414fc212e3af190e92c2d2ac41299b89402cf.