GitHub Actions のセルフホストランナーで Unity ビルドする

最終更新日:2020年09月24日

GitHub Actions は GitHub のリポジトリでビルド等を自動化するサービスです。

通常 GitHub 側でコンテナを立ち上げて実行しますが、自分で用意した PC にセルフホストランナーをインストールして GitHub Actions から呼び出して実行することもできます。Oculus Quest のプロジェクトのためにセルフホストランナーを導入してみたので、Unity のビルドとテストを走らせる基本的な方法をメモ書きです。

セルフホストランナーを使う理由ですが、Unity の大きなプロジェクトで CI ビルドする場合、毎回まっさらなコンテナイメージでチェックアウトして Library フォルダのない初期状態からインポート・ビルドし直すのは非現実的です。セルフホストすれば差分のみをチェックアウトして繰り返しビルドできます。

またこのページでは触れませんが、iOS ビルドする場合、GitHub Actions の macOS の料金が高い(Linux の10倍!)のでセルフホストがほぼ必須になると思います。

セルフホストランナーを使用する手順

GitHub Actions のセルフホストランナーで Unity ビルドする手順を簡単に説明します。ビルド用 PC としてここでは Windows を使用しています。

Unity のプロジェクトを用意する

Unity のプロジェクトを作成してコマンドラインからビルドできるようにしておきます。Editor という名前のフォルダに下記のようなビルドスクリプトを作っておきます。

using System.Linq;
using UnityEditor;

public class CI
{
    [MenuItem("CI/Build")]
    public static void Build()
    {
        BuildPipeline.BuildPlayer(ScenePaths, "Build/Application.apk", BuildTarget.Android, BuildOptions.CompressWithLz4);
    }

    static string[] ScenePaths => EditorBuildSettings.scenes.Select(scene => scene.path).ToArray();
}

コンソールから以下のようなコマンドを実行します。Unity のパスは適宜変更してください。

"C:\Program Files\Unity\Hub\Editor\2020.1.2f1\Editor\Unity.exe" -quit -batchmode -projectPath . -executeMethod CI.Build -buildTarget Android -setDefaultPlatformTextureFormat astc -nographics -logFile output.txt

しばらく待って Build フォルダに .apk ファイルがビルドされることを確認してください。確認したら GitHub でリポジトリを作り(適宜 .gitignore を設定して)push します。

セルフホストランナーをセットアップする

次にセルフホストランナーを使用できるように準備しましょう。

GitHub でリポジトリの Setings > Actions を開いて、Self-hosted runners で Add Runner をクリックします。PowerShell を開き、ドライブのルートに移動して(ドライブはどこでも大丈夫のようです)ページに表示されているコマンドを上から順番にコピペ実行してください。

configure.cmd でランナーの名前やディレクトリ等を設定して、run.cmd を実行するとセルフホストランナーがジョブ待機状態になります。

なお、GitHub Actions はデフォルトのシェルとして PowerShell を使用するのですが、外部からダウンロードした PowerShell スクリプトを実行できるように、管理者モードの PowerShellで下記を実行しておきます。

Set-ExecutionPolicy RemoteSigned

GitHub Actions でビルドする

GitHub のリポジトリに GitHub Actions の workflow ファイルを作成します。リポジトリの Actions タブでテンプレートを選択できるのですが、「set up a workflow yourself」をクリックして以下を参考に書き換えてください(最後の行の Copy-Item でビルドされた .apk ファイルを確保しています。コピー先フォルダを適当に変更してください)。

name: Build

on:
  push:
    branches: [ master ]

jobs:
  build:
    runs-on: self-hosted

    steps:
    - name: Checkout
      uses: actions/checkout@v2
      with:
        lfs: true
        clean: false

    - name: Unity Build
      shell: cmd
      run: |
        "C:\Program Files\Unity\Hub\Editor\2020.1.2f1\Editor\Unity.exe" -quit -batchmode -projectPath . -executeMethod CI.Build -buildTarget Android -setDefaultPlatformTextureFormat astc -nographics -logFile -

    - name: Release
      run: Copy-Item Build\Application.apk D:\Builds\Application${{ github.run_number }}.apk

右上の Start commit ボタンでコミットすると、すぐ手元の PC が動き出してビルドが開始されるはずです。GitHub の Actions のページでビルドの進行をリアルタイムで確認できます。

runs-on: self-hosted によりセルフホストランナーで実行されるようになっています。下の記述により、master にコミットが push されるたびにビルドが実行されます。

on:
  push:
    branches: [ master ]

actions/checkout の「clean: false」がミソで、リポジトリのチェックアウト時に Library フォルダ等を消さないようにします。また、Git LFS を使用している場合は 「lfs: true」が必要 です。

Unity は cmd から実行し -logfile -(「-」が必要)でログを標準出力していて、GitHub 上で閲覧できます。PowerShell で実行する場合は以下のようにすれば標準出力からログを出力できます(が、ビルドが終了しても Actions が次のステップに行かなかったりする? たまたまかもしれませんが……)。

      run: |
        & "C:\Program Files\Unity\Hub\Editor\2020.1.2f1\Editor\Unity.exe" -quit -batchmode -projectPath . -executeMethod CI.Build -logFile - -buildTarget Win64 -nographics | Out-Host

ビルドして生成された .apk ファイルについて、ここでは ${{ github.run_number }} でビルド番号をつけてコピーしています。

プルリクエストでテストを走らせる

ビルドができるようになったら次はテストです。

Jenkins だと GitHub Branch Source Plugin を使用して、正直かなりセットアップが面倒くさいのですが、GitHub Actions だとずっと簡単で、最低限以下のような workflow ファイルを追加するだけです。

name: Pull Request Test

on:
  pull_request:
    branches: [ master ]
    types: [ opened, synchronize ]

jobs:
  test:
    runs-on: self-hosted

    steps:
    - name: Checkout
      uses: actions/checkout@v2
      with:
        fetch-depth: 0
        lfs: true
        clean: false

    - name: Unity Play Mode Test
      shell: cmd
      run: |
        "C:\Program Files\Unity\Hub\Editor\2020.1.2f1\Editor\Unity.exe" -batchmode -projectPath . -runTests -testPlatform PlayMode -testResults TestResult-PlayMode.xml -logFile -
    
    - name : Unity Edit Mode Test
      shell: cmd
      run: |
        "C:\Program Files\Unity\Hub\Editor\2020.1.2f1\Editor\Unity.exe" -batchmode -projectPath . -runTests -testPlatform EditMode -testResults TestResult-EditMode.xml -logFile -

プルリクエストすると、master にマージ後のコミットがチェックアウトされ、Unity の Play Mode および Edit Mode テストが実行されて GitHub 上に結果が表示されます(Unity のテストの作り方についてはここでは説明しません)。

テスト結果を見やすく表示する方法についてはまだ検討中……。この書き込みが参考になりそうです。

以下、Tips です。

GitHub Actions の Tips

特定のタグでビルドを走らせるには

on:
  push:
    tags:
      - 'release-*'

シェルを選択するには

Windows では run ステップはデフォルトで PowerShell を使用するようになっています。cmd を使用するには shell: cmd を設定します。

shell: cmd

デフォルトのシェルやディレクトリを設定するには

defaults:
  run:
    shell: cmd
    working-directory: UnityProject

複数のリポジトリでセルフホストランナーを使用するには

セルフホストランナーはリポジトリまたは Organization ごとにセットアップできます。複数のリポジトリで共通のセルフホストランナーを使用するには、Organization に対してセットアップするしかないようです。

セルフホストランナーは同時実行できるの?

こちらのスレッドに回答がありました。

Git for Windows で workflow を push するとリジェクトされる

(refusing to allow an OAuth App to create or update workflow `.github/workflows/build.yml` without `workflow` scope)

というエラーが出る場合、Windows の 資格情報マネージャー > Windows 資格情報 で git:https://github.com の項目を削除して git コマンドで再ログインしてください。

Unity関連 の Tips

コンテナでビルドする場合

セルフホストランナーを使わない場合の参考ページです。

Unity がインストールされた Docker イメージとして gableroux/unity3d を使用するのが一般的なようです。Unity のライセンス認証で苦労するとの噂。

macOS で試行錯誤されている例。料金の問題から、結論としてセルフホストがおすすめとのことです。

.unitypackage を作るには

.unitypackage は Unity がなくても作れるようです。参考ページ:

参考リンク

書いた人:こりん(@korinVR
VR開発メモトップ