Git pre-commit hooks Part 2
by Eing Ong
In Part 1, I use “mvn test” results to determine if pre-commit should pass. This leverages many maven plugins that are handy and easy to customize for your requirements. There are 3 checks I added - FindBugs, Checkstyle and JMockit coverage threshold. Let’s get started with FindBugs first.
FindBugs plugin
Three key parameters of note are effort, threshold and failOnError. There’s not much documentation on these fields at the plugin website but you can find all configurations and default values here. The configuration in maven plugin does not map to the original Ant settings. Gradle plugin though maps nicely to Ant settings.
Anyways, I set effort to maximum for detecting all violations. Threshold has 3 settings - low, medium and high and I recommend low, otherwise why bother to use FindBugs? On failOnError, you can choose to set it to false so you can fix errors together with Checkstyle errors (and not sequentially) but be sure to add this check in Jenkins or your CI job.
You can refer to Petri K’s blog with more details on this plugin.
If you’re using gradle, take a look at FindBugs Extension
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>findbugs-maven-plugin</artifactId>
<version>3.0.3</version>
<configuration>
<effort>Max</effort>
<threshold>Low</threshold>
<xmlOutput>true</xmlOutput>
<failOnError>true</failOnError>
</configuration>
<executions>
<!-- Ensures that FindBugs inspects source code when project is compiled. -->
<execution>
<id>analyze-compile</id>
<phase>verify</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
Checkstyle plugin
In Checkstyle, we created a customized rules list to be used across all projects. This xml file is committed as a git project and added as a dependency for the plugin which you can see below. Unlike FindBugs, Checkstyle plugin has very good documentation. All configurations and default values can be found here.
To customize your own rules set (if Sun rules set is too restrictive), refer to these Checks.
Again, for gradle, you can refer to Checkstyle Extension
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>2.17</version>
<configuration>
<encoding>UTF-8</encoding>
<linkXRef>false</linkXRef>
<configLocation>com/intuit/tools/checkstyle.xml</configLocation>
<consoleOutput>true</consoleOutput>
<violationSeverity>info</violationSeverity>
</configuration>
<executions>
<!-- Ensures that Checkstyle inspects source code when project is compiled. -->
<execution>
<id>checkstyle</id>
<goals><goal>check</goal></goals>
<phase>verify</phase>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>com.intuit.tools</groupId>
<artifactId>checkstyle-resources</artifactId>
<version>1.0.1</version>
</dependency>
</dependencies>
</plugin>
Surefire plugin for JMockit coverage threshold
Last but not least is code coverage threshold for unit tests. Since we are using JMockit for unit tests, we leverage JMockit-coverage that works very well with it. We have run into many issues using Jacoco and Cobertura plugins with JMockit.
JMockit has a good write up on code coverage, see JMockit Code Coverage Tutorial. The only part that should be included is the surefire plugin and how you can set the coverage-check configuration. So, here’re snippets extracted from my pom.
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>${surefire.version}</version>
<configuration>
<systemPropertyVariables>
<coverage-metrics>all</coverage-metrics>
<!-- Threshold is set at 85% -->
<coverage-check>85</coverage-check>
</systemPropertyVariables>
</configuration>
</plugin>
<plugin>
<artifactId>maven-enforcer-plugin</artifactId>
<executions>
<execution>
<id>coverage.check</id>
<goals><goal>enforce</goal></goals>
<phase>test</phase>
<configuration>
<rules>
<requireFilesDontExist>
<files><file>coverage.check.failed</file></files>
</requireFilesDontExist>
</rules>
</configuration>
</execution>
</executions>
</plugin>
Other examples for coverage-check (instead of “85” in the example above) are
- "perFile:85,80,90", meaning that each source file must have at least 85% of line coverage, at least 70% branch coverage and at least 90% of data coverage
- "package:85,80,90", has similar thresholds as above except that it is applied to source files in a given package, including sub-packages.
Finally, these are the dependencies I use along with the plugins.
<properties>
<jmockit.version>1.21</jmockit.version>
<surefire.version>2.19.1</surefire.version>
</properties>
<dependencies>
<dependency>
<groupId>org.jmockit</groupId>
<artifactId>jmockit</artifactId>
<version>${jmockit.version}</version>
</dependency>
<dependency>
<groupId>org.jmockit</groupId>
<artifactId>jmockit-coverage</artifactId>
<version>${jmockit.version}</version>
</dependency>
<dependencies>
Good sources of information
Yelp has a website dedicated just for pre-commit, pre-commit.com. This goes to show how serious they are about good coding practices.
For more indepth learnings on the concepts as well as other git hooks, they are well explained by GitHooks and Atlassian.
Subscribe via RSS