Skip to content

Gradle plugin that helps automating releases by automatically deducting the next Semver version

License

Notifications You must be signed in to change notification settings

shestee/shipkit-auto-version

 
 

Repository files navigation

CI Gradle Plugin Portal


Shipkit Plugins

Vision

Software developers spend all their creative energy on productive work. There is absolutely zero release overhead because all software is released automatically.

Mission

Encourage and help software developers set up their releases to be fully automated.

shipkit-auto-version Gradle Plugin

Our Gradle plugin shipkit-auto-version deducts the version for the Gradle project to streamline continuous delivery. You drop a version.properties file to your repo with content like version=1.0.*. The plugin will resolve the * part of the version based on the latest release tag and the number of commits. This way you can set up the project for continuous delivery and release every merged pull request with nicely incremented version. No more infamous "version bump" commits in every release!

shipkit-auto-version plugin is tiny and has a single dependency on jSemver. It is a safe dependency because it is tiny, has no dependencies, and it is final (no code changes since 2015 - it wraps semver protocol that had no changes since 2013).

Do you want to automate changelog generation? Check out shipkit-changelog plugin that neatly integrate with shipkit-auto-version plugin.

Customers / sample projects

Usage

  1. Apply org.shipkit.shipkit-auto-version to the root project. Use the highest version available in the Gradle Plugin Portal Gradle Plugin Portal
plugins {
  id "org.shipkit.shipkit-auto-version" version "x.y.z"
}
  1. Create version.properties file and drop it to your project root. The contents should contain the version spec, and optionally, the tag prefix.
version=1.0.*

You may optionally specify the tag prefix, our default is "v" for tags like "v1.2.3". To use "no prefix" convention (e.g. tags like "1.2.3") please use an empty value: tagPrefix=

version=1.0.*
#tag prefix is optional, the default is "v", empty value means no prefix
tagPrefix=release-
  1. For your CI, make sure that all tags are fetched (see the next section)

  2. Prosper! When running Gradle the plugin will resolve * part of the version and set this value on the Gradle's project.

Fetch depth on CI

CI systems are often configured by default to perform Git fetch with minimum amount of commits/tags. However, our plugin needs tags in order to generate the release notes. When using GH actions, please configure your checkout action to fetch the entire history. Based on our tests in Mockito project, the checkout of the entire Mockito history (dating 2008) has negligible performance implication (adds ~2 secs to the checkout).

- uses: actions/checkout@v2   # docs: https://github.com/actions/checkout
  with:
    fetch-depth: '0' # will fetch the entire history

Properties exposed by the plugin

shipkit-auto-version.previous-version

This plugin exposes an 'ext' property shipkit-auto-version.previous-version that can be used to get access to the previous version. Example:

println project.ext.'shipkit-auto-version.previous-version'

shipkit-auto-version.previous-tag

Shipkit Auto Version exposes also shipkit-auto-version.previous-tag 'ext' property that gives access to the previous version's tag. It allows to get previous revision in convenient way (eg. for generating changelog with Shipkit Changelog plugin as in example below). Example:

tasks.named("generateChangelog") {
   previousRevision = project.ext.'shipkit-auto-version.previous-tag'
   //...
}

Version Overriding

It is sometimes useful to manually specify the version when building / publishing (e.g. to publish a -SNAPSHOT locally). This can be done by setting the gradle project version on the command line with the -Pversion flag, e.g. ./gradlew publishToMavenLocal -Pversion=1.0.0-SNAPSHOT.

Implementation details

When the plugin is applied to the project it will:

  • load the version spec from version.properties

    • if the gradle project already has a set version (e.g. from the command line), use that version
    • if no file or wrong format fail
    • if the spec does not contain the wildcard '*', we just use the version "as is" and return
    • if the spec has wildcard '*' patch version, we resolve the wildcard value from tags and commits:
  • run git tag

    • look for typical "version" tags in Git output (e.g. "v1.0.0", "v2.5.100")
    • identifies the latest (newest) version matching version spec
    • compares the version with the version spec:
case spec latest tag -Pversion # of commits result description
a 1.0.* v1.0.5 0 1.0.5 zero new commits
b 1.0.* v1.0.5 2 1.0.7 two new commits
c 1.0.* v1.0.5 5 (2 merge + 1) 1.0.8 two merge commits and new one on top
d 1.1.* v1.0.5 5 1.1.0 first x.y.0 version
e 2.0.* v1.0.5 5 2.0.0 first z.0.0 version
f 1.*.5 error unsupported format
g 1.0.* v1.0.5 1.0.10-SNAPSHOT [any] 1.0.10-SNAPSHOT version overridden from CLI argument
  • in case a),b) we are resolving the wildcard based on # of commits on top of the tag

    • run git log to identify # of commits
    • add commit count to the patch version value from the latest tag
    • viola! we got the version to use!
  • in case c) we have following situation (git log output):

    • 64e7eb517 Commit without a PR
    • 2994de4df Merge pull request #123 from mockito/gradle-wrapper-validation
    • 67bd4e96c Adds Gradle Wrapper Validation
    • 64e7eb517 Merge pull request #99 from mockito/ongoing-stubbing
    • dd8b07887 Add OngoingStubbing
    • 084e8af18 (tag: v1.0.5) Merge pull request #88 from mockito/mockito-88

    On top of v1.0.5 tag there are 5 commits, i.e. 2 merge commits (64e7eb517 and 2994de4df) and 1 new commit (64e7eb517) without Pull Request on top. The patch version will be 8 i.e. 5 plus a sum of those two numbers.

  • in case d),e) use '0' as patch version

  • in case g) the user manually specified the version on the command line

Similar plugins

There are other plugins out there that are similar:

  1. Below plugins are great, but they (mostly) require to push a tag to make a release. Our plugin can release every change.
  1. Below plugin can release every change, but the resulting version is not as nice (e.g. 1.0.0+3bb4161). The plugin has many features and thus is much more complex than our plugin.

Use the plugin that works best for you and push every change to production!

Discussion about this use case: mockito/shipkit#395

Contributing

This project loves contributions! For more info how to work with this project check out the contributing section in the sibling plugin shipkit-changelog.

About

Gradle plugin that helps automating releases by automatically deducting the next Semver version

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Java 51.6%
  • Groovy 48.4%