AWSを使ったクラウドUnityビルド環境の構築~GitHub Actions構築編~

エンジニアの岡村です。この記事は以前掲載した『AWSを使ったクラウドUnityビルド環境の構築~ビルドサーバー構築編~』の続編であり、シリーズの3記事目です。

synamon.hatenablog.com

synamon.hatenablog.com

また、インフラメンバーの黒岩さんに書いていただいたビルドサーバー構築編の補足になる記事もどうぞ。

synamon.hatenablog.com

これまでで作ったもの

ライセンスサーバー構築編ではUnityのフローティングライセンスを管理するサーバーを建て、ビルドサーバー構築編ではUnityがインストールされたマシンのAMI及び、それを利用してビルドトリガーに応じてSelf-Hosted Runnerを起動するよう設定しました。 その結果、以下の画像のような環境が構築されています。

今回はこの環境を利用して、Unityプロジェクトをgitのリモートリポジトリにプッシュした際、自動的にテストとビルドを行うWorkflowをGitHubで構築します。

GitHub ActionsのWorkflowを記述する

リポジトリのルート=Unityプロジェクトのルートとなっているリポジトリを用意し、.github/workflows/フォルダ内にyaml形式でワークフローを記述します。

GitHub Actionsのワークフロー構文 - GitHub Docs

今回はサンプルとして以下のような簡単なworkflowを用意しました。細かい解説は後述します。

name: ExampleWorkflow

on: [push, workflow_dispatch]

jobs:
  test:
    runs-on: [self-hosted, windows, unity-2021.3.0f1]
    strategy:
      matrix:
        platform: [EditMode, PlayMode]
    steps:
      - name: Test Unity Licensing Client
        run: '"C:\Program Files\Unity\Hub\Editor\2021.3.0f1\Editor\Data\Resources\Licensing\Client\Unity.Licensing.Client.exe" --acquire-floating'
        shell: cmd
      - uses: actions/checkout@v3
      - name: LFS pull
        run: git lfs pull
      - name: Run ${{ matrix.platform }} tests
        run: >-
          start /wait "" "C:\Program Files\Unity\Hub\Editor\2021.3.0f1\Editor\Unity.exe"
          -runTests
          -batchmode
          -projectPath .\
          -testResults .\TestResult.xml
          -testPlatform ${{ matrix.platform }}
          -logFile Editor.log & type Editor.log
        shell: cmd
      - uses: actions/upload-artifact@v3
        with:
          name: ${{ matrix.platform }}TestResult
          path: TestResult.xml
  build:
    runs-on: [self-hosted, windows, unity-2021.3.0f1]
    steps:
      - name: Test Unity Licensing Client
        run: '"C:\Program Files\Unity\Hub\Editor\2021.3.0f1\Editor\Data\Resources\Licensing\Client\Unity.Licensing.Client.exe" --acquire-floating'
        shell: cmd
      - uses: actions/checkout@v3
      - name: LFS pull
        run: git lfs pull
      - name: Run build
        run: >-
          start /wait "" "C:\Program Files\Unity\Hub\Editor\2021.3.0f1\Editor\Unity.exe"
          -batchmode -quit
          -projectPath .\
          -buildTarget Win64
          -buildWindowsPlayer Builds\Windows\Build.exe
          -logFile Editor.log & type Editor.log
        shell: cmd
      - name: Upload build
        uses: actions/upload-artifact@v3
        with:
          name: BuildWin64
          path: Builds/Windows/*

以上の内容を.github/workflow/main.ymlとして配置してGitHubにpushすると、以下のようにジョブが開始されます。

また、このタイミングでAWSの方を覗いてみると、ジョブの数に合わせて(terraformで制限した数を上限として)インスタンスが建っています。

(ここでインスタンスが暫く待っても表示されないようであれば、yaml内で指定しているself-hosted runnerのラベルが間違っているかもしれません。)

そこからさらに暫く待つとステップの処理が始まります。スポットインスタンスのリクエスト及びrunnerのセットアップに時間が掛かります。こちらの環境ではインスタンスが既に立ち上がっていない場合、pushしてから処理が始まるまで10分強程度待つ必要がありました。

ワークフローが完了すると成果物がアップロードされています。テスト結果はNUnitのxmlフォーマットで出力されているので、これを読めるレポーターに噛ませてあげれば失敗したテストをGitHub上で具体的に指摘する事も可能です(が、現時点でUnityが吐き出すxmlをきちんと読めるレポーターがMarketplaceに見つからなかった為そのままアップロードしています)。

Workflowの詳細

以降はWorkflowでUnityのビルドを行うために工夫した点をステップ単位でかいつまんで紹介します。Jenkins時代のコードを引き継いでいる個所もあるので古いハックも含まれている可能性があります。

Test Unity Licensing Client

一度FloatingLicenseのテストを行っているのですが、これを行わないとUnity実行時にライセンスサーバーと接続出来ないことがあるので毎回行っています。

      - name: Test Unity Licensing Client
        run: '"C:\Program Files\Unity\Hub\Editor\2021.3.0f1\Editor\Data\Resources\Licensing\Client\Unity.Licensing.Client.exe" --acquire-floating'
        shell: cmd

LFS pull

社内のプロジェクトではgit lfsを利用しているのですが、actions/checkoutではlfsのファイルが正しく取得できなかったため、明示的にステップを入れています。

      - name: LFS pull
        run: git lfs pull

Run Unity

Windowsはcmd、PowerShell、git bash等が使えますが、今回はcmdでUnityを実行しています。Unityをcmdで実行する際、直接exeを叩くとプロセスの終了を待たずにステップが進んでしまうため、start /waitを使って待機しています。この際、ファイルパスにスペースが含まれている為にパスをダブルクォートで囲むと、startコマンドの仕様上ウィンドウタイトルの指定として解釈されてしまうので、実行ファイルパスの前に""引数を付けています。

テストはTestFrameworkのコマンドライン引数を使って実行しているので、以前のバージョンで使用できたUnity本体のマニュアルのコマンドライン引数とは差異があります。

また、-logFile -とすることでJenkins時代はログをリアルタイムに出力できたのですが、GitHub Actionsでは(もしくはUnityバージョンの関係で)それが出来なくなっていたので、typeコマンドを繋いで出力するようにしています。

今回は特にキャッシュを行っていないのですが、Unityの実行時には大量のキャッシュファイルが生成されるので、特に大規模なプロジェクトになってきた場合はactions/cacheを使うか、Unity AcceleratorをAWS上のライセンスサーバーの横に追加で構築してもいいかもしれません。

      - name: Run ${{ matrix.platform }} tests
        run: >-
          start /wait "" "C:\Program Files\Unity\Hub\Editor\2021.3.0f1\Editor\Unity.exe"
          -runTests
          -batchmode
          -projectPath .\
          -testResults .\TestResult.xml
          -testPlatform ${{ matrix.platform }}
          -logFile Editor.log & type Editor.log
        shell: cmd
~~~~~~~~
      - name: Run build
        run: >-
          start /wait "" "C:\Program Files\Unity\Hub\Editor\2021.3.0f1\Editor\Unity.exe"
          -batchmode -quit
          -projectPath .\
          -buildTarget Win64
          -buildWindowsPlayer Builds\Windows\Build.exe
          -logFile Editor.log & type Editor.log
        shell: cmd

以上

現時点ではまだこの(BuildServerライセンス&GitHub Actions&AWSベースの)Unity CI環境はハマりポイント盛りだくさんで手探り状態です。安定を求めるのであれば既存のマネージドサービスや、物理マシンのself-hosted runnerを使った方が楽でしょう。しかし、フローティングライセンスを使うことでUnityのライセンスが扱いやすくなったこと、AWSにインスタンスを立てることでスペックの自由度やスケーラビリティが確保される事は、特にUnityを大規模に使っているような企業においては魅力的なのではないでしょうか。

AWSを使ったクラウドUnityビルド環境の構築シリーズとして、一応予定していた記事は出し切ったのですが、今後も追加情報があれば記事の修正や、追加の記事を出していこうと考えています。 記事での紹介内容も分かる人向けに端折ってお伝えしましたが、もし分からないところがあればTwitter等で指摘をお願いいたします。

このシリーズに長らくお付き合いいただき、ありがとうございました。


SynamonではUnityエンジニアを募集しています。Unityを使った最新のCI/CD環境に興味ある方、Unityを使ったマルチプレイ、マルチデバイスなメタバース構築に興味ある方は是非採用情報をご確認下さい。

herp.careers

カジュアル面談も行っています。

meety.net