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.
- 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
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 {
// ...
}
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. | . |
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 |
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.
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
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.
bld also has a Generated Version extension which provides similar functionalities.
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.
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
.
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.
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.absolutePath)
}
}
The directory containing the configuration files (version.properties
, version.mustache
) must be specified using the semver.project.dir
processor argument.
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.
If you want to contribute to this project, all you have to do is clone the GitHub repository:
git clone git@github.com:ethauvin/semver.git
Then use bld to build:
cd semver
./bld compile
The project has an IntelliJ IDEA project structure. You can just open it after all the dependencies were downloaded and peruse the code.