【Unity】GithubActionsでUnityを起動してTestRunner実行後の結果を出力するまでの手順

特定のリポジトリにアセットを**pushしたタイミングでバリデーションを走らせたい場面**があります。

例えば**バリデーションに成功した後でpushするというルール**を決めたとしても保証は出来ません。それらのアセットがバリデーション済みの保証はできません。

こういう**手動に頼らないといけない部分は自動化を検討**したいものです。
そこで**GithubActionsを使った納品物(アセット)のバリデーションを確実に走らせる**ようにしてみます。

今回は[【Unity】TestRunnerを使ったアセットバリデーションツールを最短経路で作ってみる](https://qiita.com/ohbashunsuke/items/9b8fbe2c209d8f264a4b)で作成したアセットバリデーションをGithubActionsで実行できるようにしていきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328771/f95c8312-d32b-77d0-250f-88cf1b2ea3dd.png)
全体のワークフロー図です。3つのリポジトリを使っています。

## 先人に感謝

[【Unity】GitHub Actions v2でUnity Test Runnerを走らせて、結果をSlackに報告する【入門】](https://qiita.com/pCYSl5EDgo/items/690dd56ffb0fcf64e70b)
基本はこちらの記事を参考に進めていってます。
とても参考になりました。ありがとうございます。


## 環境

- Unity2019.4.4f1

## GithubActionsでTestRunnerを走らせるまでの準備

1. ALFファイルの作成
2. ULFファイルの取得
3. ULFファイルの暗号化


GithubActionsでUnityを走らせるためには**ライセンス認証**が必要となります。
そのために**マニュアルアクティベーション**を攻略していきます。
参考 : [Offline / Manual Activation](https://docs.unity3d.com/ja/2019.3/Manual/ManualActivationGuide.html)


## 1.ALFファイルの作成

先のワークフロー図のCreateALFプライベートリポジトリでの作業です。

1. Unityを起動してALFファルを作成
1. 成果物として出力

このような手順のyamlを作成してGithubActionsを実行します。

```CreateALF.yaml
name: Create ALF File
on: [push]
jobs:
  build:
    runs-on: ubuntu-latest
    container: docker://gableroux/unity3d:2019.4.4f1
    steps:
    - run: mkdir artifact
    # 1.Unityを起動してALFファルを作成
    - run: /opt/Unity/Editor/Unity -quit -batchmode -nographics -logfile -createManualActivationFile || exit 0
    - run: cp "Unity_v2019.4.4f1.alf" artifact
    # 2.成果物として出力
    - uses: actions/upload-artifact@master
      with:
        name: 2019.4.4f1
        path: artifact
```


このワークフローが成功すると、このようにALFが成果物としてダウンロードできるようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328771/fb500f04-6ee5-0142-e8d4-40aa1a4a5fb5.png)



自分はCI・GithubActions初学者なので**GithubActionsワークフロー**の構文について調査しておきます。

参考:[GitHub Actionsのワークフロー構文](https://docs.github.com/ja/actions/reference/workflow-syntax-for-github-actions)

文法 | 内容 | 備考 
--- | --- | ---
name  | ワークフロー名 | 任意の名前 
on  | 実行トリガー | push, issueなど
jobs | ジョブリスト | 
build | ジョブ名 | 任意の名前 
runs-on | (必須)ジョブを実行するマシンの種類指定 | 
container | 指定コンテナ | 
steps | 一連のタスク | すべてのアクションはステップとして実行される |
run | OSのシェルを実行 | 
uses | ステップの一部として実行されるアクション | 
with | usesで指定したアクションに必要なパラメータ | KEY・VALUEのmap 

#### その他構文的に分からなかった部分の調査

#### actions/upload-artifact

`actions/upload-artifact`に付随する `with`のの調査です。

```CreateALF(抜粋).yaml
- uses: actions/upload-artifact@master
  with:
    name: 2019.4.4f1
    path: artifact
```
`actions/upload-artifact`とはGithub公式が提供する**ビルドの成果物をアップロードするアクション**です。引き渡すパラメータに`name`と`path`を**with**でセットしています。

##### `name`と`path`の必要性の調べ方

本家の`actions/upload-artifact`のソースを確認します。
https://github.com/actions/upload-artifact/blob/main/action.yml

以下その一部です。

```action(抜粋).yml
inputs: 
  name:
    description: 'Artifact name'
    required: false
  path:
    description: 'A file, directory or wildcard pattern that describes what to upload'
    required: true
``` 

このように**inputs(入力)**に`name`と`path`をパラメータとして必要としている事が分かります。pathは`required: true`なので**必須**です。


CreateALF.yamlで定義した`with`の内容が`actions/upload-artifact`の入力情報として渡されたという事が分かり、スッキリしました。

参考 : [成果物を使用してワークフローデータを永続化する](https://docs.github.com/ja/actions/configuring-and-managing-workflows/persisting-workflow-data-using-artifacts)

#### actions/upload-artifactの後ろの「@」について

`@`をつけるとバージョンを指定できます。

- @ブランチ名
- @コミットハッシュ

という使い方が出来るようです。

参考 : [バージョンされたアクションを使用する例](https://docs.github.com/ja/actions/reference/workflow-syntax-for-github-actions#%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3%E3%81%95%E3%82%8C%E3%81%9F%E3%82%A2%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%99%E3%82%8B%E4%BE%8B)




## 2.ULFファイルの取得

ULFとは**UnityLicenseFile**の事で、中身に認証情報が格納されています。
このファイルがオフライン認証を可能にするため重要なファイルです。このファイルを取得する方法です。

https://license.unity3d.com/manual にアクセスします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328771/d03cd552-2110-035b-e23e-5ef56a9cf3cd.png)
キャプチャのように先程取得したALFファイルを突っ込んでNextボタンをクリックします。

#### ファイル命名バリデーションが存在する

**Unity_v2019.4.4f1.alf**では命名で弾かれてしまいました。
正しくは、 `Unity_v2019.4.4.alf`です。
ファイル命名に注意が必要です。

その後の質問に回答し、無事にULFファイルを取得できました。
ファイル名は`Unity_v2019.x.ulf`です。


## ULFファイルの暗号化

CreateULFプライベートリポジトリでの作業です。

先程取得したULFファイルをこのリポジトリのルートに配置します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328771/4a0554ac-fdfd-b873-1f0c-8120b80aa9b2.png)


ULFファイル(Unity_v2019.x.ulf)はXMLなので中身が丸見えです。
[参考サイト](https://qiita.com/pCYSl5EDgo/items/690dd56ffb0fcf64e70b)の通り、事前にopensslで暗号化して使用時に復号化して使うことにします。


### 事前にGithub上でパスワードを作成

`Settings > Secrets`から暗号化に使うパスワードを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328771/d3e32e67-7254-e7cd-15f0-06cc2f9053fe.png)

このようにKeyとValueをセットにした鍵を作成することが出来ます。GithubActions上で以下のようにValueのパスワードにアクセスすることが出来ます。

```yaml
${{ secrets.Key名  }}
```
実際のコードでは`${{ secrets.CYPHERKEY }}`でアクセスしています。


平文のULFファイルを暗号化するGithubActionsが以下です。

```CreateULF.yaml
name: Create Unity License File

on: [push]

jobs:
  job:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@master
      - run: mkdir -p artifact
      - run: openssl aes-256-cbc -e -in Unity_v2019.x.ulf -out artifact/Unity_v2019.x.ulf-cipher -k ${{ secrets.CYPHERKEY }}
      - uses: actions/upload-artifact@master
        with:
          name: ciphers
          path: artifact
```


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328771/f640f161-dfbc-9872-6050-10ebbc90d15c.png)

ワークフローが完了すると成果物として**暗号化されたULF**が取得できます。
ファイル名を分かりやすく`Unity_v2019.x.ulf-cipher`としています。


## GithubActionsでTestRunnerを実行する

TestRunnerWithGithubActionsパブリックリポジトリでの作業です。
https://github.com/baobao/unity-test-runner-with-github-actions

以前執筆した[【Unity】TestRunnerを使ったアセットバリデーションツールを最短経路で作ってみる](https://qiita.com/ohbashunsuke/items/9b8fbe2c209d8f264a4b)で作成した[Unityプロジェクト](https://github.com/baobao/unity-test-runner-asset-test-shortcode)をGithubActionsでEditorModeTestを走らせます。ソースを丸コピしています。

暗号化したULFをリポジトリのルートに配置します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328771/56396ce6-9f57-ca6d-ad5c-cb19573dd31f.png)


ちなみにローカルPCでコマンドラインからUnityのEditorModeを実行するコマンドは以下です。これをGithubActionsのジョブに組み込んでいきます。

```zsh
'/Applications/Unity Hub/2019.4.4f1/Unity.app/Contents/MacOS/Unity' -runTests -projectPath /パス(省略)/プロジェクト名 -batchmode -testPlatform EditMode
```



以下の手順のジョブをyamlに書いてGithubActionsで実行してみます。

1. 暗号化されたULFの復号化
2. Unity起動 ULFを使ってライセンス認証
3. Unity起動 EditorModeTestの実行
4. 成果物をartifactディレクトリにアップロード


```run-test-runner.yml
name: UnityTestRunnerWithGithubActions

on:
  push:
    branches:
    - master

jobs:
  editorTestJob:
    runs-on: ubuntu-latest
    container: docker://gableroux/unity3d:2019.4.4f1

    steps:
    - uses: actions/checkout@master
    # TestRunnerの結果を出力するディレクトリ作成
    - run: mkdir -p artifact
    # 暗号化したULFから復号化したULFを取り出す
    - run: openssl aes-256-cbc -d -in Unity_v2019.x.ulf-cipher -k ${CYPHER_KEY} >> /Unity_v2019.x.ulf
      env:
        CYPHER_KEY: ${{ secrets.cypherkey }}
    # Unity起動 ULFを使ってライセンス認証
    - run: /opt/Unity/Editor/Unity -manualLicenseFile /Unity_v2019.x.ulf -batchmode -nographics -quit || exit 0
    # Unity起動 EditorModeTestの実行
    # 結果(results.xm;)をpath/to/artifact/に出力
    - run: /opt/Unity/Editor/Unity -batchmode -nographics -silent-crashes -logFile -projectPath . -runEditorTests -editorTestsResultFile artifact/results.xml || exit 0
    # 成果物をartifactディレクトリにアップロード
    - uses: actions/upload-artifact@master
      with:
        name: test-result
        path: artifact
```

このGithubActionsを実行すると以下のようにTestの結果を受け取ることが出来ます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328771/4dad3f5c-88b1-e23b-d1c8-b5ad7f0108fe.png)


## テストの時間と無料枠

1回のテストに3分半ほど掛かるようです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328771/a1a96f80-ea45-6877-769f-ec204b1eb8bb.png)

Github Freeの場合**2000分/月**の無料枠です。このレベルのジョブで約570回実行できるという事になります。実用的か現段階では分からないです。

ちなみにGithubActionsの無料枠を使い切った場合は、単純に使えなくなるだけのようですね。


## 参考
- [GitHub Actions の無料枠を使いきった場合](https://qiita.com/technote-space/items/7b2694786f577c823fc1)
- [GitHub Actionsの支払いについて](https://docs.github.com/ja/github/setting-up-and-managing-billing-and-payments-on-github/about-billing-for-github-actions)
- [【Unity】Unity Test Runner（Test Framework）でコマンドラインからテストを実行する](https://light11.hatenadiary.com/entry/2020/06/15/194738)