Giter Club home page Giter Club logo

git-versioner-maven-extension's Introduction

Git Versioner Maven Plugin

Release Build Status GitHub

Generate the semver version using the git commit history and automatically set it to maven pom.

No more manually modifying the pom.xml to decide on the versions. You continue developing and adding commits to your project. When it is time to release, add a commit with a message containing a specific version keyword and watch the magic happen.

How does it work?

This extension iterates over all the commit history and looks for a predefined keywords representing version changes. It then computes the version number upto current commit.

The extension supports generating Semantic Versions x.y.z format. The format pattern is configurable to use values such as Git hash, branch name etc.

See manikmagar/git-versioner-maven-extension-examples for examples of using this extension.

What are version keywords?

Version keywords are the reserved words that describes which milestone of the release is this.

By default, extension supports following keywords -

  • [major] - A Major version milestone Eg. 1.0.0 → 2.0.0

  • [minor] - A Minor version milestone Eg. 1.1.0 → 1.2.

  • [patch] - A Patch version milestone Eg. 1.1.1 → 1.1.2

To change the keywords, see how to Customize Version Keywords.

How to configure?

This is a maven build core extension that can -

  • Participate in maven build lifecycle

  • Automatically set the building project’s version

  • No explicit mojo executions needed to set the version

  • Project’s POM remain unchanged

To use as a maven build extension,

Create (or modify) extensions.xml file in ${project.baseDir}/.mvn/ to have the following entry -

📎
The artifact id is git-versioner-maven-extension.
.mvn/extensions.xml
<extensions xmlns="http://maven.apache.org/EXTENSIONS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://maven.apache.org/EXTENSIONS/1.0.0 https://maven.apache.org/xsd/core-extensions-1.0.0.xsd">
    <extension>
        <groupId>com.github.manikmagar</groupId>
        <artifactId>git-versioner-maven-extension</artifactId>
        <version>${latest-version-here}</version>
    </extension>

</extensions>

With just that configuration, next time your project runs any maven goals, you should see version from this module is used by Maven reactor. Try running mvn package on your project.

How to start with a different version?

It is possible that your project is already released with a certain version. In that case, you can configure the initial version to start counting versions from.

You can add following properties to .mvn/git-versioner.extensions.properties file -

Example configuration for initial version for extension mode
gv.initialVersion.major=1
gv.initialVersion.minor=3
gv.initialVersion.patch=4

With above initial version configuration, the first version calculated by this extension will be -

  • Major: 2.0.0

  • Minor: 1.4.0

  • Patch: 1.3.5

How do I increment version?

Now that you have extension configured, you can continue with your regular development.

When it is time to increment version, you may use one of the following three goals to add an empty commit with appropriate Version Keyword -

  • git-versioner:commit-major: Adds a git commit with a commit message containing Major version keyword

  • git-versioner:commit-minor: Adds a git commit with a commit message containing Minor version keyword

  • git-versioner:commit-patch: Adds a git commit with a commit message containing Patch version keyword

🔥
Use --non-recursive flag when running commit goal in a multi-module maven project to avoid adding one commit per included module.

The default message pattern is chore(release): [%k] where [%k] is the keyword token. To change the default message pattern, you could pass -Dgv.commit.message=<message> argument when running the goal.

📎
When this extension is configured, it automatically makes git-versioner plugin goals available with NO any additional configuration.
Example commit patch with a custom message
mvn git-versioner:commit-patch "-Dgv.commit.message=chore: [%k] release" --non-recursive

Off course, you can also add commits manually with appropriate version keywords.

Manually adding a version commit
git commit --allow-empty -m "chore: [<keyword>] release" // (1)
  1. where <keyword> can be one of these - major, minor, or patch.

How to change the version pattern?

The default version pattern used is major.minor.patch(-commit) where (-commit) is skipped if commit count is 0.

This pattern can be canged by setting a property in .mvn/git-versioner.extensions.properties.

The following example will generate versions as major.minor.patch+shorthash, eg. 1.2.3+a5a29f8.

Example configuration for version pattern in extension mode
gv.pattern.pattern=%M.%m.%p+%h
Table 1. Available Tokens for Version Pattern
Token Description Example

%M

Major Version

1.y.z

%m

Minor Version

x.1.z

%p

Patch Version

x.y.1

%c

Commit count

x.y.z-4

([anything]%c)

Non-Zero Commit count

Given %M.%m.%p(-%c) with %M=1, %m=2, %p=3

when c == 0 → 1.2.3

when c > 0, = 5 → 1.2.3-5

%b

Branch name

%M.%m.%p+%b1.2.3+main

%H

Long Hash Ref

%M.%m.%p+%H1.2.3+b5f600c40f362d9977132e8bf7398d2cdc745c28

%h

Short Hash Ref

%M.%m.%p+%H1.2.3+a5a29f8

How to customize version keywords?

The default version keywords [major], [minor], and [patch] can be customized by overriding the configuration.

To use different keywords, you can add following properties to .mvn/git-versioner.extensions.properties file -

Example configuration for initial version for extension mode
gv.keywords.majorKey=[BIG]
gv.keywords.minorKey=[SMALL]
gv.keywords.patchKey=[FIX]

Use regex for version keywords

You can also use regex to match version keywords. This is useful when you want to be sure that the version keyword will only be matched when it is the first word in the commit message. So if for example you have a merge commit message which contains the messages of the merged commits, you can use a regex to match only the first commit message.

To use regex for version keywords, you can add following properties to .mvn/git-versioner.extensions.properties file -

Example configuration for regex version keywords
gv.keywords.useRegex=true
gv.keywords.majorKey=^\\[major\\].*
gv.keywords.minorKey=^\\[minor\\].*
gv.keywords.patchKey=^\\[patch\\].*

How to access generated version properties?

This extension adds all version properties to Maven properties during build cycle -

Example of Injected maven properties (demo values)
git-versioner.commitNumber=0
git-versioner.major=0
git-versioner.minor=0
git-versioner.patch=1
git-versioner.version=0.0.1
git.branch=main
git.hash=67550ad6a64fe4e09bf9e36891c09b2f7bdc52f9
git.hash.short=67550ad

You may use these properties in maven pom file, for example as ${git.branch} to access git branch name.

How to create Git tags?

You can use git-versioner:tag goal to create a git tag for current version in local git repository.

📎
This does not push tag to remote repository.
Tag goal with default parameter values
mvn git-versioner:tag \
  "-Dtag.failWhenTagExist=true" \
  "-Dtag.messagePattern=Release version %v" \
  "-Dtag.namePattern=v%v"

For Tag goal, it is possible to configure pom.xml to contain the git-versioner plugin with required execution configuration.

Git Tag Goal with default configuration parameters
<plugin>
    <groupId>com.github.manikmagar</groupId>
    <artifactId>git-versioner-maven-plugin</artifactId>
    <executions>
      <execution>
        <id>tag</id>
        <goals>
          <goal>tag</goal>
        </goals>
        <configuration>
          <failWhenTagExist>true</failWhenTagExist> // (1)
          <tagNamePattern>v%v</tagNamePattern>  // (2)
          <tagMessagePattern>Release version %v</tagMessagePattern> // (3)
        </configuration>
      </execution>
    </executions>
</plugin>
  1. If set to not fail, it will just log warning and skip tag creation.

  2. Tag name pattern to use. Default v%v will result in tags like v1.2.3.

  3. Tag message pattern to use. Default Release version %v will add tag message like Release version 1.2.3.

Contributing

All contributions are welcome. Please see Contributing guides.

Acknowledgement

This is inspired from Gradle plugin toolebox-io/gradle-git-versioner that I have been using for my Gradle projects. This maven plugin is my attempt to get those auto-version capabilities into my Maven builds.

git-versioner-maven-extension's People

Contributors

bjsee avatar dependabot[bot] avatar manikmagar avatar olivier-hubaut avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

git-versioner-maven-extension's Issues

Plugin does not work with IntelliJ

When loading a project that has this extension in IntelliJ, it fails with the following message:

No HEAD exists and no explicit starting revision was specified

Looking in the logs of IntelliJ, we can see the following stacktrace:

2023-05-16 08:47:05,811 [  62395]   INFO - #o.j.i.maven - com.github.manikmagar.maven.versioner.core.GitVersionerException: One of setGitDir or setWorkTree must be called.
	at com.github.manikmagar.maven.versioner.core.git.JGit.executeOperation(JGit.java:21)
	at com.github.manikmagar.maven.versioner.core.git.JGitVersioner.version(JGitVersioner.java:23)
	at com.github.manikmagar.maven.versioner.extension.GitVersionerModelProcessor.processModel(GitVersionerModelProcessor.java:90)
	at com.github.manikmagar.maven.versioner.extension.GitVersionerModelProcessor.read(GitVersionerModelProcessor.java:64)
	at org.apache.maven.model.building.DefaultModelBuilder.readModel(DefaultModelBuilder.java:552)
	at org.apache.maven.model.building.DefaultModelBuilder.build(DefaultModelBuilder.java:257)
	at org.apache.maven.model.building.DefaultModelBuilder.build(DefaultModelBuilder.java:243)
	at org.apache.maven.project.DefaultProjectBuilder.build(DefaultProjectBuilder.java:175)
	at org.apache.maven.project.DefaultProjectBuilder.build(DefaultProjectBuilder.java:122)
	at org.jetbrains.idea.maven.server.Maven3ServerEmbedder.buildSinglePom(Maven3ServerEmbedder.java:198)
	at org.jetbrains.idea.maven.server.Maven3ServerEmbedder.getProjectBuildingResults(Maven3ServerEmbedder.java:167)
	at org.jetbrains.idea.maven.server.Maven3XServerEmbedder.lambda$doResolveProject$2(Maven3XServerEmbedder.java:866)
	at org.jetbrains.idea.maven.server.Maven3ServerEmbedder$1.run(Maven3ServerEmbedder.java:366)
	at org.jetbrains.idea.maven.server.Maven3ServerEmbedder.executeWithSessionScope(Maven3ServerEmbedder.java:441)
	at org.jetbrains.idea.maven.server.Maven3ServerEmbedder.executeWithMavenSession(Maven3ServerEmbedder.java:374)
	at org.jetbrains.idea.maven.server.Maven3ServerEmbedder.executeWithMavenSession(Maven3ServerEmbedder.java:363)
	at org.jetbrains.idea.maven.server.Maven3XServerEmbedder.doResolveProject(Maven3XServerEmbedder.java:849)
	at org.jetbrains.idea.maven.server.Maven3XServerEmbedder.resolveProject(Maven3XServerEmbedder.java:798)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:360)
	at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200)
	at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197)
	at java.base/java.security.AccessController.doPrivileged(AccessController.java:712)
	at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196)
	at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:587)
	at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:828)
	at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:705)
	at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
	at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:704)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
	at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: java.lang.IllegalArgumentException: One of setGitDir or setWorkTree must be called.
	at org.eclipse.jgit.lib.BaseRepositoryBuilder.requireGitDirOrWorkTree(BaseRepositoryBuilder.java:636)
	at org.eclipse.jgit.lib.BaseRepositoryBuilder.setup(BaseRepositoryBuilder.java:600)
	at org.eclipse.jgit.storage.file.FileRepositoryBuilder.build(FileRepositoryBuilder.java:55)
	at com.github.manikmagar.maven.versioner.core.git.JGit.executeOperation(JGit.java:16)
	... 34 more

Which break the whole integration with Maven.

It looks like, when invoked from IntelliJ, JGit is unable to find the .git folder. Probably because the Maven3XServerEmbedder class is ran from outside the working folder.

I see that in the JGit#findGitDir method, the basePath is built from the mavenProject basedir information. I think the same principle could be used in the JGit#executeOperation method.

Create git tags

Add a plugin goal to create a git tag in local repository with current computed version.

does not work on java 8

This extension does not run when used in Java 8. Adding an extension entry in extensions.xml will not show any issues at execution time but it won't execute either.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.