HBASE-27272: Enable code coverage reporting to SonarQube in hbase-connectors (#99)
Signed-off-by: Balazs Meszaros <meszibalu@apache.org>
diff --git a/dev-support/code-coverage/README.md b/dev-support/code-coverage/README.md
new file mode 100644
index 0000000..b6af086
--- /dev/null
+++ b/dev-support/code-coverage/README.md
@@ -0,0 +1,49 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+# Code analysis
+
+The `run-coverage.sh` script runs maven with the coverage profile which generates the test coverage data for both java
+and scala classes.
+If the required parameters are given it also runs the sonar analysis and uploads the results to the given SonarQube
+Server.
+
+## Running code analysis
+
+After running the script the code coverage results are generated under the `test-reporting/target/code-coverage/`
+folder.
+The JaCoCo code coverage library generated reports can be found under the `jacoco-reports` folder and the SCoverage
+generated results can be found under the `scoverage-reports` folder.
+
+Here is how you can generate the code coverage reports:
+
+```./dev-support/code-coverage/run-coverage.sh```
+
+## Publishing coverage results to SonarQube
+
+The required parameters for publishing the results to SonarQube are:
+
+- host URL,
+- login credentials,
+- project key
+
+The project name is an optional parameter.
+
+Here is an example command for running and publishing the coverage data:
+
+```./dev-support/code-coverage/run-coverage.sh -l ProjectCredentials -u https://exampleserver.com -k Project_Key -n Project_Name```
\ No newline at end of file
diff --git a/dev-support/code-coverage/run-coverage.sh b/dev-support/code-coverage/run-coverage.sh
new file mode 100755
index 0000000..c56d846
--- /dev/null
+++ b/dev-support/code-coverage/run-coverage.sh
@@ -0,0 +1,69 @@
+#!/usr/bin/env bash
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+usage() {
+ echo
+ echo "options:"
+ echo "-h Display help"
+ echo "-u SonarQube Host URL"
+ echo "-l SonarQube Login Credentials"
+ echo "-k SonarQube Project Key"
+ echo "-n SonarQube Project Name"
+ echo
+ echo "Important:"
+ echo " The required parameters for publishing the coverage results to SonarQube:"
+ echo " - Host URL"
+ echo " - Login Credentials"
+ echo " - Project Key"
+ echo
+}
+
+execute() {
+SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd)"
+MAIN_POM="${SCRIPT_DIR}/../../pom.xml"
+
+ mvn -B -e -f "$MAIN_POM" clean install -DskipTests -DskipShade -Pcoverage
+
+ mvn -B -e -f "$MAIN_POM" package -fn -Pcoverage
+
+ # If the required parameters are given, the code coverage results are uploaded to the SonarQube Server
+ if [ -n "$SONAR_LOGIN" ] && [ -n "$SONAR_PROJECT_KEY" ] && [ -n "$SONAR_URL" ]; then
+ mvn -B -e -Pcoverage sonar:sonar -Dsonar.clover.reportPath=./target/clover/clover.xml \
+ -Dsonar.host.url="$SONAR_URL" -Dsonar.login="$SONAR_LOGIN" -Dsonar.projectKey="$SONAR_PROJECT_KEY" -Dsonar.projectName="$SONAR_PROJECT_NAME"
+ fi
+}
+
+while getopts ":u:l:k:n:h" option; do
+ case $option in
+ u) SONAR_URL=${OPTARG:-} ;;
+ l) SONAR_LOGIN=${OPTARG:-} ;;
+ k) SONAR_PROJECT_KEY=${OPTARG:-} ;;
+ n) SONAR_PROJECT_NAME=${OPTARG:-} ;;
+ h) # Display usage
+ usage
+ exit
+ ;;
+ \?) # Invalid option
+ echo "Error: Invalid option"
+ exit
+ ;;
+ esac
+done
+
+# Start code analysis
+execute
diff --git a/pom.xml b/pom.xml
index 4d9bc56..ba889f6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -167,6 +167,10 @@
<glassfish.el.version>3.0.1-b08</glassfish.el.version>
<compat.module>hbase-hadoop2-compat</compat.module>
<dependency.locations.enabled>false</dependency.locations.enabled>
+ <sonar-maven-plugin.version>3.9.1.2184</sonar-maven-plugin.version>
+ <scoverage.version>1.4.11</scoverage.version>
+ <sbt-compiler.version>1.0.0</sbt-compiler.version>
+ <jacoco.version>0.8.8</jacoco.version>
</properties>
<dependencyManagement>
<dependencies>
@@ -713,5 +717,77 @@
</plugins>
</build>
</profile>
+ <!-- this profile runs unit test code coverage analysis -->
+ <profile>
+ <id>coverage</id>
+ <activation>
+ <activeByDefault>false</activeByDefault>
+ </activation>
+ <modules>
+ <module>test-reporting</module>
+ </modules>
+ <properties>
+ <sonar.projectBaseDir>.</sonar.projectBaseDir>
+ <sonar.exclusions>test-reporting/**/*</sonar.exclusions>
+ <sonar.coverage.exclusions>**/example/**/*,**/DumpToStringListener*,**/KafkaProxy*</sonar.coverage.exclusions>
+ <sonar.java.binaries>**/target/classes</sonar.java.binaries>
+ <sonar.surefire.reportsPath>${project.build.directory}/surefire-reports</sonar.surefire.reportsPath>
+ <sonar.coverage.jacoco.xmlReportPaths>
+ ${sonar.projectBaseDir}/test-reporting/target/site/jacoco-aggregate/jacoco.xml
+ </sonar.coverage.jacoco.xmlReportPaths>
+ <sonar.scala.coverage.reportPaths>
+ ${sonar.projectBaseDir}/spark/hbase-spark/target/scoverage.xml
+ </sonar.scala.coverage.reportPaths>
+ <argLine />
+ <main.basedir>${project.basedir}</main.basedir>
+ <codeCoverageReportRootDir>${main.basedir}/test-reporting/target/code-coverage</codeCoverageReportRootDir>
+ <jacocoDestFile>${codeCoverageReportRootDir}/jacoco.exec</jacocoDestFile>
+ <jacocoReportDir>${codeCoverageReportRootDir}/jacoco-reports</jacocoReportDir>
+ <scoverageReportDir>${codeCoverageReportRootDir}/scoverage-reports</scoverageReportDir>
+ </properties>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.jacoco</groupId>
+ <artifactId>jacoco-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.sonarsource.scanner.maven</groupId>
+ <artifactId>sonar-maven-plugin</artifactId>
+ <version>${sonar-maven-plugin.version}</version>
+ </plugin>
+ </plugins>
+
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.scoverage</groupId>
+ <artifactId>scoverage-maven-plugin</artifactId>
+ <version>${scoverage.version}</version>
+ <configuration>
+ <excludedPackages>src/test/java</excludedPackages>
+ <excludedFiles>IntegrationTest*</excludedFiles>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.jacoco</groupId>
+ <artifactId>jacoco-maven-plugin</artifactId>
+ <version>${jacoco.version}</version>
+ <configuration>
+ <excludes>**/example/**/*</excludes>
+ </configuration>
+ <executions>
+ <execution>
+ <id>prepare-agent</id>
+ <goals>
+ <goal>prepare-agent</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+ </profile>
</profiles>
</project>
diff --git a/spark/hbase-spark/pom.xml b/spark/hbase-spark/pom.xml
index 26c5c70..7ac4828 100644
--- a/spark/hbase-spark/pom.xml
+++ b/spark/hbase-spark/pom.xml
@@ -509,6 +509,98 @@
</plugins>
</build>
</profile>
+
+ <profile>
+ <id>coverage</id>
+ <activation>
+ <activeByDefault>false</activeByDefault>
+ </activation>
+ <properties>
+ <sonar.sources>src/main/</sonar.sources>
+ <main.basedir>${project.parent.parent.basedir}</main.basedir>
+ </properties>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>net.alchim31.maven</groupId>
+ <artifactId>scala-maven-plugin</artifactId>
+ <configuration>
+ <testSourceDir>src/test/scala</testSourceDir>
+ <sourceDir>src/main/scala</sourceDir>
+ </configuration>
+ <executions>
+ <execution>
+ <id>default-sbt-compile</id>
+ <goals>
+ <goal>compile</goal>
+ <goal>testCompile</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <skipMain>true</skipMain>
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.scoverage</groupId>
+ <artifactId>scoverage-maven-plugin</artifactId>
+ <configuration>
+ <scalacPluginVersion>1.4.11</scalacPluginVersion>
+ <highlighting>true</highlighting>
+ <aggregate>true</aggregate>
+ <failOnError>false</failOnError>
+ <encoding>${project.build.sourceEncoding}</encoding>
+ <outputDirectory>${scoverageReportDir}</outputDirectory>
+ <xmlOutputDirectory>${scoverageReportDir}</xmlOutputDirectory>
+ </configuration>
+ <executions>
+ <execution>
+ <id>instrument</id>
+ <goals>
+ <goal>pre-compile</goal>
+ <goal>post-compile</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>package</id>
+ <goals>
+ <goal>package</goal>
+ <goal>report</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>scoverage-report</id>
+ <goals>
+ <!-- Needed for Sonar -->
+ <goal>report-only</goal>
+ </goals>
+ <phase>prepare-package</phase>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ <reporting>
+ <plugins>
+ <plugin>
+ <groupId>org.scoverage</groupId>
+ <artifactId>scoverage-maven-plugin</artifactId>
+ <reportSets>
+ <reportSet>
+ <reports>
+ <report>report-only</report>
+ </reports>
+ </reportSet>
+ </reportSets>
+ </plugin>
+ </plugins>
+ </reporting>
+ </profile>
</profiles>
</project>
diff --git a/test-reporting/pom.xml b/test-reporting/pom.xml
new file mode 100644
index 0000000..0a5f5df
--- /dev/null
+++ b/test-reporting/pom.xml
@@ -0,0 +1,109 @@
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <!--
+ /**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <artifactId>hbase-connectors</artifactId>
+ <groupId>org.apache.hbase.connectors</groupId>
+ <version>${revision}</version>
+ </parent>
+
+ <artifactId>test-reporting</artifactId>
+ <packaging>pom</packaging>
+ <version>${revision}</version>
+ <name>Test Reporting</name>
+ <description>Test Reporting for Apache HBase Connectors</description>
+
+ <properties>
+ <argLine/>
+ <main.basedir>${project.parent.basedir}</main.basedir>
+ </properties>
+
+ <dependencies>
+ <!-- module dependencies where coverage is needed -->
+ <dependency>
+ <groupId>org.apache.hbase.connectors.kafka</groupId>
+ <artifactId>hbase-kafka-proxy</artifactId>
+ <version>${revision}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.hbase.connectors.spark</groupId>
+ <artifactId>hbase-spark</artifactId>
+ <version>${revision}</version>
+ <exclusions>
+ <exclusion>
+ <!-- make sure wrong scala version is not pulled in -->
+ <groupId>org.scala-lang</groupId>
+ <artifactId>scala-library</artifactId>
+ </exclusion>
+ <exclusion>
+ <!-- make sure wrong scala version is not pulled in -->
+ <groupId>org.scala-lang</groupId>
+ <artifactId>scalap</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>com.google.code.findbugs</groupId>
+ <artifactId>jsr305</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>${surefire.version}</version>
+ <configuration>
+ <argLine>${argLine} -Xms256m -Xmx2048m</argLine>
+ <forkCount>1</forkCount>
+ <runOrder>random</runOrder>
+ </configuration>
+ </plugin>
+ </plugins>
+
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.jacoco</groupId>
+ <artifactId>jacoco-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>report</id>
+ <goals>
+ <goal>report-aggregate</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <outputDirectory>${jacocoReportDir}</outputDirectory>
+ <sourceEncoding>${project.build.sourceEncoding}</sourceEncoding>
+ <outputEncoding>${project.reporting.outputEncoding}</outputEncoding>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+</project>
\ No newline at end of file