[Unity] 汎用的なCI環境構築ライブラリを作ったお話

# 概要

[サムザップ Advent Calendar 2022](https://qiita.com/advent-calendar/2022/sumzap) 10日目の記事です。
本稿は業務改善系の記事です。

プロジェクトごとに毎回ビルド環境の構築コストがかかる課題を解決するため、fastlaneを利用したCI環境構築ライブラリを作成しました。
今回はそのライブラリのご紹介になります。

## fastlaneとは

https://fastlane.tools/

Ruby製のライブラリで開発支援ツールです。
アプリビルド〜アプリ申請の自動化を行うことができます。
証明書・プロビジョニングプロファイルの管理など、申請において属人化しやすい作業をアクションという名のコマンドを実行することで再現性のとれたフローを作れます。

# 作ったもの

- Unity向けC#ビルドスクリプト
- ビルドマシン環境構築スクリプト
- プロジェクト環境構築スクリプト

順を追って説明します。

## Unity向けC#ビルドスクリプト

大きく分けて以下のような構成で実装しました。
一部のクラス名は用途がわかりやすいように実際とは異なった名前にしています。

|クラス名|説明|
|:--|:--|
|Builder|アプリビルドを実行する。UnityのビルドAPIを呼び出します。|
|BuildProcessRunner|ビルドプロセスを実行する。BuildProfile,環境変数,コマンドライン引数から最終的なビルドオプションを作成|
|BuildProfile|プラットフォームごとのビルドプロファイル（設定）を保持する|
|UnityCISettings|プロジェクト固有の設定を保持する|

## ビルドマシン環境構築スクリプト

ビルドマシンの環境構築を行うシェルスクリプトを作成しました。
内容的にはfastlane実行のための環境を構築しています。
このスクリプトは初期設定として以下を1度のみ実行します。

- バージョン指定でRubyをインストール（rbenvを使用）
- bundlerをインストール

## プロジェクト環境構築スクリプト

ビルドマシン環境構築スクリプト同様シェルスクリプトで作成しました。
プロジェクト固有の環境を構築します。
このスクリプトで行っているのは以下のとおりです

- rbenvの初期化
- Ruby のローカルバージョン指定（rbenvを使用）
- bundle の設定・Gemfileに記述されているライブラリをインストール
- fastlane初期化・プラグインのインストール
- ビルド先ディレクトリ作成

# 全体構成

以下は本ライブラリを利用し、Jenkinsでビルド環境を構築した例です。
赤で塗っている箇所が今回のライブラリ部分です。
アプリのビルドとアップロードにはfastlaneを使用しています。

![advent_calendar_ci_jenkins.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218179/d5798d99-1292-592c-cfe2-94ccd56b1629.png)

|名称|説明|
|---|---|
|cli-lib-repo|本ライブラリのリポジトリ|
|unity-project-repo|Unityプロジェクトのリポジトリ|
|project-ci-src-repo|プロジェクト固有のCI環境構築・ビルドで使うリポジトリ|

## 留意事項

ビルドマシンのおおまかなシステム要件は以下のとおりです。

- Intel Mac（M1は未検証）
- macOS Catalina (10.15.7) 以上 推奨

## ディレクトリ構成
Unityプロジェクト階層に以下のようなfastlane実行環境を構築します。
`setup` ディレクトリ, `Gemfile`,`Gemfile.lock` はプロジェクト導入時に1度だけコピーする形です。

```shell
.                             # Unityプロジェクトディレクトリ
├── Builds/                   # 本スクリプトによる自動生成
│   ├── Android/              # 本スクリプトによる自動生成
│   └── iOS/                  # 本スクリプトによる自動生成
├── fastlane/                 # 本スクリプトによる自動生成
│   ├── Appfile               # 本スクリプトによる自動生成
│   └── Fastfile              # 本スクリプトによる自動生成
├── setup/                    # セットアップ用のファイルを格納したディレクトリ
│   ├── .gitignore.example    # バージョン管理対象外を記述した.gitignoreサンプル
│   ├── setup_machine_env.sh  # マシン環境構築を行うスクリプト
│   ├── setup_project_env.sh  # プロジェクト環境構築を行うスクリプト
│   └── utility.sh            # 共通ユーティリティスクリプト
├── Gemfile                   # gemライブラリパッケージを記述したファイル
├── Gemfile.lock              # 依存関係とバージョンを記述したファイル
└── vendor/                   # bundle installによる自動生成
```

# 導入のメリット

## プロジェクト毎に環境構築コードを書かなくて済む

以下、太字の部分がライブラリ導入によって簡略化できます。

**1. マシン環境構築
2. プロジェクト環境構築
3. Unityプロジェクトのビルド設定**
4. ビルドマシン構築・設定

つまりメンテナーは**ビルドマシン構築と設定のみに集中できます**。

## ビルド環境の再現性を保証できる

後述する環境構築スクリプト実行により、常に**同じ環境を作れます**。
新しくビルドマシンを増やす際に設定フローから**属人的なミスを排除できます**。

## CIツールに依存しない

CIツールに依存しないよう設計されているため、プロジェクトごとに適したCIツールを選定可能です。
（もちろんCIツールの設定は各自で用意する必要があります）

## 環境構築の手順が単純

以下は環境構築スクリプトをgitクローンして実行するまでの例です。
必要な手順が機械的に処理できる粒度でステップ数も少ないです。

```shell
# 環境構築の実行手順
# ci-libディレクトリにCI環境構築ライブラリを落としてくる
git clone <ci-lib-repository> ci-lib
# unity-projectディレクトリにUnityプロジェクトを落としてくる
git clone <unity-project-repository> unity-project
# ci-libから必要なファイルをコピー（setupディレクトリ,setup.command,Gemfile,Gemfile.lockをunity-project直下へ）
cd ~/unity-project
cp -r ~/ci-lib/setup ~/ci-lib/setup.command ~/ci-lib/Gemfile ~/ci-lib/Gemfile.lock ./
# コマンド実行（対話形式でマシン環境構築とプロジェクト環境構築の有無が選択できる）
chmod +x ./setup.command
zsh ./setup.command

# [Optional] マシン環境構築・プロジェクト環境構築を個別で実行する場合
zsh ./setup/setup_machine_env.sh
zsh ./setup/setup_project_env.sh
```

# 最後に

サムザップでは実際に一部プロジェクトに導入しており、メリットを体感しています。
まだまだ細かい部分で人の手が入ってしまっている等、改善項目はあります。
将来的にはそういったところもケアして、多くのプロジェクトに導入して貢献できればと思っています。

今回は全体構成を主体とした記事のため詳細は割愛しました。
それぞれの詳細はどこか別で記載できればと思います。
本記事が、同様の課題を抱えているプロジェクトの改善につながれば幸いです。