UnityCloudBuildでTestFlightへの配信を完全自動化する
UnityプロジェクトのiOSパッケージビルドを行い、TestFlight配信の完全自動化、しかもUnityCloudBuildで、が出来るようになったので、記事としてまとめたいと思います。
目標
Unityプロジェクトの成果物をiOS端末で気軽に確認したい
ビルドの自動化が目標
git push -> TestFlightからアプリが降って来る!の流れにしたい
目標を達成する上での制約や要件
TestFlightを使う
AdHoc配信だと端末に制限が出る
InHouseにするまでもない
証明書の管理やビルド設定を個別に教えるコストを省きたい
Jenkinsの面倒を見なくて済むように
fastlaneを使う手段は除外
UnityCloudBuildを使用する
Unityライセンスの消費がされないメリットがある
UnityCloudBuildでの完了通知を検知が必要
WebHookが設定出来るが、外部ネットワークに公開しないといけない
iOSビルド番号のインクリメントを自動化する必要がある
TestFlight配信では必須
iTunesConnectでの「輸出コンプライアンスの確認」チェックをする手間を省く
結果
諸々の手順は後回しに、結果的に以下の流れになりました。
bitbucketにpush
bitbucketのpush通知を #cloudbuild のチャンネルに流す
UnityCloudBuildのAuto-Buildが更新を検知
UnityCloudBuildがiOSビルド開始
iOSビルドの完了
slackの #cloudbuild のチャンネルで完了通知を流す
slackに常駐しているbotが #cloudbuild のチャンネルに流れた完了通知を検知
Jenkinsのjobを実行
TestFlightへアップロード
TestFlightから配信される
slack上のログではこうなります
https://gyazo.com/6ccd95e0dd979e58b464f5e44806917f
git push -> TestFlightからアプリが降って来る!
の環境ができました。
残りは設定方法などの手順を公開して行きます。
iOSビルド番号のインクリメント
以下のファイルを作成します。
code:Assets/Editor/CloudBuildHelper.cs(cs)
using UnityEngine;
using UnityEditor;
using System;
public class CloudBuildHelper : MonoBehaviour
{
public static void PreExport(UnityEngine.CloudBuild.BuildManifestObject manifest)
{
string buildNumber = manifest.GetValue("buildNumber");
if (buildNumber != null) {
PlayerSettings.iOS.buildNumber = buildNumber;
}
}
}
処理内容としてはビルド番号を
iOSビルド番号 = UnityCloudBuildのビルド番号
に指定されるようにします。これでビルド番号がかぶることがなくなります。
作成したファイル内の処理が走るように、UnityCloudBuildの設定で「エクスポート前メソッド」に設定します。
https://gyazo.com/7091a36abfc75d611c55ae366fc8a6a2
他にもこちらの情報が使用できるので閲覧しておきましょう。
使用できる情報はこのページのマニフェスト情報が使える
「輸出コンプライアンスの確認」チェックの回避
以下のファイルも作成します。
code:Assets/Editor/BuildBatch.cs(cs)
using UnityEngine;
using UnityEditor;
using UnityEditor.iOS.Xcode;
using UnityEditor.Callbacks;
using System;
using System.Linq;
using System.IO;
using System.Collections.Generic;
public class BuildBatch : MonoBehaviour
{
// iOSのTestFlightで「輸出コンプライアンスの確認」の設定チェックの回避
public static void ChangeXcodePlist(BuildTarget buildTarget, string pathToBuiltProject)
{
if (buildTarget == BuildTarget.iOS)
{
string plistPath = pathToBuiltProject + "/Info.plist";
var plist = new PlistDocument();
plist.ReadFromString(File.ReadAllText(plistPath));
var rootDict = plist.root;
rootDict.SetString("ITSAppUsesNonExemptEncryption", "false");
File.WriteAllText(plistPath, plist.WriteToString());
}
}
}
処理内容としては、UnityのXcodeビルド完了後にXcodeプロジェクト内の ITSAppUsesNonExemptEncryption を false に設定します。
ここまででUnityCloudBuildで作成されたipaファイルをiTunesConnectにアップロードすれば、勝手にTestFlightで配信されるようになりました。
次はiTunesConnectへアップロードする方法になります
iTunesConnectへのアップロード
Jenkinsでアップロードする
Jenkinsを使いたくない気持ちとは裏腹に、やっぱり便利なJenkinsを使わざるを得なくなりました。使いましょう。
Jenkinsのリモートからビルドに対応したjobの作成、以下のシェルの実行がされるように設定をします
code:シェルの実行(bash)
export api_key=<UnityCloudBuildのAPIキー>
export orgid=<UnityCloudBuildのorgid>
export projectid=<UnityCloudBuildのプロジェクトキー>
export buildtargetid=<UnityCloudBuildのビルドターゲットID>
export filepath=build.ipa
export user=<iTunesConnectへのアップロードユーザーのメールアドレス>
export pass=<iTunesConnectへのアップロードユーザーのパスワード、2ファクト認証を設定してAppパスワードを指定するのがおすすめ>
export url=`curl \
-s -X GET \
-H "Content-Type: application/json" \
-H "Authorization: Basic ${api_key}" \
curl --output ${filepath} ${url}
/Applications/Xcode.app/Contents/Applications/Application\ Loader.app/Contents/Frameworks/ITunesSoftwareService.framework/Support/altool --upload-app -f ${filepath} -u ${user} -p ${pass}
jqコマンドをあらかじめインストールして置きましょう。
処理内容としては、UnityCloudBuildのAPIを実行して最新の成功したビルドからipaファイルを取得、iTunesConnectにアップロードしています。
ここで使用しているJenkinsはMac miniを想定しています。
だけどこのJenkinsは外部に公開していません。セキュリティ的なリスクから社内ネットワークのみからしかアクセスができません。そうなるとUnityCloudBuildからの完了通知を受け取ることができなくなります。
そこで今回はslackに常駐しているbotに働いてもらいましょう。
slack botが完了通知を検知
slack上に常駐するチャットボットを使用します、hubot製です
slackに流れた単語に反応するように設定できます
UnityCloudBuildの完了通知に反応してJenkinsのjobを実行するように設定しました
設定コードはググれば出て来るので割愛
反応する文言 + 反応する部屋 はセットで設定します
反応する文言は以下で設定しています
code:反応する文言
Build success
Default iOS
社内ネットワークに存在しているJenkins実行のためのアプローチですが、これ以外にも設定方法はあるかもしれないです。
以上で設定方法が完了しました。
繰り返しになりますが、設定を行う事によって以下の流れが実現されます。
https://gyazo.com/6ccd95e0dd979e58b464f5e44806917f
UnityCloudBuildでTestFlight配信の完全自動化の道。これにて完了になります。
そもそも公式で出来ないの?
完全自動化が出来ることには出来た
だけど思いの外最初の設定が面倒臭い事になりました
公式で対応する予定はないのか?
現状はiOSビルドは出来るが、そのあとのTestFlightへのアップロードには対応していない
対応待ちのFeedbackは存在している