15 KiB
Semantic Version Annotation Processor
An annotation processor that automatically generates a GeneratedVersion
class based on a Mustache template and containing the semantic version (major, minor, patch, etc.) that is read from a Properties file or defined in the annotation.
This processor was inspired by Cédric Beust's version-processor and works well in conjunction with the Semantic Version Plugin for Gradle.
Table of Contents
Examples
- Using annotation elements:
import net.thauvin.erik.semver.Version;
@Version(major = 2, minor = 1, patch = 1, preRelease = "beta")
public class A {
// ...
}
- Or using a properties file:
import net.thauvin.erik.semver.Version;
@Version(properties = "version.properties")
public class A {
// ...
}
# version.properties
version.major=1
version.minor=0
version.patch=0
version.prerelease=beta
Template
Upon running the annotation processor, a source file GeneratedVersion.java is automatically generated with static methods to access the semantic version data. The source is based on a fully customizable Mustache template.
To use your own template, simply create a version.mustache
file in the project's root directory. The processor will automatically look for it.
To specify your own template name, use:
@Version(template = "version.mustache")
public class A {
// ...
}
Default Template
The default template implements the following static variables:
Field | Description | Example |
---|---|---|
PROJECT |
The project name, if any. | MyProject |
BUILDDATE |
The build date. | java.util.Date |
VERSION |
The full version string. | 1.2.3-alpha+001 |
MAJOR |
The major version. | 1 |
MINOR |
The minor version. | 2 |
PATCH |
The patch version. | 3 |
PRERELEASE |
The pre-release version, if any. | alpha |
PRERELASE_PREFIX |
The pre-release prefix | - |
BUILDMETA |
The build metadata, if any. | 001 |
BUILDMETA_PREFIX |
The metadata prefix. | + |
SEPARATOR |
The version separator. | . |
Custom Template
A very simple custom template might look something like:
/* version.mustache */
package {{packageName}};
import java.util.Date;
public final class {{className}} {
public final static String PROJECT = "{{project}}";
public final static Date DATE = new Date({{epoch}}L);
public final static String VERSION = "{{semver}}";
}
The mustache variables automatically filled in by the processor are:
Variable | Description | Type |
---|---|---|
{{packageName}} |
The package name. | String |
{{className}} |
The class name. | String |
{{project}} |
The project name. | String |
{{epoch}} |
The build epoch/unix time. | long |
{{major}} |
The major version. | int |
{{minor}} |
The minor version. | int |
{{patch}} |
The patch version. | int |
{{preRelease}} |
The pre-release version. | String |
{{preReleasePrefix}} |
The pre-release prefix. | String |
{{buildMeta}} |
The build metadata version. | String |
{{buildMetaPrefix}} |
The metadata prefix. | String |
{{separator}} |
The version separator. | String |
{{semver}} or {{version}} |
The full semantic version. | String |
Please also look at this example using java.time
Elements & Properties
The following annotation elements and properties are available:
Element | Property | Description | Default |
---|---|---|---|
project |
version.project |
The project name. | |
major |
version.major |
The major version number. | 1 |
minor |
version.major |
The minor version number. | 0 |
patch |
version.patch |
The patch version number. | 0 |
preRelease |
version.prerelease |
The pre-release version. | |
preReleasePrefix |
version.prerelease.prefix |
The pre-release prefix. | - |
buildMeta |
version.buildmeta |
The build metadata version. | |
buildMetaPrefix |
version.buildmeta.prefix |
The metadata prefix. | + |
separator |
version.separator |
The version separator. | . |
packageName |
The package name. | Same as annotated class | |
className |
The name of the generated class. | GeneratedVersion |
|
properties |
The properties file. | ||
template |
The template file. | version.mustache |
|
type |
Either java or kt for Kotlin. |
java |
|
keysPrefix |
The prefix for all property keys. | version. |
In order to easily incorporate with existing projects, the property keys may be assigned custom values:
@Version(
properties = "example.properties",
keysPrefix = "example.",
majorKey = "maj",
minorKey = "min",
patchKey = "build",
preReleaseKey = "rel",
buildMetaKey = "meta",
projectKey = "project"
)
public class Example {
// ...
}
# example.properties
example.project=Example
example.maj=1
example.min=0
example.build=0
example.rel=beta
example.meta=
# ...
⚠️
keysPrefix
is a new element staring in1.1.0
and may break older versions when using custom property keys.
⚡ A quick fix is to includekeysPrefix=""
in the annotation to remove the defaultversion.
prefix.
Maven
To install and run from Maven, configure an artifact as follows:
<dependency>
<groupId>net.thauvin.erik</groupId>
<artifactId>semver</artifactId>
<version>1.2.1</version>
</dependency>
Please look at pom.xml in the examples/java directory for a sample:
mvn verify
bld
To install and run from bld, just add the dependency to your build file:
public class ExampleBuild extends Project {
public ExampleBuild() {
// ...
scope(compile)
.include(dependency("net.thauvin.erik", "semver", version(1, 2, 1)));
}
}
Please look at ExampleBuild in the examples/java/bld directory for a sample. It also shows how to incorporate the generated code into the source tree
, more information is also available here.
Gradle
Class Generation
To install and run from Gradle, add the following to build.gradle:
repositories {
mavenCentral()
}
dependencies {
annotationProcessor 'net.thauvin.erik:semver:1.2.1'
compileOnly 'net.thauvin.erik:semver:1.2.1'
}
tasks.withType(JavaCompile).configureEach {
options.compilerArgs += [ "-Asemver.project.dir=$projectDir" ]
}
The directory containing the configuration files (version.properties
, version.mustache
) must be specified using the semver.project.dir
processor argument.
The GeneratedVersion.java
class will be automatically created in the build/generated
directory upon compiling.
Please look at build.gradle in the examples/java/gradle directory for a sample.
Class & Source Generation
In order to also incorporate the generated source code into the source tree
, add the following to build.gradle:
tasks.withType(JavaCompile).configureEach {
options.generatedSourceOutputDirectory.set(file("${projectDir}/src/generated/java"))
}
The GeneratedVersion.java
file will now be located in src/generated
.
Kotlin
The annotation processor also supports Kotlin.
To generate a Kotlin version file, simply specify the type
as follows:
import net.thauvin.erik.semver.Version
@Version(properties = "version.properties", type="kt")
open class Main {
// ...
}
The Kotlin default template implements the same static fields and functions as the Java template.
Please look at the examples/kotlin project for a build.gradle.kts sample.
Kotlin & Gradle
To install and run from Gradle, add the following to build.gradle.kts:
var semverProcessor = "net.thauvin.erik:semver:1.2.1"
dependencies {
kapt(semverProcessor)
compileOnly(semverProcessor)
}
kapt {
arguments {
arg("semver.project.dir", projectDir)
}
}
The directory containing the configuration files (version.properties
, version.mustache
) must be specified using the semver.project.dir
processor argument.
Auto-Increment
Incrementing the version is best left to your favorite build system. For a solution using Gradle, please have a look at the Semver Version Plugin for Gradle.
There are also full examples in both Java and Kotlin showing how to use both the plugin and annotation processor concurrently.