/jgitver

jgit based library to calculate semver compatible version from git tree

Primary LanguageJavaApache License 2.0Apache-2.0

jgitver: git versioning library Build Status

The goal of jgitver is to provide a common way, via a library, to calculate a project semver compatible version from a git repository and the tags it contains. By doing so, it will then be easy to integrate it into build systems like maven, gradle or ant.

How it works

jgitver uses annotated tags, lightweight tags, branches names & commits to deduce the version of a particular git commit. From a given commit, a little bit like git describe command, jgitver walks thru the commit tree to retrieve tag(s) on ancestor commit(s). From there , depending on the configuration, a version will be deducted/calculated.

Simplicity & power

jgitver comes with default modes that follow best practices & conventions making it a no brainer to use with good defaults but you can configure it to work as you would like to.

versions, identifier & qualifiers

When computing versions, jgitver focuses on providing semver compatible versions.

  • version: as defined by semver, a serie of X.Y.Z where X, Y & Z are non-negative integers
  • identifier: a textual information following the version, build from alphanumeric characters & hyphen
  • qualifiers: qualifiers are textual information that can be combined to build a semver identifier

Quick examples

Before going into deep explanations & documentation let's first show what you will have when using jgitver on your git projects.

Using default configuration

Default configuration

Using default maven like configuration

Default maven like

Usage

Most of the time you will want to use jgitver via one of its extensions/plugins:

  • jgitver maven plugin, which can be used in its simplest form as:

    ...
      <build>
          <extensions>
              <extension>
                  <groupId>fr.brouillard.oss</groupId>
                  <artifactId>jgitver-maven-plugin</artifactId>
                  <version>X.Y.Z</version>
              </extension>
          </extensions>
         ...
      </build>
    ...
    

    find the latest version on maven central

  • jgitver gradle plugin which can be used using plugins DSL syntax:

    plugins {
      id "fr.brouillard.oss.gradle.jgitver" version "X.Y.Z"
    }
    

    find the latest version in gradle plugin portal

But of course, jgitver is a java library published on maven central and can be used as such.

package fr.brouillard.oss.jgitver;

import java.io.File;

public class UsageExample {
    /**
     * Display the calculated version of the working directory, using jgitver in mode 'maven like'.
     */
    public static void main(String[] args) throws Exception {
        File workDir = new File(System.getProperty("user.dir"));
        try (GitVersionCalculator jgitver = GitVersionCalculator.location(workDir).setMavenLike(true)) {
            System.out.println(jgitver.getVersion());
        }
    }
}

Concepts

Annotated tags

When the HEAD is on a git commit which contains an annotated tag that matches a version definition, this annotated tag is used to extract the version.

Lightweight tags

Lightweight tags are used by jgitver to better control the resulting version calculation (for example jump from 1.0.X scheme to 2.0.X starting from commit ABCDEF).

If you do not know the difference between lightweight & annotated tags, please refer to git documentation ; here is an extract of git tag man page.

Annotated tags are meant for release while lightweight tags are meant for private or temporary object labels. For this reason, some git commands for naming objects (like git describe) will ignore lightweight tags by default.

In contrary to annotated tags, Lightweight tags are considered by jgitver as ìndicators and will be used as a basis for other computation/calculations depending on the configuration:

  • adding SNAPSHOT qualifier
  • adding distance qualifier
  • adding SHA1 qualifier
  • ...

default version

When no suitable tag can be found in the commit history, then jgitver will consider that a virtual lightweight tag was found on first commit with a version 0.0.0.

Configuration, modes & strategies

Maven strategy

In this mode (which is the default mode of the jgitver maven plugin) activated by a call to GitVersionCalculator#setMavenLike(true), jgitver will:

  • on a DETACHED HEAD having an annotated tag, use the tag name without further computation
  • add SNAPSHOT qualifier to the calculated version
  • increase the patch version except if it comes from a lightweight tag
  • use annotated tags before lightweight ones when on a DETACHED HEAD
  • use lightweight tags before annotated ones when on a normal branch (master or any other branch)
  • add a branch qualifier on purpose

Parameters affecting this mode:

  • GitVersionCalculator#setNonQualifierBranches(String): comma separated list of branch name for which no branch qualifier will be used. Default value is master.

Default strategy

In this mode, which is the default one, jgitver will:

  • on a DETACHED HEAD having an annotated tag, use the tag name without further computation
  • use annotated tags before lightweight ones when on a DETACHED HEAD
  • use lightweight tags before annotated ones when on a normal branch (master or any other branch)
    • exception is when HEAD is on current branch, lightweight tags have precedence only when the repository is dirty
  • add a branch qualifier on purpose

Then depending on the configuration it will also:

  • GitVersionCalculator#setUseDistance(boolean): add distance from HEAD as a qualifer, default is true
  • GitVersionCalculator#setAutoIncrementPatch(boolean): increment the patch version except if it comes from a lightweight tag, default is false
  • GitVersionCalculator#setNonQualifierBranches(String): comma separated list of branch name for which no branch qualifier will be used. Default value is master.
  • GitVersionCalculator#setUseDirty(boolean): add "dirty" as a qualifier if the repository is stale (uncommited changes, new files, ...), default is false
  • GitVersionCalculator#setUseGitCommitId(boolean): add git commit HEAD SHA1 as a qualifier, default is false
  • GitVersionCalculator#setGitCommitIdLength(int): truncate the previous qualifier to the given length. Valid value must be between 8 & 40, default is 8

Versions naming & extraction

jgitver uses a pattern recognition in order to filter the tags it uses for any version computation.

The pattern used is the following (interpreted as java.util.regex.Pattern): `v?([0-9]+(?:.[0-9]+){0,2}(?:-[a-zA-Z0-9-_]+)?)``

For non regex experts basically it identifies:

  • dotted versions in the form MAJOR.MINOR.PATCH, where MAJOR, MINOR & PATCH are integers and having MINOR & PATCH as optional
  • followed optionally by a - (minus) sign and an identifier. The identifier can be interpreted by jgitver as a serie of qualifiers separated by the - (minus) sign
  • the version can be optionally preceded by the 'v' (letter V) character

Build & release

Normal build

  • mvn clean install

Release

  • mvn -Poss clean install: this will simulate a full build for oss delivery (javadoc, source attachement, GPG signature, ...)
  • git tag -a -s -m "release X.Y.Z, additionnal reason" X.Y.Z: tag the current HEAD with the given tag name. The tag is signed by the author of the release. Adapt with gpg key of maintainer.
    • Matthieu Brouillard command: git tag -a -s -u 2AB5F258 -m "release X.Y.Z, additionnal reason" X.Y.Z
    • Matthieu Brouillard public key
  • mvn -Poss,release -DskipTests deploy
  • git push --follow-tags origin master