こんにちは。エンジニアの横田です。
前回、Unity Cloud Buildを使ってiOS用のipaファイルをビルドするところまでをご紹介しました。今回はipaファイルをiOSデバイスでDLできるようにApple Store ConnectのTestFlightにアップロードする手順をご紹介します。

Apple Store ConnectのTestFlightにipaファイルをアップロードする。

調べたところ、ipaファイルをApple Store Connectにアップロードする方法は3つありました。

・Transporter on Windows
・AppUploader
・Unity Cloud Build上のスクリプト

Transporter on Windows
MacではTransporterというアプリでApple Store Connectにipaファイルをアップできるようです。Windows用にはコマンドで動作するTransporter on Windowsというものがありました。
ダウンロードして手順を進めていくと、途中でAppStoreInfo.plistファイルが必要になり、いろいろ試しましたがWindowsだけで正しい書式のAppStoreInfo.plistファイルを用意する事が僕にはできませんでした。
ここを読むとWindowsから Transporter on Windowsでipaアップできるとありますが、手順の途中で「macOS上で.plistファイルを出力する」という
手順があって結局Macがないとダメという事で詰みます。

AppUploader
ネット上の記事でよく登場するのがこのAppUploaderというアプリでした。
わかりやすいGUIで簡単にipaファイルをApple Store Connectにアップロードする事ができますが、有償ソフトなの無償期間がすぎると1ライセンス/365日を30ドルで購入する必要があります。

Unity Cloud Build上のスクリプト
こちらの記事の中で紹介されているのですが、Unity Cloud Buildから直接アップロードする方法というのが存在する事をしりました。
Unity Cloud Build内の設定で、ビルドが終わった後に任意のスクリプトを動作させる事ができるらしいのですが、その中でipaファイルをApple Store Connectに直接アップロードできるコマンドがあるようです。
この方法であれば、ビルド後に自動でアップロードされる上に無料でできるので最終的にはこの方法を採用しました。

スクリプトでipaファイルをApple Store Connectに自動でアップロードする。

まず、大前提として下記の3つが必要になります。
キーID(Key ID)
・issuer ID(Issuer ID)

・秘密鍵(.p8ファイル)

とりあえず下記の内容のシェルスクリプトファイルを作ってUnityプロジェクトのAssets/UnityCloudBuildという適当な名前をつけたフォルダに置きます。
ファイル名は何でも大丈夫ですがとりあえず今回はPost-build.shとしておきます。

#!/bin/bash

# Cloud Build のログでデバッグ表示
echo "=== Post-build スクリプト開始 ==="

# BUILD_PATH の確認(未定義の場合は明示的に fallback)
if [ -z "$BUILD_PATH" ]; then
  echo "警告: BUILD_PATH が未定義です。カレントディレクトリを使用します。"
  BUILD_PATH=$(pwd)
else
  echo "BUILD_PATH: $BUILD_PATH"
fi

# IPAファイルのパス(Unity Cloud Build が自動で設定)
IPA_PATH="$UNITY_PLAYER_PATH"

if [ ! -f "$IPA_PATH" ]; then
  echo "X エラー: IPAファイルが見つかりません: $IPA_PATH"
  echo "=== Post-build スクリプト終了 ==="
  exit 1
fi

echo "IPAファイルのパス: $IPA_PATH"

# App Store Connect API 認証情報を設定
# あなたの APIキーID
API_KEY_ID="YOUR_API_KEY_ID"
# あなたの Issuer ID に書き換えてください
API_ISSUER_ID="YOUR_API_ISSURE_ID"
# .p8 ファイルの復元先
PRIVATE_KEYS_DIR="$BUILD_PATH/private_keys"
API_KEY_FILE="$PRIVATE_KEYS_DIR/AuthKey_$API_KEY_ID.p8"

# base64 を復元
mkdir -p "$PRIVATE_KEYS_DIR"

if [ -z "$UCB_JWT_PRIVATE_KEY" ]; then
  echo "エラー: 環境変数 UCB_JWT_PRIVATE_KEY が定義されていません。"
  echo "=== Post-build スクリプト終了 ==="
  exit 1
fi

echo "$UCB_JWT_PRIVATE_KEY" | base64 --decode > "$API_KEY_FILE"

if [ ! -f "$API_KEY_FILE" ]; then
  echo "エラー: .p8ファイルの復元に失敗しました: $API_KEY_FILE"
  echo "=== Post-build スクリプト終了 ==="
  exit 1
fi

echo ".p8 ファイルを復元しました: $API_KEY_FILE"

# IPA を App Store Connect にアップロード(xcrun 使用)
xcrun altool --upload-app \
  --type ios \
  --file "$IPA_PATH" \
  --apiKey "$API_KEY_ID" \
  --apiIssuer "$API_ISSUER_ID" \
  --verbose

RESULT=$?

# アップロード結果を確認
if [ "$RESULT" -eq 0 ]; then
  echo "TestFlight へのアップロード完了"
else
  echo "アップロード失敗(エラーコード: $RESULT)"
  echo "=== Post-build スクリプト終了 ==="
  exit $RESULT
fi

echo "=== Post-build スクリプト終了 ==="

コード内の”YOUR_API_KEY_ID”と”YOUR_API_ISSUER_ID”の箇所には自分で発行したKey IDとIssuer IDに書き換えないといけないのですが、これらは Apple Store Connectサイト上で発行できます。
発行方法はネットで検索すれば参考になる記事がたくさん出てきますが、公式のヘルプはここが参考になると思います。
僕は社内で発行する権限がなかったので、権限を持っている管理者の方に用意してもらいました。
(正確には権限を付与はしてもらったが、うまくできなかった)
書き換えたらgitにコミットします。

上記のスクリプトを動作させる為に、Advanced settingsタブのScript hooksの項目で Post-build scriptの箇所にPost-build.shファイルまでの
パスを追加してください。


(.p8)ファイルの取扱いに関して
.p8ファイルはAppleの認証キーで非常に重要なファイルです。
リポジトリにコミットすると第三者に漏れる可能性があります。
今回はGitのリポジトリには(.p8)ファイルを含めずにBase64化してUnity Cloud Build上の環境変数にセットし、スクリプトで復号して一時ファイルとして配置する方法をとっています。

ローカルでシェルスクリプトで下記のコマンドを実行する事でbase64化できます。

base64 AuthKey_xxxxxxxx.p8 > AuthKey_xxxxxxxx.p8.b64

base64化された.b64ファイルをメモ帳等で開いて中身の文字列をコピーします。Advanced settingsタブのEnvironment variablesの項目で +Add variablesをクリック。base64化された秘密鍵(.p8)を環境変数として追加しておきます。

Variable key : UCB_JWT_PRIVATE_KEY
Variable value : 先ほどコピーしたbase64化された文字列

お疲れ様です。ここまで来たら再度Buildしてみてください。
ビルド後にipaファイルが自動でApple Store ConnectTestFlightにアップされると思います。


ビルド時にビルド番号がかぶっていてipaファイルのアップロードに失敗する

ipaファイル内のビルド番号がApple Connect上にアップ済みのビルド番号と同じだとアップロードできないという問題が発生しました。
UnityプロジェクトのProject Settingsからビルド番号を手動でインクリメントすれば解決するのですが、毎回ビルドする前に変更するのは手間です。
ビルド番号をスクリプトで自動で更新する方法があるので、こける問題をスクリプトで解決します。
下記のスクリプトをUnityProjectのEditorフォルダ内に置いてください。
内容は、Unity Cloud Build側の環境変数で用意されているビルド番号はビルド毎に自動でインクリメントされているのでこの変数をUnityプロジェクト内のビルド番号に代入するというものです。
これで手動でビルド番号を更新する必要はなくなります。
https://github.com/1-10/UnityCloudBuildUtilities/blob/main/Editor/EditorStartupProcessor.cs


TestFlightにアップロード完了時「輸出コンプライアンスがありません」と毎回表示される

無事にTestFlightにアップロードできても、毎回「輸出コンプライアンス情報の回答」を行う必要があります。
こちらのブログを参考にスクリプトで解決しましょう。
これでアップロード時に輸出コンプライアンスの回答を省略できるのでアップロード完了時、すぐにデバイス側でインストールできるようになります。
最終的に僕が使用しているスクリプトは下記になります。
UnityProjectのEditorフォルダ内に置いてください。
このスクリプトファイルには「輸出コンプライアンス情報の回答」を回避するコード以外のスクリプトも含まれていますので、不必要なら先のブログ先のコードを参考にした方がいいです。
https://github.com/1-10/UnityCloudBuildUtilities/blob/main/Editor/PostBuildProcessor.cs

以上です。手順が多いので3回に渡って記事にしましたが以上でWindows環境のみでUnity製のiOSアプリが開発できる環境が整ったと思います。
本来Xcode側で設定するような項目はほとんどはスクリプトで設定できそうなので、よほどな事がない限りはWindowsだけでも開発できそうです。
このあたりネット上で記事が少ないので、間違っていたりもっとこうした方がいいなどのアドバイスがあれば僕のぜひXのアカウントまで教えていただきたいです!
お疲れ様でした!



参考サイト
【iOS】アプリを提出する度に暗号化の質問に答える必要をなくす方法

TestFlightで毎回表示される「輸出コンプライアンスがありません」の設定を省略する方法


以上です。



■ワントゥーテンでは中途採用募集中です!

1→10(ワントゥーテン)のカルチャーや、作品のクリエイティブに共感し、自身のより高い成長を求めている方からのご応募をお待ちしています!