ビルド時にgitのCommit Hashを定数として自動生成する

# はじめに
バージョニングはアプリをデプロイする上で大事な要素です。
大抵の開発プラットフォームにはバージョン番号が設定できます。それを設定画面やトップ画面等で表示しているアプリもよく見かけます。
ですが「このアプリはいつ時点のコミットでビルドしたものなのか？」を確認したい場合、数字ではひと目でわかりません。
というわけで、ビルド前に自動で現在のコミットのハッシュ値を定数のクラスとして生成する`Editor拡張`を作成しました。


## 準備
### Editorフォルダに格納する

[CommitHashGenerator.cs](https://gist.github.com/nekomimi-daimao/0e987de15a6cd84995319c19ba077fe9)

この`.cs`を`Editor`フォルダに格納します。
このとき、自動生成される`.cs`のパスを変更したい場合は以下の箇所を書き換えます。

```c#:CommitHashGenerator_Line_28
// replace if necessary
private const string FilePath = "Assets/Scripts/Generated";
```

### 生成する
```c#:Commit.cs
public static class Commit
{
    public const string Hash = "390181b";
}
```
このような`.cs`が自動生成されます。

#### 手動生成
<img width="573" alt="スクリーンショット 2020-03-20 1.40.16.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146245/8f8d28de-ca2e-aff0-06c8-0a84efabaaa3.png">
`Create -> CommitHash`で手動で生成することができます。
importした直後はこれで.csを生成してください。

#### 自動生成
[IPreprocessBuildWithReport.OnPreprocessBuild](https://docs.unity3d.com/ScriptReference/Build.IPreprocessBuildWithReport.OnPreprocessBuild.html)
ビルドの開始前に呼ばれる上のコールバックのタイミングで`.cs`を自動生成します。

### `.gitignore`と`.gitkeep`
`Commit.cs`は別のコミットでビルドするたびに再生成されるため、`.gitignore`に登録することをおすすめします。
しかしそのままだと空フォルダに`Unity`が`.meta`を生成するので、`.gitkeep`を使ってフォルダの構成を維持しておくと便利です。

### CI対応
`Jenkins`や`CircleCI`など、様々な`CI/CD`ツールがあります。
やり方はプロジェクトによって異なると思うので、以下の`public static`なAPIを公開してあります。

```c#:CommitHashGenerator_publicApi
/// <summary>
/// 引数のstringをHashに設定したCommit.csを生成します.
/// </summary>
public static void GenerateScript(string hash)

/// <summary>
/// 現在のcommitのhash値を取得します.
/// </summary>
public static Task<string> CheckCommitHashAsync()
```
`BuildPipeline.BuildPlayer`の実行前に上記の`API`を実行すれば生成されます。

## 使用例
<img width="171" alt="スクリーンショット 2020-03-20 2.16.23.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146245/66666e5a-0447-570e-5cab-08bff4ba6c37.png">
デフォルトだと上記のパスに生成されます。
画面に表示してみました。

```c#:SampleCommitHash
using UnityEngine;
using UnityEngine.UI;

public class SampleCommitHash : MonoBehaviour
{
    [SerializeField]
    private Text _text;

    private void Start()
    {
        _text.text = Commit.Hash;
    }
}
```

## まとめ
**これ作ってなかった自分、アホですわ！**
って言いたくなるくらい便利です。
アプリのバイナリのバージョン確認やログ収集など、どの時点かのビルドかがわかるようになるとここまで便利になるとは……。

*「リリースしたいんだけど、このバイナリいつビルドしたやつだろう……***ヨシ！」**[^who]

みたいなことがなくせます。やったね！

[前回](https://qiita.com/nekomimi-daimao/items/cd1e59c71b78bf5afda8)の記事で[MessagePack-CSharp](https://github.com/neuecc/MessagePack-CSharp)のもろもろを解析した結果思いつきました。
`OSS`をちゃんと読むの大事ですね。肝心の`Serialize/Deserialize`してるあたりはぜんぜんわかんなかったです。わからん。
手元に開発環境が`mac`しかないので、`win`とか`linux`とかの人は動かしてみて、だめだったらなんか適当に直しといてください。

おしまい。

[CommitHashGenerator.cs](https://gist.github.com/nekomimi-daimao/0e987de15a6cd84995319c19ba077fe9)

## 参考

[【Unity】ビルド時にGitコミットハッシュをバージョン情報に含めた件](https://gomafrontier.com/unity/2062)
[Git で現在のコミットのハッシュを取得する方法](https://gotohayato.com/content/85/)
[（小ネタ）改行文字を削除する](https://redwarrior.hateblo.jp/entry/2016/02/08/090000)
[スクリプトからテンプレを自動作成【Unity】【エディタ拡張】](https://kan-kikuchi.hatenablog.com/entry/TemplateScriptCreator)
[Unityプロジェクトへファイルを追加する際に上書き更新する](http://tsubakit1.hateblo.jp/entry/20140615/1402844126)
[【Unity】エディタ拡張で使用できるコールバックを40個まとめて紹介](http://baba-s.hatenablog.com/entry/2017/12/04/090000)
[Unityのエディタ拡張で設定を保存](https://www.f-sp.com/entry/2016/08/25/194719)
[メニューを追加するための属性「MenuItem」は意外と多機能【Unity】【エディタ拡張】【属性】](https://kan-kikuchi.hatenablog.com/entry/MenuItem)


[^who]: もちろんしたことないですけどねそんなこと!!!?!?!!!?!!!?!?!?!?!?!???!!!!