Github Actionsを使ってUnityのWindowsバイナリをビルドする

# はじめに
- Github Actionsを利用して、クラウド上でUnityのバイナリを作成する方法を紹介します
- Github Actionsをうまく使うことで、ローカルでJenkinsなどを構築する必要がなくなります
- 今回はWindowsのバイナリを作成する方法を紹介します

# サンプルプロジェクト
https://github.com/tkada/UnityBuildWithGithubActions

スクリプトとUnityプロジェクトはこちらにアップロードされています

# Unity側準備
- 手動でビルドできる状態までセットアップしておきます
- それ以外は特別準備する必要はありません
- とりあえず文字を表示するだけのシーンを作成しました

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/105021/114bf151-f216-ed2e-0da8-09f90ed3d14f.png)


# Github側の準備
- 今回、こちらの記事をかなり参考にさせていただきました
- [【Unity】GitHub Actions v2でUnity Test Runnerを走らせて、結果をSlackに報告する【入門】](https://qiita.com/pCYSl5EDgo/items/690dd56ffb0fcf64e70b)

ビルド前の事前準備として
1. ALFファイルの作成
2. ULFファイルの取得
3. ULFファイルの暗号化
が必要になります。

というのは、コンテナ化されているUnityにもアクティベーションが必要なためです。
`ULFファイル`はUnityをアクティベーションするために必要なファイルです。
このULFファイルを使ってUnityのアクティベーションを行うのですが、そのまま公開リポジトリに置いてしまうのは危険なため、暗号化をしてから置くことが多いです。
（プライベートリポジトリでしか運用しないのであれば、ULFファイルを暗号化せずに、そのまま置いてしまう運用もありだと思います。）

## ALFファイルの作成
```CreateLicenseALF.yaml
name: Create ALF File

on: [push]

jobs:
  build:

    runs-on: ubuntu-latest
    strategy:
      matrix:
        unity-tag: [2019.2.9f1]

    container: docker://gableroux/unity3d:${{ matrix.unity-tag }}

    steps:
    - run: mkdir artifact
    - run: /opt/Unity/Editor/Unity -quit -batchmode -nographics -logfile -createManualActivationFile || exit 0
    - run: cp "Unity_v$UNITY_VERSION.alf" artifact
      env:
        UNITY_VERSION: ${{ matrix.unity-tag }}
    - uses: actions/upload-artifact@master
      with:
        name: ${{ matrix.unity-tag }}
        path: artifact
```

このファイルをリポジトリの`.github\workflows`内に設置し、pushするとGithub Actionsが実行されます。
実行が完了するとリポジトリのActionsタブ内に結果が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/105021/5ec3e0ed-59e7-2e49-84ff-b88c655dea44.png)

問題なく実行が完了していれば`Artifacts`内にZIPされた.alfファイルが保存されています。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/105021/bc768808-e326-3848-dab1-be8cd7b03cae.png)

別のバージョンのUnityを使いたいときには

```yml
strategy:
      matrix:
        unity-tag: [2019.2.9f1]
```

上記の`2019.2.9f1`の部分を書き換えます。
使えるUnityのバージョンは[gableroux/unity3d](https://hub.docker.com/r/gableroux/unity3d/tags) から選ぶことができます。
なお、ALFファイルを作成するときはプラットフォームが付与されてないコンテナを使うようにしてください。
　`2019.2.9f1-android`ではなく、`2019.2.9f1`を使う。
これはZIPするときの環境変数`UNITY_VERSION`にコンテナ名を使っているためで、プラットフォームが付与されているとエラーが発生してしまうためです。

## ULFファイルの取得
[Manual activation](https://license.unity3d.com/manual)のページを開き、先ほど作成したalfファイルをアップロードします。
いくつか質問があるので、それに答えます。途中でPro版とPersonal版を選ぶ箇所がありますが、Personal版でも問題なく使うことができます。
最終的に`Unity_v2019.x.ulf`というULFファイルが取得できます。

## ULFファイルの暗号化
ULFファイルを暗号化します。暗号化には`OpenSSL`コマンドを使用します。
`openssl aes-256-cbc -e -in Unity_v2019.x.ulf -out Unity_v2019.x.ulf-cipher -k password`
コマンドの`password`の部分には任意の文字列を入力します
これで暗号化されたULFファイルを作成することができました。
作成した`Unity_v2019.x.ulf-cipher`はリポジトリのRootにpushしておきます。

ここまで来たら準備完了です。

# Github Actionsでビルドする
以下のファイルを作成して、Unityからプロジェクトをビルドできるようにしました

```UnityBuild.yaml
name: UnityBuild

on: [push]

jobs:
  editorTestJob:
    runs-on: ubuntu-latest
    container: docker://gableroux/unity3d:${{ matrix.unity-tag }}
    strategy:
      matrix:
        unity-tag: [2019.2.9f1-windows]

    steps:
    - uses: actions/checkout@master
    - run: openssl aes-256-cbc -d -in Unity_v2019.x.ulf-cipher -k ${CYPHER_KEY} -md md5 >> ./License.ulf
      env:
          CYPHER_KEY: ${{ secrets.CYPHER_KEY }}
    - run: /opt/Unity/Editor/Unity -quit -batchmode -nographics -silent-crashes -logFile -manualLicenseFile ./License.ulf || exit 0
    - run: |
          CURRENT_DIR=`pwd`
          echo ${CURRENT_DIR}
          /opt/Unity/Editor/Unity -quit -batchmode -nographics -silent-crashes -logFile -projectPath GithubActions -buildWindows64Player ${CURRENT_DIR}/Windows/windows.exe || exit 0
    - uses: actions/upload-artifact@master
      with:
        name: WindowsBuild
        path: Windows
    

```

このスクリプト内で実行していることは以下の通りです。
1.Unityコンテナの使用
2.リポジトリのチェックアウト
3.暗号化されたULFファイルを復号化する
4.Unityのアクティベーションを行う
5.Unityのコマンドラインツールを使ってプロジェクトをビルドする
6.出力されたバイナリをZIPしてアップロードする


スクリプト内にパスワードを直接書いてしまうと丸見えになってしまうため`Secrets`という機能を使って管理者しかわからないようにします。
リポジトリのSettings->Secrets->Add a new secretから追加することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/105021/73d6527c-55d5-03ba-b83f-e391e968dc52.png)

Github Actions上で使うときは
`CYPHER_KEY: ${{ secrets.CYPHER_KEY }}`
のように使います。すると、ログも***という表示になり、外部からは見えなくなります。
[暗号化されたシークレットの作成と利用](https://help.github.com/ja/actions/automating-your-workflow-with-github-actions/creating-and-using-encrypted-secrets)

`- run: openssl aes-256-cbc -d -in Unity_v2019.x.ulf-cipher -k ${CYPHER_KEY} -md md5 >> ./License.ulf`
この部分で暗号化されたULFファイルを復号化して`./License.ulf`に出力しています

少し古めのOpenSSLで暗号化した場合

```
*** WARNING : deprecated key derivation used.
Using -iter or -pbkdf2 would be better.
```
というエラーが出ることがあります。このエラーを回避するために`-md md5`のオプションを追加しています。
新しいOpenSSLを暗号化に使用した場合`-md md5`のオプションは必要ありません。
[Openssl 1.1.0でもファイルを復号化する](https://qiita.com/noboru_i/items/687387148468e16c059a)

`- run: /opt/Unity/Editor/Unity -quit -batchmode -nographics -silent-crashes -logFile -manualLicenseFile ./License.ulf || exit 0`

この部分でUnityのアクティベーションを行っています。
Github Actionsの場合、コンテナが都度作られるためアクティベーションも毎回行う必要があるようです。

```
- run: |
          CURRENT_DIR=`pwd`
          echo ${CURRENT_DIR}
          /opt/Unity/Editor/Unity -quit -batchmode -nographics -silent-crashes -logFile -projectPath GithubActions -buildWindows64Player ${CURRENT_DIR}/Windows/windows.exe || exit 0
```

バイナリのビルドには`-buildWindows64Player`のオプションを使用しています。
このコマンドに続けて出力ファイル名を入力する必要があります。
出力場所を設定するため`pwd`コマンドを使ってカレントディレクトリを環境変数に設定しています

```
CURRENT_DIR=`pwd`
```

プロジェクトのパスは`-projectPath`を使用して設定をしています。
その他のオプションについて詳しくは[Unityの引数オプション](https://docs.unity3d.com/ja/2018.4/Manual/CommandLineArguments.html)をご覧ください。

これでpushするたびにWindowsビルドを実行ZIPにしてアップロードまで自動化することができました。

# 終わりに
- 今回は`-buildWindows64Player`を使って設定そのままでビルドしました。Build用のEditor拡張を作り、引数としてオプションを渡すことでビルドをカスタマイズすることができます。
[ビルド用関数を作る](https://qiita.com/broken55/items/9220e86460e320ffefbf#%E3%83%93%E3%83%AB%E3%83%89%E7%94%A8%E9%96%A2%E6%95%B0%E3%82%92%E4%BD%9C%E3%82%8B)
- Github Actionsではビルドするだけでなく、Testを走らせたり、命名規則のチェックをしたりといろいろなことが自動化できます。ぜひ使ってみてください

# 参考資料
- [GitHub Actions Documentation](https://help.github.com/ja/actions)
- [【Unity】GitHub Actions v2でUnity Test Runnerを走らせて、結果をSlackに報告する【入門】](https://qiita.com/pCYSl5EDgo/items/690dd56ffb0fcf64e70b)
- [CircleCIでUnityをテスト/ビルドする、或いは.unitypackageを作るまで](http://neue.cc/2019/04/08_574.html)