Gradle でバージョン番号を自動的に付ける 〜 git-describe とのコラボ

gradle

よく訓練されたアップル信者、都元です。暑いっすね。 先週は Developers.IO 2017 イベントで登壇いたしました。ご来場頂きましたみなさま、感謝感激ありがとうございました。

さて突然ですが、Gradle で管理する Java ライブラリのプロジェクトがあるとします。

Gradleプロジェクトには version というプロパティがあり、その値は「そのビルド時点でのバージョン番号」とするのが一般的です。

よくある Gradle プロジェクトの version の指定

たいていは gradle.properties 等に値を定義しておいて…

currentVersion = 1.0-SNAPSHOT

build.gradle の中で値を参照したりして、プロパティにセットしたりしていることでしょう。

...

version = currentVersion

...

そして、リリースタグを打つ直前に値を 1.0 に書き換えてコミット。 タグを打ったら次期開発バージョン 1.1-SNAPSHOT に書き換えてコミット…。

なーんてことを。私もやっておりました。

git-describe

git describe というコマンドをご存知でしょうか? 一言で言えば、「現在のコミットを表すいい感じの文字列」をくれるコマンドです。

例えば git describe の結果 1.0-12-g33bf9c0 という値が帰ってきたとします。 これは「直近のタグが 1.0 で、そこから 12 回のコミットを経た 33bf9c0 という abbrev-commit ID を持つコミット」 という意味です。

なんかいい感じですね。

Gradle 内で describe の値を取得する

ではこの値が Gradle 内から参照できれば、それを version プロパティに入れておけばいいじゃないですか。

ということでこんなスクリプトを作って、gradle/version.gradle ファイルとして配置してみました。

buildscript {
    repositories.mavenCentral()
    dependencies.classpath 'org.ajoberstar:grgit:1.7.2'
}

ext {
    git = org.ajoberstar.grgit.Grgit.open(file('.'))
    describedCommit = git.describe().toString().trim()
}

version = describedCommit +
    (describedCommit.matches(".*-[0-9]+-g[0-9a-f]{7}") ? "-SNAPSHOT" : "") +
    (git.status().isClean() ? "" : "+dirty")

task showVersion {
    doLast {
        println version
    }
}

Java 界の慣習で「正規リリースではないもの(=タグがついていないもの)のバージョンは "-SNAPSHOT" を付ける」 というものがあるので、ちゃんとそれに従っておきました。 また、未コミットのファイルが存在する場合はさらに "+dirty" を付ける、などの工夫もしてみました。

まぁこのあたりはお好みでスクリプトを書き換えてください。

build.gradle ファイルからは下記のようにこのスクリプトを参照します。

apply from: 'gradle/version.gradle'

さて、showVersion タスクを実行してみると…

$ ./gradlew showVersion

> Task :showVersion
1.0-12-g33bf9c0-SNAPSHOT+dirty


BUILD SUCCESSFUL in 1s
1 actionable task: 1 executed

タグを打った、まさに「正規のリリースバージョン」のコミット上でこのコマンドを実行すれば、シンプルに「1.0」等、タグ名と同じバージョン番号になります。

というわけで、リリース時にバージョン番号を繰り上げてコミット。リリース時にバージョン番号を繰り上げてコミット。 という非人道的な作業がまたひとつ、駆逐されたかと思います。

ご注意

  • 当然のことながら、gitでバージョン管理しているプロジェクトでなければ、このしくみは使えませんw
  • また、タグを一度も打ったことがないプロジェクトだと、ちょっと残念な感じになってしまいます。それでも上手く動くようにするには、version.gradle にいい感じの工夫を入れて頂ければ…(丸投げ)