MinVerでお手軽にライブラリのバージョン番号の管理を行う

# はじめに

.NET で作成したライブラリを公開する場合、.csproj などでパッケージ名やバージョンの設定を行った後に特定のタグが付与されたことを契機に GitHub Actions などを使ってビルドしてパッケージリポジトリに Push することが多いと思います。この場合、.csproj と GIT のタグの両方でバージョンを設定する必要があります。

この記事では [MinVer](https://github.com/adamralph/minver) を使ってバージョン設定の負荷を軽減する方法について説明します。

# MinVer と MinVer のインストール

[MinVer](https://github.com/adamralph/minver) は有効な[セマンティックバージョニング](https://semver.org/spec/v2.0.0.html) のタグを付与すると、タグとコミットの深さをもとにバージョン番号を自動的に設定してくれるツールです。バージョン番号の推測は[ドキュメントのこの記載](https://github.com/adamralph/minver#how-it-works)に基づき行われるので、[GitVersion](https://github.com/GitTools/GitVersion) や [Nerdbank.GitVersioning](https://github.com/dotnet/Nerdbank.GitVersioning) よりも簡単に利用することができます。

ライブラリとして導入する場合は管理したいプロジェクトに MinVer をインストールするだけです。

```
PM> Install-Package MinVer
```

CLI としてインストールする場合は dotnet のサブコマンドとしてインストールすることができます。

```
dotnet tool install --global minver-cli
```

# 使ってみる

バージョンを示すタグ一つも付いていない状況でパッケージを作成すると、`ClassLibrary1.0.0.0-alpha.0.1.nupkg`というパッケージファイルが作成されました。

```
❯ git log --oneline
f2019d6 (HEAD -> master) プロジェクト ファイルを追加します。
9fbb4bc .gitignore および .gitattributes を追加します。
❯ dotnet pack
.NET 向け Microsoft (R) Build Engine バージョン 16.11.0+0538acc04
Copyright (C) Microsoft Corporation.All rights reserved.

  復元対象のプロジェクトを決定しています...
  復元対象のすべてのプロジェクトは最新です。
  ClassLibrary1 -> C:\Users\xxxxx\source\repos\ClassLibrary1\ClassLibrary1\bin\Debug\net5.0\ClassLibrary1.dll
  パッケージ 'C:\Users\xxxxx\source\repos\ClassLibrary1\ClassLibrary1\bin\Debug\ClassLibrary1.0.0.0-alpha.0.1.nupkg' が正常に作成されました。
```

一つ履歴を作ってコミットしたら`ClassLibrary1.0.0.0-alpha.0.2.nupkg`になりました。

```
❯ git commit --allow-empty -m "ほげ"
[master 2e5f2b8] ほげ
❯ dotnet pack
... 略 ...
  パッケージ 'C:\Users\xxxxx\source\repos\ClassLibrary1\ClassLibrary1\bin\Debug\ClassLibrary1.0.0.0-alpha.0.2.nupkg' が正常に作成されました。
```

`1.0.0-beta.1` というタグであれば `ClassLibrary1.1.0.0-beta.1.nupkg` になり、この状態で 2 回コミットしたら `ClassLibrary1.1.0.0-beta.1.2.nupkg` になりました。

```
❯ git tag 1.0.0-beta.1
❯ dotnet pack
... 略 ...
  パッケージ 'C:\Users\xxxxx\source\repos\ClassLibrary1\ClassLibrary1\bin\Debug\ClassLibrary1.1.0.0-beta.1.nupkg' が正常に作成されました。
❯ git commit --allow-empty -m "はげ"
❯ git commit --allow-empty -m "はげげ"
❯ dotnet pack
... 略 ...
  パッケージ 'C:\Users\xxxxx\source\repos\ClassLibrary1\ClassLibrary1\bin\Debug\ClassLibrary1.1.0.0-beta.1.2.nupkg' が正常に作成されました。
```
リリース用に `1.0.0` のようなタグをつければ、サフィックスがとれ `ClassLibrary1.1.0.0.nupkg` が作成されます。その後改めてコミットを行うと、`alpha` サフィックスがつくようになります。

```
❯ git tag 1.0.0
❯ dotnet pack
... 略 ...
  パッケージ 'C:\Users\xxxxx\source\repos\ClassLibrary1\ClassLibrary1\bin\Debug\ClassLibrary1.1.0.0.nupkg' が正常に作成されました。
❯ git commit --allow-empty -m "はげげge"
❯ dotnet pack
... 略 ...
  パッケージ 'C:\Users\xxxxx\source\repos\ClassLibrary1\ClassLibrary1\bin\Debug\ClassLibrary1.1.0.0-alpha.0.1.nupkg' が正常に作成されました。
```

beta 以外にも下記のようなラベルにも対応しているようです。

- 1.0.0-beta.1
- 1.0.0-pre.1
- 1.0.0-preview-20181104
- 1.0.0-rc.1

# タグをプレフィクス付きで管理したい

GIT のタグを `v1.0.0` のような形式にしたい場合は、プロジェクトファイルに `MinVerTagPrefix` を定義します。

```xml:ClassLibrary1.csproj
<PropertyGroup>
  <MinVerTagPrefix>v</MinVerTagPrefix>
</PropertyGroup>
```

定義後は `v` がつかないタグはバージョンタグと認識されなくなるので、`2.0.0` とタグを付けても `ClassLibrary1.1.0.0.nupkg` のままですが、`v2.0.0` だとしっかり `ClassLibrary1.2.0.0.nupkg` になってくれます。

```
❯ git tag 2.0.0
❯ dotnet pack
... 略 ...
  パッケージ 'C:\Users\xxxxx\source\repos\ClassLibrary1\ClassLibrary1\bin\Debug\ClassLibrary1.1.0.0.nupkg' が正常に作成されました。
❯ git tag v2.0.0
❯ dotnet pack
... 略 ...
  パッケージ 'C:\Users\xxxxx\source\repos\ClassLibrary1\ClassLibrary1\bin\Debug\ClassLibrary1.2.0.0.nupkg' が正常に作成されました。
```

# おわりに

頻繁にバージョンを上げるようなライブラリの場合であれば複数の設定があるのは煩わしいし、ほとんどバージョンを上げないようなライブラリであればプロジェクト側のバージョンを上げ忘れてしまうなどの作業漏れが発生してしまうことがあるかもしれません。こういった細かい部分を自動化してくれるライブラリはありがたいですね。

他にも多くのオプションがあるので、まずは [MinVerのREADME](https://github.com/adamralph/minver) を確認してみてください。