-
Notifications
You must be signed in to change notification settings - Fork 89
Release Plugins
One of the primary features of gradle-git
is the pair of release plugins that allow you to infer your project's version and manage the tasks executed for your release process.
There are two plugins included:
-
org.ajoberstar.release-base
Provides the basic functionality, but you configure how versions are inferred. -
org.ajoberstar.release-opinion
Adds an opinionated set of strategies to infer your project's version.
plugins {
// if you want to use the opinionated config
id 'org.ajoberstar.release-opinion' version '<version>'
// if you want to configure it to your preferences
id 'org.ajoberstar.release-base' version '<version>'
}
// if you want to use the opinionated config
apply plugin: 'org.ajoberstar.release-opinion'
// if you want to configure it to your preferences
apply plugin: 'org.ajoberstar.release-base'
NOTE: Either plugin should only be applied to one project as it will apply the inferred version to all projects in the build.
- Configures the project's version based on the inference strategies you (or the opinion plugin) configure.
- Version isn't inferred until it's used (i.e.
project.version.toString()
is called)
- Version isn't inferred until it's used (i.e.
- Adds a
release
task that:- Tags the version, if the inference strategy calls for it.
- Pushes the current branch and all tags to the origin.
Generally you will want to execute other tasks, such as build
, uploadArchives
, and/or publish*
tasks. Use standard Gradle dependencies and task ordering to handle this.
tasks.release.dependsOn 'build', 'publishToMyRepo'
Execute the release task and (optionally, as noted below) specify the release.scope
and/or release.stage
properties.
./gradlew release -Prelease.scope=major -Prelease.stage=final
Have you ever seen a commit message simply say "Bumping version number"? I imagine everyone has, but there's really no good reason for it.
While most build tools encourage (or force) you to hardcode your version number into the build script, Git illustrates the power of basing the version on your VCS tags, with the git describe
command, which reflects the amount of change since the previous tag (e.g. 0.1.0-22-g26f678e
).
This plugin leverages Git tags as the baseline your version is computed from.
While this plugin provides more general support, it has the most support for Semantic Versioning. SemVer provides a specific meaning to the difference between two version numbers, helping a consumer understand what scope of impact they should expect when upgrading.
A semantic version consists of <normal>[-<pre release>][+<build metadata>]
(e.g. 1.2.3-rc.2+abcde1234). The normal component consists of <major>.<minor>.<patch>
.
After applying the plugin as noted at the top of this doc, your project will be ready to infer semantic versions based on the nearest tag and the release.scope
and/or release.stage
properties you can pass into your build.
Versions will fall into one of the following stages:
Name | Creates Tag | Requires Clean Repo | Example |
---|---|---|---|
final | yes | yes | 1.0.0 |
rc | yes | yes | 1.1.0-rc.1 |
milestone | yes | yes | 1.2.0-milestone.2 |
dev | no | no | 1.3.0-dev.5+ae2dfa2 or 1.3.0-dev.5.uncommitted+ae2dfa2 or 1.3.0-milestone.1.dev.5+ae2dfa2 |
Additionally, if you provide no input (via the release.*
properties) and have not made any changes since the last tagged version, that version will be reused.
As an example this walks you through a series of Gradle executions. A few things of note:
- You don't need to use the
release
task to get version inference. - Without a scope input, it will detect it from the difference from the last final release and the last tagged one (e.g. a milestone of a minor version will default you to minor). If nothing detected, it will default to patch.
- Without a stage input, it will default to dev (assuming you've made changes since the last tagged version).
Repo State | Latest Version Tag | Gradle Command (w/ gradle or gradlew in front) |
Inferred Version |
---|---|---|---|
3 commits and some uncommitted changes | None | test | 0.0.1-dev.3.uncommitted+ae2dfa2 |
Ready to release a milestone | None | release -Prelease.scope=minor -Prelease.stage=milestone | 0.1.0-milestone.1 |
More commits, no uncommitted | 0.1.0-milestone.1 | test | 0.1.0-milestone.1.dev.2+5612df0 |
A couple more commits, want to publish | 0.1.0-milestone.1 | release -Prelease.stage=dev | 0.1.0-milestone.1.dev.4+029b57e |
Ready for another milestone | 0.1.0-milestone.1 | release -Prelease.stage=milestone | 0.1.0-milestone.2 |
Rebuilding on another machine | 0.1.0-milestone.2 | build | 0.1.0-milestone.2 |
ready for an rc | 0.1.0-milestone.2 | release -Prelease.stage=rc | 0.1.0-rc.1 |
some uncommitted changes for a fix | 0.1.0-rc.1 | build | 0.1.0-rc.1.dev.0.uncommitted+9686285 |
commit the fix and another rc | 0.1.0-rc.1 | release -Prelease.stage=rc | 0.1.0-rc.2 |
ready for final release | 0.1.0-rc.2 | release -Prelease.stage=final | 0.1.0 |
making a bug fix | 0.1.0 | release -Prelease.stage=rc | 0.1.1-rc.1 |
fix is ready for final | 0.1.1-rc.1 | release -Prelease.scope=patch -Prelease.stage=final | 0.1.1 |
more commits, with major changes | 0.1.1 | release -Prelease.scope=major -Prelease.stage=milestone | 1.0.0-milestone.1 |
final of this | 1.0.0-milestone.1 | release -Prelease.stage=final | 1.0.0 |
rc of minor change | 1.0.0 | release -Prelease.scope=minor -Prelease.stage=rc | 1.1.0-rc.1 |
that minor was actually breaking | 1.1.0-rc.1 | release -Prelease.scope=major -Prelease.stage=rc | 2.0.0-rc.1 |
If you don't want to use the opinionated config, you can apply org.ajoberstar.release-base
instead and configure it using the extension.
release {
// if you don't apply org.ajoberstar.grgit, you need to specify the repository to interact with
grgit = Grgit.open(currentDir: project.file('.'))
/*
* Base plugin adds no strategies.
* Opinion plugin adds:
* RebuildVersionStrategy.INSTANCE
* Strategies.DEVELOPMENT
* Strategies.PRE_RELEASE
* Strategies.FINAL
*/
// add your own choices from some pre-configured samples
versionStrategy RebuildVersionStrategy.INSTANCE
versionStrategy Strategies.SNAPSHOT
versionStrategy Strategies.PRE_RELEASE_ALPHA_BETA
versionStrategy Strategies.FINAL
// add your own custom strategy
versionStrategy(new CustomVersionStrategy())
// the approach to creating tags can also be modified
tagStrategy {
prefixNameWithV = false // defaults to true
generateMessage = { version -> "My new version $version.version" }
}
}
Additional pre-built strategies are available in Strategies (source).
There are certainly other options than gradle-git
for Gradle release plugins. Here are the ones that I am aware of:
- townsfolk/gradle-release - designed to work like the Maven Release plugin. If that's what you are looking for, this is your best option.
- ari/gradle-release-plugin - Seems purely oriented around versioning the release and tagging it. Versions are generated dynamically based on current branch or tag.
-
stianh/gradle-release-plugin - Similar approach (and created before) the
ari
plugin. However, as of 4/13/14 it hasn't had any commits in 9 months. -
netzwerg/gradle-release-plugin - Minimal plugin which operates on semantic version kept in
version.txt
file. Updates version, tags repo, pushes current branch ("no surprise" defaults, fully configurable). Runs non-interactively, thus well suited for CI.