Reusable build configuration and parent pom modules for BorderTech open source projects.
- Simplifies the steps to release your project to Maven Central
- Enforce quality assurance and security checks on your project code
java-common provides two parent pom modules:
- bordertech-parent is the top level pom that configures maven release plugin
- qa-parent provides quality assurance and security checks
Projects should generally use qa-parent as their parent POM:
<project>
....
<parent>
<groupId>com.github.bordertech.common</groupId>
<artifactId>qa-parent</artifactId>
<version>1.0.21</version>
</parent>
....
</project>
By default qa checks do not run, you must enable them on a per-module basis or in your project parent pom:
<property>
<bt.qa.skip>false</bt.qa.skip>
</property>
The qa-parent default is to fail the build if QA violations are found. This can be overridden by setting the following property:
<property>
<bt.qa.fail>false</bt.qa.fail>
</property>
Use the following to run the qa-parent verification:
mvn verify
If using maven release ensure the necessary POM sections are overriden - these are marked in the bordertech-parent pom, for example:
<!--
Descendants SHOULD override the url.
-->
<url>https://github.com/bordertech/java-common/</url>
Once you have configured your project and environment you can release to Maven Central.
The golden rule for releasing is ALWAYS do the release on a separate branch (it makes backing out much easier when problems arise).
Full documentation is available in the wiki under Releasing.
This is the top-level pom.xml file.
It configures the maven release plugin for projects to release to Maven Central.
Note that java projects should generally not consume this directly but instead should use qa-parent as a parent POM instead.
The qa-parent runs quality assurance checks on your java code using tools such as:
- the Checkstyle plugin to check the code style used by the developers
- the PMD plugin for source code analysis
- the Spotbugs plugin that looks for bugs in Java programs using bug patterns
- the OWASP plugin to check security vulnerabilities
- the Enforcer plugin to check dependency convergence
The qa-parent also runs:
- the JaCoCo plugin for code coverage reports
- the Surefire plugin for running unit tests
The qa-parent inherits all of the release functionality from bordertech-parent.
The qa-parent provides a profile quick-build
that for convenience skips all tests and QA. This is very useful when developing a project and a quick build of the project is required.
The qa-parent provides a profile display-versions
that uses the Version checker plugin to report project dependencies that have new versions.
Refer to Version checker plugin for all override details.
This is primarily a shared resources module used by qa-parent and potentially other BorderTech maven modules.
Refer to bordertech-parent's pom.xml for all project properties.
Projects must ensure the necessary POM sections are overriden - these are marked in the bordertech-parent pom, for example:
<!--
Descendants SHOULD override the url.
-->
<url>https://github.com/bordertech/java-common/</url>
Refer to qa-parent's pom.xml for all project properties.
Refer to the plugin sections below for basic override details:
- Checkstyle plugin
- PMD plugin
- Spotbugs plugin
- OWASP plugin
- Enforcer plugin
- JaCoCo plugin
- Surefire plugin
By default qa checks (i.e. Checkstyle, PMD, Spotbugs, OWASP, Convergence Check) do not run, you must enable them on a per-module basis or the project parent pom:
<property>
<bt.qa.skip>false</bt.qa.skip>
</property>
The qa-parent default is to fail the build if QA violations are found. This can be overridden by setting the following property:
<property>
<bt.qa.fail>false</bt.qa.fail>
</property>
By default, qa-parent configures the code analysis plugins to ignore generated source code and only analyse the project's main source directory.
The following properties are set in qa-parent for Checkstyle and PMD:
<property>
<bt.checkstyle.src>${project.build.sourceDirectory}</bt.checkstyle.src>
<bt.pmd.src>${project.build.sourceDirectory}</bt.pmd.src>
</property>
Spotbugs is different from Checkstyle and PMD as it requires an exclude filter to be configured to ignore generated files.
The following properties are set in qa-parent for Spotbugs:
<property>
<!-- Exclude files in the generated-sources directory -->
<spotbugs.excludeFilterFile>bordertech/bt-spotbugs-exclude-generated-files.xml</spotbugs.excludeFilterFile>
<!-- Need to add sources for source tag in exclude and include filters to work -->
<spotbugs.addSourceDirs>true</spotbugs.addSourceDirs>
</property>
Refer to Checkstyle plugin for all override details.
<property>
<checkstyle.skip>true</checkstyle.skip>
</property>
The checkstyle config defaults to bordertech/bt-checkstyle.xml
. This config is based on sun-checks.xml
provided by checkstyle.
To add or change a checkstyle rule you are required to create your own config.xml file and set the checkstyle.config.location
property.
<property>
<checkstyle.config.location>${basedir}/my-checkstyle-config.xml</checkstyle.config.location>
</property>
Create a suppression file add set the checkstyle.suppressions.location
property.
<property>
<checkstyle.suppressions.location>${basedir}/my-suppression.xml</checkstyle.suppressions.location>
</property>
Example suppression file:-
<?xml version="1.0"?>
<!DOCTYPE suppressions PUBLIC "-//Puppy Crawl//DTD Suppressions 1.0//EN" "http://www.puppycrawl.com/dtds/suppressions_1_0.dtd">
<suppressions>
<!-- Ignores for all files -->
<suppress checks="NPathComplexity" files="."/>
</suppressions>
Refer to PMD plugin for all override details.
<property>
<pmd.skip>true</pmd.skip>
<cpd.skip>true</cpd.skip>
</property>
The default rule set is bordertech/bt-pmd-rules.xml
.
You can override the default by creating your own custom rule set and set the bt.pmd.rules.file
property.
<property>
<bt.pmd.rules.file>${basedir}/my-rules.xml</bt.pmd.rules.file>
</property>
An extra rule set can be added via the plugin rulesets
configuration.
<plugin>
...
<configuration>
<rulesets>
<ruleset>${bt.pmd.rules.file}</ruleset>
<ruleset>${basedir}/my-rules.xml</ruleset>
</rulesets>
</configuration>
...
</plugin>
Create an excludes file that lists classes and rules to be excluded from failures and set the pmd.excludeFromFailureFile
property.
<property>
<pmd.excludeFromFailureFile>${basedir}/my-pmd-excludes.properties</pmd.excludeFromFailureFile>
</property>
Example properties file:
com.my.example.MyClass=LoggerIsNotStaticFinal
Refer to spotbugs plugin or doco for all override details.
<property>
<spotbugs.skip>true</spotbugs.skip>
</property>
Create a filter file and set spotbugs.excludeFilterFile
property.
<property>
<!-- List of exclude filter files -->
<spotbugs.excludeFilterFile>${basedir}/my-spotbugs-exclude-file.xml</spotbugs.excludeFilterFile>
</property>
Example filter file:-
<?xml version="1.0" encoding="UTF-8"?>
<FindBugsFilter>
<!-- False Positive on Loading Property Filenames -->
<Match>
<Bug pattern="PATH_TRAVERSAL_IN" />
</Match>
</FindBugsFilter>
When adding a custom exclude filter and the module still needs to ignore generated source, then merge the excludes used in the default filter bt-spotbugs-exclude-generated-files:
<FindBugsFilter>
<!-- Exclude files in the generated-sources directory. For the source tag to work with the full path of the source files the addSourceDirs property on the plugin must be set to true. -->
<Match>
<Source name="~.*generated-sources.*" />
</Match>
</FindBugsFilter>
Refer to OWASP plugin for all override details.
<property>
<dependency-check.skip>true</dependency-check.skip>
</property>
Create a suppression file add set the suppressionFiles
property.
<property>
<suppressionFiles>${basedir}/my-owasp-suppressions.xml</suppressionFiles>
</property>
Example suppression file content:
<?xml version="1.0" encoding="UTF-8"?>
<suppressions xmlns="https://jeremylong.github.io/DependencyCheck/dependency-suppression.1.1.xsd">
<suppress>
<notes>
<![CDATA[
Example to suppress a specific CVE.
]]>
</notes>
<cve>CVE-2019-12814</cve>
</suppress>
</suppressions>
If you are behind a Proxy then the OWASP plugin needs to be told which proxy to use. You can set the mavenSettingsProxyId
property in your settings.xml to the appropriate PROXY-ID (which is usually defined in the same settings.xml).
<properties>
<mavenSettingsProxyId>MY-PROXY-ID</mavenSettingsProxyId>
</properties>
Updating the OWASP vulnerability database can also be blocked by the PROXY blocking HTTP HEAD requests. To work around this you will need a command line option: -Ddownloader.quick.query.timestamp=false
Refer to enforcer plugin for all override details.
<property>
<bt.convergence.check.skip>true</bt.convergence.check.skip>
</property>
<property>
<bt.convergence.check.fail>false</bt.convergence.check.fail>
</property>
Refer to JaCoCo plugin for all override details.
<property>
<jacoco.skip>true</jacoco.skip>
</property>
Refer to Surefire plugin for all override details.
<property>
<skipTests>true</skipTests>
</property>
If your project has multiple modules and you want to provide the same override/exclude files for all the submodules, then a good solution is to use a build-tools
module similar to java-common/build-tools.
Once you have created a build-tools submodule, define the plugins you want to override in the project parent pom with the custom build-tools module as a dependency.
<!-- Example of adding a custom build-tools module to spotbugs -->
<plugin>
<groupId>com.github.spotbugs</groupId>
<artifactId>spotbugs-maven-plugin</artifactId>
<dependencies>
<!-- My project build-tools module. -->
<dependency>
<groupId>com.my.project</groupId>
<artifactId>build-tools</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
</dependencies>
</plugin>