Skip to content

Commit

Permalink
HV-2057 Add Sonar stage to the build
Browse files Browse the repository at this point in the history
  • Loading branch information
marko-bekhta committed Oct 18, 2024
1 parent fa15e3f commit dc2a9ae
Show file tree
Hide file tree
Showing 2 changed files with 137 additions and 1 deletion.
65 changes: 65 additions & 0 deletions Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ stage('Default build') {
dir(helper.configuration.maven.localRepositoryPath) {
stash name:'default-build-result', includes:"org/hibernate/validator/**"
}
stash name:'default-build-jacoco-reports', includes:"**/jacoco.exec"
}
}
}
Expand Down Expand Up @@ -330,6 +331,62 @@ stage('Non-default environments') {
}
}

stage('Sonar analysis') {
def sonarCredentialsId = helper.configuration.file?.sonar?.credentials
if (sonarCredentialsId) {
runBuildOnNode {
helper.withMavenWorkspace {
if (enableDefaultBuild && enableDefaultBuildIT) {
unstash name: "default-build-jacoco-reports"
}
environments.content.jdk.enabled.each { JdkBuildEnvironment buildEnv ->
unstash name: "${buildEnv.tag}-build-jacoco-reports"
}
environments.content.wildflyTck.enabled.each { JdkBuildEnvironment buildEnv ->
unstash name: "${buildEnv.tag}-build-jacoco-reports"
}

// we don't clean to keep the unstashed jacoco reports:
sh "mvn package -Pskip-checks -Pci-build -DskipTests -Pcoverage-report ${toTestJdkArg(environments.content.jdk.default)}"


// WARNING: Make sure credentials are evaluated by sh, not Groovy.
// To that end, escape the '$' when referencing the variables.
// See https://www.jenkins.io/doc/book/pipeline/jenkinsfile/#string-interpolation
withCredentials([usernamePassword(
credentialsId: sonarCredentialsId,
usernameVariable: 'SONARCLOUD_ORGANIZATION',
// https://docs.sonarsource.com/sonarqube/latest/analyzing-source-code/scanners/sonarscanner-for-maven/#analyzing
passwordVariable: 'SONAR_TOKEN'
)]) {
// We don't want to use the build cache or build scans for this execution
def miscMavenArgs = '-Dscan=false -Dno-build-cache'
sh """ \
mvn sonar:sonar \
${miscMavenArgs} \
-Dsonar.organization=\${SONARCLOUD_ORGANIZATION} \
-Dsonar.host.url=https://sonarcloud.io \
-Dsonar.projectKey=hibernate_hibernate-validator \
${helper.scmSource.pullRequest ? """ \
-Dsonar.pullrequest.branch=${helper.scmSource.branch.name} \
-Dsonar.pullrequest.key=${helper.scmSource.pullRequest.id} \
-Dsonar.pullrequest.base=${helper.scmSource.pullRequest.target.name} \
${helper.scmSource.gitHubRepoId ? """ \
-Dsonar.pullrequest.provider=GitHub \
-Dsonar.pullrequest.github.repository=${helper.scmSource.gitHubRepoId} \
""" : ''} \
""" : """ \
-Dsonar.branch.name=${helper.scmSource.branch.name} \
"""} \
"""
}
}
}
} else {
echo "Skipping Sonar report: no credentials."
}
}

} // End of helper.runWithNotification

// Job-specific helpers
Expand Down Expand Up @@ -364,6 +421,7 @@ abstract class BuildEnvironment {
abstract String getTag()
boolean isDefault() { isDefault }
boolean requiresDefaultBuildArtifacts() { true }
boolean generatesCoverage() { true }
}

class JdkBuildEnvironment extends BuildEnvironment {
Expand All @@ -386,6 +444,7 @@ class SigTestBuildEnvironment extends BuildEnvironment {
String getTag() { "sigtest-jdk$testJavaVersion" }
@Override
boolean requiresDefaultBuildArtifacts() { true }
boolean generatesCoverage() { false }
}

void keepOnlyEnvironmentsMatchingFilter(String regex) {
Expand Down Expand Up @@ -484,6 +543,12 @@ void mavenNonDefaultBuild(BuildEnvironment buildEnv, String args, String project
$args \
"""
}

if ( buildEnv.generatesCoverage() ) {
// We allow an empty stash here since it can happen that a PR build is triggered
// but because of incremental build there will be no tests executed and no jacoco files generated:
stash name: "${buildEnv.tag}-build-jacoco-reports", includes:"**/jacoco.exec", allowEmpty: true
}
}

String toTestJdkArg(BuildEnvironment buildEnv) {
Expand Down
73 changes: 72 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,7 @@
<version.maven-wrapper-plugin>3.3.2</version.maven-wrapper-plugin>
<version.spotless-maven-plugin>2.43.0</version.spotless-maven-plugin>
<version.jacoco.plugin>0.8.12</version.jacoco.plugin>
<version.sonar.plugin>4.0.0.4121</version.sonar.plugin>

<!-- Forbidden API related properties -->
<forbiddenapis-junit.path>forbidden-junit.txt</forbiddenapis-junit.path>
Expand Down Expand Up @@ -351,6 +352,19 @@
<maven.compiler.release>${java-version.main.release}</maven.compiler.release>
<maven.compiler.testRelease>${java-version.test.release}</maven.compiler.testRelease>

<!--
The absolute path to the root project directory.
This property is set by the build-helper plugin.
We initialize it to some crude, potentially wrong value,
because the Sonar Maven plugin uses this property indirectly,
but ignores any change made by other plugins.
This default value is the best we can do without the help of a Maven plugin.
Useful resources:
- https://www.mojohaus.org/build-helper-maven-plugin/rootlocation-mojo.html
-->
<rootProject.directory>${user.dir}</rootProject.directory>

<!-- Set empty default values to avoid Maven leaving property references (${...}) when it doesn't find a value -->
<!-- Argument passed from the command line -->
<surefire.jvm.args.commandline></surefire.jvm.args.commandline>
Expand Down Expand Up @@ -380,6 +394,7 @@
Allows distinguishing between multiple executions of the same test in test reports.
-->
<surefire.environment>default</surefire.environment>
<jacoco.environment.sub-directory>${surefire.environment}</jacoco.environment.sub-directory>

<arquillian.wildfly.jvm.args.add-opens></arquillian.wildfly.jvm.args.add-opens>
<arquillian.wildfly.jvm.args.add-modules></arquillian.wildfly.jvm.args.add-modules>
Expand All @@ -399,6 +414,48 @@
<!-- Formatting -->
<format.skip>false</format.skip>
<goal.spotless-maven-plugin>apply</goal.spotless-maven-plugin>

<!-- Sonar options -->
<!--
We want to take into account coverage data from integration tests from other projects as well.
This requires to use a single destination file for ITs, because:
- Integration tests cover code from other modules.
- The Sonar plugin computes coverage when inspecting each module,
and by default only takes into account JaCoCo coverage reports from the inspected module.
Thus it ignores some relevant ITs by default.
- Even when configured, the Sonar plugin only accept an *explicit* list of JaCoCo coverage reports
(no wildcards).
Thus we cannot easily configure the Sonar plugin to inspect JaCoCo coverage reports from other modules,
unless we somehow aggregate all of the coverage data into a single, shared JaCoCo coverage report.
The chosen solution was to make the "reports" module invoke jacoco's "report-aggregate" goal
to create a single aggregate report, and configure sonar to only inspect that file.
Useful resources to understand what is going on (caution, not everything is up-to-date):
- https://docs.sonarqube.org/display/SONAR/Analysis+Parameters
- https://docs.sonarqube.org/display/PLUG/Usage+of+JaCoCo+with+Java+Plugin
- https://www.devcon5.ch/en/blog/2015/05/29/multi-module-integration-test-coverage-sonar-jacoco/
- http://javamemento.blogspot.fr/2016/02/sonar-jacoco-maven-multi-module.html
- https://github.com/SonarSource/sonar-scanning-examples/blob/master/sonarqube-scanner-maven/pom.xml
- https://stackoverflow.com/a/49528226/6692043
- https://www.eclemma.org/jacoco/trunk/doc/report-aggregate-mojo.html
- Not relevant anymore, but we used to merge *.exec files: https://www.eclemma.org/jacoco/trunk/doc/merge-mojo.html
-->
<sonar.coverage.jacoco.xmlReportPaths>${rootProject.directory}/build/reports/target/site/jacoco-aggregate/jacoco.xml</sonar.coverage.jacoco.xmlReportPaths>
<!--
Exclude build code and integration tests defined in the main source from coverage computation.
-->
<sonar.coverage.exclusions>
**/org/hibernate/checkstyle/**,
**/org/hibernate/validator/build/enforcer/**,
</sonar.coverage.exclusions>
<!--
Exclude build code, unit tests and integration tests from duplication analysis.
-->
<sonar.cpd.exclusions>
**/org/hibernate/checkstyle/**,
**/org/hibernate/validator/build/enforcer/**,
**/src/test/java/**
</sonar.cpd.exclusions>
</properties>

<dependencyManagement>
Expand Down Expand Up @@ -650,6 +707,15 @@
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>set-root-location-property</id>
<goals>
<goal>rootlocation</goal>
</goals>
<configuration>
<rootLocationProperty>rootProject.directory</rootLocationProperty>
</configuration>
</execution>
<execution>
<id>parse-jakarta-validation-spec-version</id>
<goals>
Expand Down Expand Up @@ -1517,6 +1583,11 @@
<artifactId>jacoco-maven-plugin</artifactId>
<version>${version.jacoco.plugin}</version>
</plugin>
<plugin>
<groupId>org.sonarsource.scanner.maven</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>${version.sonar.plugin}</version>
</plugin>
</plugins>
</pluginManagement>
</build>
Expand Down Expand Up @@ -1894,7 +1965,7 @@
</goals>
<configuration>
<propertyName>failsafe.jvm.args.jacoco</propertyName>
<destFile>${project.build.directory}/coverage/jacoco.exec</destFile>
<destFile>${project.build.directory}/${jacoco.environment.sub-directory}/coverage/jacoco.exec</destFile>
</configuration>
</execution>
</executions>
Expand Down

0 comments on commit dc2a9ae

Please sign in to comment.