勉強不足で至らんブログ

勉強不足ですが色々と書いていきます。

UnityのCIをCircleCIで頑張る

UnityのCIを無料で使いたい

業務だとJenkins等を使われてるイメージのあるUnityですが、個人作業だと自前でサーバー建てたくない(昔やったけど電気代がつらかった)し有料のCloudBuildを使うのも…僕はケチんぼなんでしたくない…サーバーレスで使えるCircleCIを使ってみようというのが始まりでした。

そこから CircleCIでUnityのTest&Buildを雰囲気理解で走らせた の記事を書き

Aiming Tech Book Vol.2 ここではCircleCIのOrbsを作った話をしていました。(OrbsはCircleCIのライブラリのようなもの) unity-ci(自分が作ったUnity用Orbs)でUnityのBuildやTestはある程度楽になったのですがライセンス周りは手動でどうにかする内容でした。

ここまでの記事ではUnityのバージョンごとにulfというUnityのライセンスファイルを手動で作ってCircleCIの環境変数base64エンコードをかけて登録する必要がありました。 そこから先日 Unityの.alfファイルから自動で.ulfをダウンロードしたい! PuppeteerというjsのUIテストツールを使用して.alfというUnityのライセンスリクエストファイルからコマンドを叩けばUnityライセンス認証ファイルである.ulfをダウンロードするツールを使って自動化までしました。

これでulfも出来たから安泰…!というわけにはいかず、後からunity-license-activateのUnityアカウントのログインによる2要素認証処理が必要だったり、unity-ciもファイルからライセンス認証をする対応が必要だったりしました。

そして最近やっと改修が落ち着いたのでまとめようと思います。改善点はまだまだありますが…一旦…

ここまでやって何が問題なの

ざっくりまとめると

  • unity-license-activateが2要素認証に対応してなかった
  • unity-ciがファイルからのライセンス認証に対応してなかった

ということになります。 個人開発だと安易にバージョンを上げることがあるのでバージョンの壁は自動で越えさせたかったというモチベーションがありました。

unity-license-activateとunity-ciを知らない方が多いと思いますので軽く紹介しますと

unity-license-activateはターミナル等で node activate.js $email $password $alf_file_path とすればemailとpasswordからアカウントでログインしてalfをulfに変えてくれるツールになります。

また、unity-ciはCircleCIでyamlを記述する際に

version: 2.1

orbs:
  unity-ci: mizotake/unity-ci@0.1.2

executors:
  unity_executor:
    docker:
      - image: gableroux/unity3d:2019.1.0f2

workflows:
  version: 2
  unity-ci-test:
    jobs:
      - unity-ci/build:
          name: Build Execute Win
          exec: unity_executor
          platform: Win
          method: Build.Method
          zip: true
      - unity-ci/test:
          name: Edit Mode Test
          exec: unity_executor
          mode: editmode
      - unity-ci/test:
          name: Play Mode Test
          exec: unity_executor
          mode: playmode

上記のように記述すればCircleCIでBuildやTestが可能になるOrbsになります。

今回の追加対応した大雑把な流れ

  1. 開発対象のUnityバージョンで.alfを生成
  2. unity-license-activateをgitで落としてくる
  3. npmで環境設定してunity-license-activateを叩いて.ulfをダウンロード
  4. ダウンロードした.ulfでUnityのライセンス認証

をCircleCI上で自動化しました。

開発対象のUnityバージョンで.alfを生成

これはUnityのコマンドラインにあるので素直に /opt/Unity/Editor/Unity -quit -batchmode -nographics -logFile -createManualActivationFile || exit 0

createManualActivationFileで生成します。しかし、終了コードがすべて失敗になるので強制的に成功させます。

unity-license-activateをgitで落としてくる

CircleCI上で行っているので、素直にgitで落としてくるものの alpine/git のDockerImageを使いCircleCIの機能である persist_to_workspace を使って次のjobでnodejsのImageで実行させるようにしています。

npmで環境設定してunity-license-activateを叩いて.ulfをダウンロード

以前書いた記事 Unityの.alfファイルから自動で.ulfをダウンロードしたい! で可能になったのですが初めて実行するPCでは2要素認証をクリアする必要がでてきます。そこで node activate.js $email $password $alf_file_path という引数がデフォルトですが node activate.js $email $password $alf_file_path $verify_code 第4引数に2要素認証のコードを入れて進めるようにしました。 CircleCIでどうやってクリアするのかというと

f:id:MakeTake:20191230092038p:plain

ここにあるsshでCircleCIにアクセスする方法をとります。まず2要素認証をメールなどではなくてGoogleの「認証システム」アプリなどにします。このアプリだと認証コードが一分ほど有効です。そのためsshで接続してunity-license-activateを叩いて認証するまで時間的には間に合います。 一度認証が通ればその後は必要になりませんがプロジェクトごとに一度ssh接続して認証してあげる必要がありそうです。

手法としては力技という感じがしますが自分としては他に道が見えなかったのでこうしました!!!

unity-ciのアップデート

そして自前で作っているCircleCIのOrbsがファイルからのライセンスアクティベートに対応していなかったので対応しました。

対応してOrbsを使うときには固定の文字列を入れたりしないといけないのでまだ改修が必要な感じがしますが一旦こうなります。

version: 2.1

orbs:
  unity-ci: mizotake/unity-ci@0.1.2

executors:
  unity_executor:
    docker:
      - image: gableroux/unity3d:2019.3.0f1

jobs:
  setup:
    machine: true
    steps:
      - checkout
      - run: sudo mkdir -p /activateTools
      - run: sudo chmod -R 777 /activateTools
      - run: touch /activateTools/ProjectVersion.txt && cat ~/project/ProjectSettings/ProjectVersion.txt > sudo /activateTools/ProjectVersion.txt
      - restore_cache:
          key: unity-license-{{ checksum "/activateTools/ProjectVersion.txt" }}
      - persist_to_workspace:
          root: /activateTools
          paths:
            - .
  unity-ci-test-editmode:
    executor: unity_executor
    steps:
      - setup_remote_docker:
          docker_layer_caching: true
      - attach_workspace:
          at: /activateTools
      - checkout
      - unity-ci/unity_activate
      - unity-ci/test:
          mode: editmode
      - save_cache:
          key: unity-license-{{ checksum "/activateTools/ProjectVersion.txt" }}
          paths:
            - /activateTools/Unity.ulf
      - persist_to_workspace:
          root: /activateTools
          paths:
            - .

workflows:
  version: 2
  test:
    jobs:
      - setup
      - unity-ci/outputAlf:
          exec: unity_executor
          requires:
            - setup
      - unity-ci/cloneActivateTool:
          requires:
            - unity-ci/outputAlf
      - unity-ci/outputUlf:
          requires:
            - unity-ci/cloneActivateTool
      - unity-ci-test-editmode:
          requires:
            - unity-ci/outputUlf

権限付与が必要だったり、Unityプロジェクトのpathがルートにある前提だったりと改修要素が見えますがファイル認証の対応を優先して行いました。 これでバージョンの壁も突破して実行が可能になると思います。

おわり

UnityのCIをCircleCIで行うために頑張ると以上のようなことも必要になってきました…素直にCloudBuild使う方が楽な気はしますが色々と突破するための技術を学ぶのも中々幅が広くて面白いです。 しかし、Orbsである程度省略して書けるようになったので良きかなと思ってます。ご興味あれば使ってみてください…!