Introducing the Maven git commit id Plugin
Have you ever had the problem of not knowing which version of your application was deployed on, for example, a test environment? Or have you had to manually adapt version information for each release in order to make it available in an About-dialog? Then the Maven git commit id plugin has come to the rescue! In this post, we will build a Spring Boot application with a RESTful web service for retrieving versioning information. The only thing we will have to do is to configure the Maven git commit id plugin and create the web service. After this, versioning information is automatically updated during each build!
Create a Spring Boot Application
First, we create a basic Spring Boot application with a RESTful web service for retrieving manually entered version information. JDK9 and modules are used, so we will encounter some 'problems' along the way. But these will be tackled also!
We create the VersionController class, which has hard-coded version information in it. We will replace it later on with the information retrieved from the git commit id plugin.
package com.mydeveloperplanet.mygitcommitidplanet;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import static org.springframework.web.bind.annotation.RequestMethod.GET;
@RestController
public class VersionController {
@RequestMapping("/version", method= GET)
public String versionInformation() {
return "Version 1.0-SNAPSHOT";
}
}
Add the entry point for the Spring Boot application in an Application.java class:
package com.mydeveloperplanet.mygitcommitidplanet;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Build the application with a clean install. The module-info.java file must be the following:
module com.mydeveloperplanet.mygitcommitidplanet {
requires spring.web;
requires spring.boot;
requires spring.boot.autoconfigure;
}
Building the application gave the following error:
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-jar-plugin:2.6:jar (default-jar) on project mygitcommitidplanet: Execution default-jar of goal org.apache.maven.plugins:maven-jar-plugin:2.6:jar failed: An API incompatibility was encountered while executing org.apache.maven.plugins:maven-jar-plugin:2.6:jar: java.lang.ExceptionInInitializerError: null
This is solved by using version 3.0.2 of the maven jar plugin. Add the following to the plugin section of the pom.xml:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
</plugin>
Run the application with the following command from the root of the project:
java -jar target/mygitcommitidplanet-1.0-SNAPSHOT.jar
Starting the application, the following warning is shown:
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.springframework.cglib.core.ReflectUtils$1...
It appears to be a known problem, see SPR-15859.
Go to your browser and enter the URL http://localhost:8080/version. As expected, the hard-coded value is returned:
Version 1.0-SNAPSHOT
git commit id Plugin
Now that we have everything in place, we can start adding the git commit id plugin. Detailed information of all properties can be found on the GitHub repository of the git commit id plugin.
Enable git commit id
Add the following to the plugin section of the POM file:
<plugin>
<groupId>pl.project13.maven</groupId>
<artifactId>git-commit-id-plugin</artifactId>
<version>2.2.4</version>
<executions>
<execution>
<id>get-the-git-infos</id>
<goals>
<goal>revision</goal>
</goals>
</execution>
</executions>
<configuration>
<dotGitDirectory>${project.basedir}/.git</dotGitDirectory>
<prefix>git</prefix>
<verbose>false</verbose>
<generateGitPropertiesFile>true</generateGitPropertiesFile>
<generateGitPropertiesFilename>${project.build.outputDirectory}/git.properties</generateGitPropertiesFilename>
<format>json</format>
<gitDescribe>
<skip>false</skip>
<always>false</always>
<dirty>-dirty</dirty>
</gitDescribe>
</configuration>
</plugin>
Run the Maven build. In the directory target/classes, the git.properties file is added with the version information in JSON format.
{
"git.branch" : "master",
"git.build.host" : "LT0265",
"git.build.time" : "2018-01-21T17:34:26+0100",
"git.build.user.email" : "gunter@mydeveloperplanet.com",
"git.build.user.name" : "Gunter Rotsaert",
"git.build.version" : "1.0-SNAPSHOT",
"git.closest.tag.commit.count" : "",
"git.closest.tag.name" : "",
"git.commit.id" : "6f592254e2e08d99a8145f1295d4ba3042310848",
"git.commit.id.abbrev" : "6f59225",
"git.commit.id.describe" : "6f59225-dirty",
"git.commit.id.describe-short" : "6f59225-dirty",
"git.commit.message.full" : "Created basic Spring Boot application with webservice for retrieving hard-coded version information",
"git.commit.message.short" : "Created basic Spring Boot application with webservice for retrieving hard-coded version information",
"git.commit.time" : "2018-01-21T17:33:13+0100",
"git.commit.user.email" : "gunter@mydeveloperplanet.com",
"git.commit.user.name" : "Gunter Rotsaert",
"git.dirty" : "true",
"git.remote.origin.url" : "https://github.com/mydeveloperplanet/mygitcommitidplanet.git",
"git.tags" : ""
}
Now take a closer look at the mygitcommitidplanet-1.0-SNAPSHOT.jar file. In the directory BOOT-INF/classes, the file git.properties is available. At this point, we already have what we want: versioning information is included in our deliverable. We can always look inside the JAR file to find out what the exact version information of the sources was for this deliverable.
Add Version Information to the RESTful Web Service
The next step is to replace the hard-coded version information from our RESTful web service with the contents of the git.properties file. Since the git.properties file is already in JSON format, the only thing we have to do is to read the contents of the file and return it in our web service.
Our VersionController.java file becomes the following:
@RequestMapping(value = "/version", method = GET)
public String versionInformation() {
return readGitProperties();
}
private String readGitProperties() {
ClassLoader classLoader = getClass().getClassLoader();
InputStream inputStream = classLoader.getResourceAsStream("git.properties");
try {
return readFromInputStream(inputStream);
} catch (IOException e) {
e.printStackTrace();
return "Version information could not be retrieved";
}
}
private String readFromInputStream(InputStream inputStream)
throws IOException {
StringBuilder resultStringBuilder = new StringBuilder();
try (BufferedReader br = new BufferedReader(new InputStreamReader(inputStream))) {
String line;
while ((line = br.readLine()) != null) {
resultStringBuilder.append(line).append("\n");
}
}
return resultStringBuilder.toString();
}
Build with Maven and run the application. Again, go to the URL http://localhost:8080/version. The contents of our git.properties file is shown.
This is exactly what we wanted: The version information can be retrieved at any moment and is always up-to-date. If you have a client application, e.g. a browser application, it is easy to use this information in an About-section.
Validating git properties
It is also possible to add validation to the git.properties file when you want to restrict the format. The build will fail if it does not met the validation configuration. We are now going to add a validation in order to let the build fail when the repository is dirty.
First, we add a ValidationProperties section to the configuration section in our pom.xml file:
<validationProperties>
<!-- verify that the current repository is not dirty -->
<validationProperty>
<name>validating git dirty</name>
<value>${git.dirty}</value>
<shouldMatchTo>false</shouldMatchTo>
</validationProperty>
</validationProperties>
Secondly, we have to activate the validation. This is done in the executions section of the git-commit-id plugin:
<execution>
<id>validate-the-git-infos</id>
<goals>
<goal>validateRevision</goal>
</goals>
<phase>package</phase>
</execution>
I did not commit the changes I have made to the pom.xml file yet, so my repository is dirty. Build the application with Maven. As expected, the build fails with the following error:
Validation 'validating git dirty' failed! Expected 'true' to match with 'false'!
If we now change the shouldMatchTo to true and run the build again, the build is successful.
Summary
The Maven git commit id plugin is indispensable and should be added to each Maven project. It automatically creates the versioning information during a build so that you are able to verify the versioning information when an application is deployed. No discussions anymore about which version of the software is running on an environment.