-
Notifications
You must be signed in to change notification settings - Fork 3
Defining Rules
Rules are defined using the rules
DSL inside the gitVersion
extension. It can be used either as a
property, or in "block" mode using a closure:
gitVersion.rules.onBranch( ... ) { ... }
gitVersion {
rules {
onBranch (...) { ... }
}
}
Different types of rules match under certain conditions. When determining the version, all rules are taken into
consideration in the order of their appearance (with the exception of before
and after
rules, see below).
For each rule whose condition matches, the body will be evaluated.
This is the most important type of rule, because you will usually want to follow different scenarios based on the branch that is currently checked out. For example, when building from the master or a feature branch, you may want a suffix (called a "prerelease tag" in the SemVer spec) appended to the version, whereas for a release
The first argument to onBranch
can either be a string or a regular expression. If the argument is a
string, the rule body will be evaluated if the current branch name exactly matches the argument. The string is
not interpreted as a regular expression.
gitVersion.rules {
onBranch ('master') {
println 'on master branch!'
}
}
If the argument is a Pattern
, then the rule body will be evaluated if the current branch name matches the pattern.
Inside the rule body, you may use the matcher
variable to access any captured groups.
Remember that Groovy allows you to construct a Pattern
conveniently using the
pattern operator ~
and
"slashy" string literals.
gitVersion.rules {
onBranch (~'feature/(.*)') {
println 'on feature branch!'
}
onBranch (~/release\/(\d+)\.(\d+)/) {
println 'on release branch!'
}
}
As their name implies, these rules always match, regardless of the current branch name or any other repository state.
gitVersion.rules {
before { ... }
always { ... }
after { ... }
}
The before
and after
rules are always evaluated before (or after) any other rules, regardless of where they are
defined. Multiple before
rules (or multiple after
rules) are evaluated in the order of their appearance.
As a special case, the repository might be in a state that is called a
"detached head" in Git: in this state, there is no branch
currently checked out; the HEAD
points to a specific commit instead of a branch. You can cover this case using the
onDetachedHead
rule:
gitVersion.rules {
onDetachedHead { ... }
}
Inside a rule body, you presumably want to define your version, rather than printing messages to the console. For this goal, there are a number of properties and methods available inside the rule body.
In addition to manipulating the version directly, there are some powerful high-level Git operations available which are useful in versioning tasks (see "Git Operations" below).
The version
property allows you to manipulate the version, which is ultimately the result of the versioning process.
The version may be manipulated in a number of different ways:
// Parsing the version directly from a SemVer-compliant string
version = '1.2.3-beta'
// Setting multiple parts of the version at once
version.set(1, 2, 3, 'beta')
// Setting parts of the version individually
version.major = 1
version.minor = 2
version.patch = 3
version.prereleaseTag = 'beta'
By default, all matching rules are evaluated in the order of definition (with special
treatment of before
and after
rules). This may not always be desired. Within a rule,
you can skip the evaluation of all following rules by setting skipOtherRules
to true
:
gitVersion.rules {
onBranch('master') {
// ...
skipOtherRules = true
}
// This rule will *not* be evaluated for the master branch
always {
// ...
}
}
Inside a rule body, the following properties are available to access the state of the Git repository:
Property | Type | Description |
---|---|---|
|
|
The current HEAD of the repository. May be used to access the commit ID, commit message, attached tags or even walk through the history. |
|
|
Representation of the current Git branch. Will be |
|
|
The name of the current branch. |
|
|
Allows access to the Git repository as a whole, e.g. to list tags and branches. |
The following methods are available inside a rule body, and allow for high-level operations on a Git repository which are useful for versioning tasks:
Finds the latest Git tag with the given name or matching the given regular expression. This is useful if tags are your primary versioning mechanism.
For example, if you tag commits on the master
branch with versions like "v1.2",
then the following rule will find the latest such tag:
gitVersion.rules {
onBranch('master') {
def tag = findLatestTag ~/v?(\d+)\.(\d+)/
if (tag) {
version.major = tag.matches[1].toInteger()
version.minor = tag.matches[2].toInteger()
}
}
}
By default, this does not consider tagged commits from branches that were merged
in. Put differently, the method findLatestTag
walks backward from the HEAD until
it finds a matching tag. On a merge commit (i.e. a commit with more than one parent),
only the first parent is followed.
You can change this behavior using the second parameter includeMerges
to the method,
which is false
by default:
def tag = findLatestTag(~/v?(\d+)\.(\d+)/, true)
In this case all merged branches are followed. The sorting is topographical first, then by commit date. Topographical sorting means that when walking backwards in the history, all commits are looked at before all of their ancestors.
This method counts the number of commits that were made after the given commit or tag. It can be used with any object that has a Git ID (commit hash). If used with the current HEAD, it will return 0.
For example, to use it on the result of the findLatestTag
method from above:
gitVersion.rules {
onBranch('master') {
def tag = findLatestTag ~/v?(\d+)\.(\d+)/
if (tag) {
version.major = tag.matches[1].toInteger()
version.minor = tag.matches[2].toInteger()
version.patch = countCommitsSince tag
}
}
}
In this example, the tags will only contain the major/minor version numbers, and we use the number of commits since the tag as the patch version part. If we build directly on a commit tagged "v1.2", the resulting version will be "1.2.0". If 3 more commits have been made since the tag, the resulting version will be "1.2.3".
The method branchPoint
finds the commit where the current branch was created off
another branch. This can be very useful in combination with countCommitsSince
, if
you follow a GitFlow-like approach with release branches:
gitVersion.rules {
// Release branch names contain the major/minor version, e.g. release/1.0
onBranch(~/release\/(\d+\.\d+)/) {
// Take the major and minor version from the branch name
version.setFrom matches[1]
// The patch version should be the number of commits since
// this release branch was branched off
version.patch = countCommitsSince branchPoint('origin/develop')
}
}