白黒羊

Game CI × GitHub Actions でUnityのCI/CDでハマったところ

GitHub Actions初心者が、想定通りの動きをしてくれるworkflowを構築するまでに100回程度試行錯誤を繰り返した際の記録です。

General GitHub Actions Errors

Game CI使用時に限らない、一般的なエラーです。

Error: .github#L1
every step must define a uses or run key

.ymlファイルに根本的な間違いがあるときに表示されるエラーメッセージ? です。
何も実行されずに終了します。
uses の前に余計な - が入っていることで、何も内容がない -name: が生まれてしまっています。

NG

  steps:
    - name: steam
    - uses: ./.github/actions/deploy-to-steam

OK

  steps:
    - name: steam
      uses: ./.github/actions/deploy-to-steam

Invalid workflow file: .github/workflows/main.yml#L**
invalid value workflow reference: no version specified

.ymlファイルの書式に間違いがあるときに表示されるエラーメッセージです。実行されずに終了してしまいます。
手元のIDEにプラグインを入れて使っていましたが、GitHub内のエディタの方がこの辺りの問題に気が付きやすかったかもしれないです。あとはGitHub Actions Heroというサービスで一通り学ぶのも良さそう。
ここではsteps を使わずに uses を使っているのが問題です。

NG

deploy:
  name: deploy
  needs:
    - build-windows
    - build-mac
  uses: ./.github/actions/deploy-to-steam

OK

deploy:
  name: deploy
  runs-on: windows-latest
  needs:
    - build-windows
    - build-mac
  steps:
    - name: steam
      uses: ./.github/actions/deploy-to-steam

Invalid workflow file: .github/workflows/main.yml#L**

The workflow is not valid. .github/workflows/main.yml (Line: 11, Col: 5): Unexpected value ‘on’ .github/workflows/main.yml

job内でpushされたbranchに応じて実行するかどうかを決めるのは if: を使います。
on: は最上位の階層でしか使えません。

NG

jobs:
  build-windows:
    name: build-for-${{ matrix.targetPlatform }}
    runs-on: windows-latest
    on:
      push:
        branches:
          - master
          - demo

OK

jobs:
  build-windows:
    name: build-for-${{ matrix.targetPlatform }}
    runs-on: windows-latest
    if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/demo'

Can’t find ‘action.yml’, ‘action.yaml’ or ‘Dockerfile’ under ‘/Users/runner/work/PROJECT/PROJECT/.github/actions/restore-lfs-assets’. Did you forget to run actions/checkout before running your local action?

別ファイルに定義してある action (composite) を使う前には checkout しておかないと見つけられません。

https://github.com/actions/checkout/discussions/277

https://github.community/t/getting-cant-find-action-yml-even-though-the-action-exists/17862

NG

steps:
  - name: restore-lfs-assets
    uses: ./.github/actions/restore-lfs-assets

OK

steps:
  - name: Checkout repository
    uses: actions/checkout@v2
  - name: restore-lfs-assets
    uses: ./.github/actions/restore-lfs-assets

/Users/runner/work/PROJECT/PROJECT/./.github/actions/unity-build/action.yml (Line: 10, Col: 22): Unrecognized named-value: ‘secrets’. Located at position 1 within expression: secrets.GITHUB_TOKEN

別ファイルに定義してある action (composite) の中ではGitHubに登録してある secrets はそのままは使えません。

NG

# in actions/unity-build/action.yml
with:
  githubToken: ${{ secrets.GITHUB_TOKEN }}

OK

# in workflows/main.yml
env:
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

# in actions/unity-build/action.yml
with:
  githubToken: ${{ env.GITHUB_TOKEN }}

main.ymlの matrix もそのままでは使えないので、 env: 内で再定義する必要があります。

なお、 env: で定義した値を使うときは ${{ env.GITHUB_TOKEN }} のように env. をつけて、 with: で定義した値を使うときは ${{ input.githubToken }} のように input. をつけて呼び出します。

また、それぞれ細かいcompositeで構成されているworkflowにおいて、全体で共有できる動的な環境変数生成も色々試してみましたが難しかったです。
echo "project_name=PROJECT" >> $GITHUB_ENV みたいにshellを使って $GITHUB_ENV に追加していく方法が一番近いのかなとは思うのですが、

steps:
  - name: variables
    run: |
      echo "build_path=PROJECT/Builds/${{ matrix.targetPlatform }}/" >> $GITHUB_ENV
      echo "app_path=${{ env.build_path }}${{ env.project_name }}.app" >> $GITHUB_ENV
      echo "zip_path=${{ env.build_path }}${{ env.project_name }}.zip" >> $GITHUB_ENV
    shell: bash

これを各jobに追加していくとなると、結局何か修正があったら全部書き直しになって意味がなさそうです。
結局、基本的にはmain.yml内のenvで変数の定義をしています。

Error: Process completed with exit code 2.
(syntax error near unexpected token `(‘)

変数の中に [ ] ( ) などの記号が入っているときは””でエスケープするようにしましょう。

NG

env:
        APPLE_IDENTITY: Developer ID Application: XXXXXXXXXX (YYYYYYYYY)
run: |
    codesign -o runtime -f --deep -s ${{ env.APPLE_IDENTITY }} ${{ env.app_path }}

OK

env:
        APPLE_IDENTITY: Developer ID Application: XXXXXXXXXX (YYYYYYYYY)
run: |
    codesign -o runtime -f --deep -s "${{ env.APPLE_IDENTITY }}" ${{ env.app_path }}

Notes for GitHub Actions

まとめるほどもないですが、Artifact (アーティファクト)系の小ネタ。

  • Artifactの名前にcolon(:)は使えません。シンタックスエラーで怒られます。
  • actions/upload-artifactやactions/download-artifactでjob間で生成物の受け渡しをしていると、仕様で権限が失われます。tarにまとめたあとにアップロードするか、GitHub上のReleaseに添付することで実行権限を保持できます。

Game CI Errors

Game CIを使っているときに起きうるエラーです。

Project settings file not found at “PROJECT/ProjectSettings/ProjectVersion.txt”. Have you correctly set the projectPath?

(おそらく)通常のgit管理されたUnityプロジェクトファイルならば、.gitディレクトリとAssetsディレクトリが同じ階層にあると思うのですがその場合、サンプルのようにprojectPathを設定してしまうと、不具合が起こります。
公式のGitHubリポジトリのような階層の場合はうまくいきますが、そうでない場合は何も設定しないか、 . と書くかにしましょう。

NG (ルートディレクトリにAssetsディレクトリがある場合)

matrix:
        projectPath:
          - test-project
        targetPlatform:
          - StandaloneLinux64 # Build a Linux 64-bit standalone.

OK

matrix:
        targetPlatform:
          - StandaloneLinux64 # Build a Linux 64-bit standalone.

Notes for Game CI

そのほかGameCIを使おうとしているときにハマった項目を箇条書きしておきます。

  • GameCIのマニュアルでは、MacOSアプリのビルドにmacos-latestを使っていますが、実際にはubuntu-latestでできます。macos-latestは10倍の料金がかかるので最小限に抑えましょう。iOSビルドだったらXcodeを使うからビルド中にmacos-latestは必要です。MacOSでもNotarizationをするならmacos-latestが必要になります。
  • .app ファイルは実際にはファイルではなくてフォルダー(ディレクトリ)なので、消すときに -r オプションが必要だったり、Releaseに添付するfileとしてアップロードするときにzip化する必要があります。
  • Activationのマニュアルに、> It’s ok if the numbers don’t match your Unity version exactly. と書いてあるのですが、この exactlyの範囲はマイナーバージョン(XXXX.Y)の部分さえ一致していれば良いという感じなのでしょうか。2021.3.1f1を使っているときに、何も設定しないとデフォルトの2019のものがダウンロードされてうまくいきませんでした。 unityVersion: 2021.3.0f1 と設定すればうまくいきました。
  • MacOSビルドでAppが実行できないときは、Codesignの際にUnityのマニュアルに書いてある通りのentitlementが追加されているかを確認しましょう。上にも書きましたが、Artifactを使うと実行権限が失われる場合があるので注意です。