fastlane を Unity と Xcode 8 で使うときに署名エラーになるのを解決する
Xcode 8 にしたら、いままで使っていた lane でビルドできなくなった。 Xcode 8 から証明書の管理が自動になったため、sigh で取得した証明書が gym で使えずにエラーになっていたのが原因だった。 解決したので、メモを残しておく
概要
- Xcode 8 にアップデートすると既存の fastlane ビルドパイプラインが壊れる
- Xcode 8 から、証明書が自動取得されるようになったため、sigh と競合する
- Xcode プロジェクトの設定を変更して、証明書の指定を手動にすれば良い
環境
- Xcode Version 8.1 (8B62)
- fastlane 1.103.0
- Unity 5.4.2f2
既存の fastlane ビルドパイプラインが壊れる問題
証明書の手動取得
fastlane の issue によると、Xcode プロジェクトの設定を変更すれば良い。
通常の iOS アプリ開発であれば、.xcodeproj
や .xcworkspace
をリポジトリにコミットするので、この方法で問題ない。
しかし、Unity の場合はビルドの度に Unity が Xcode プロジェクトを書き出す形になる。 つまり、書き出された Xcode プロジェクトの設定をビルドの度に変更する必要がある。これは面倒くさい。
案 1: テンプレートの設定を変更する
Unity が Xcode プロジェクトを書き出すための、テンプレートがある(はず)ので、その設定を変更してしまう。
どうやらテンプレートの .xcodeproj
や .pbxproj
ファイルみたいなものはなくて、
/Applications/Unity/Unity.app/Contents/Tools/nodejs/lib/node_modules/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/xcode.py
で生成しているっぽい。
ということで、テンプレートの設定を変更する方針は却下する。
案 2: 書き出されたプロジェクトの設定を変更する
Unity-iPhone.xcodeporj/project.pbxproj
を変更して、証明書の指定を手動で行うように設定する。
ここで問題になるのが、UnityEditor.Xcode.PBXProject
の API が、TargetAttributes の設定には対応していないことである
ということで、.pbxproj
を自分で書き換えることにする。
書き換える場所
PBXProject section > Project object > attributes > TargetAttributes > Unity-iPhone ターゲット
の中に ProvisioningStyle = Manual;
を設定すれば良い。
Xcode のプロジェクト設定を自動化したい場合、diff
を取ると良い(あたりまえ)
-
.pbxproj
をcp
で退避する - Xcode の GUI でぽちぽち設定する
- 更新された
.pbxporj
と退避しておいたもののdiff
を取る
書き換える
fastlane で使っていくので、Ruby で書き換える。CI でクリーンビルドすることを想定しているので、冪等性は考慮しないで、雑に書き換えている。
pbxproj_path = File.join(Dir.pwd, xcodeproj_path, 'project.pbxproj')
pbxproj = File.read(pbxproj_path)
target_id = /([0-9-A-Z]+) \/\* Unity-iPhone \*\/,/.match(pbxproj)[1]
target_attributes = "#{target_id} = {\n\tProvisioningStyle = Manual;\n};"
attributes = /\t+attributes = {\n\t+TargetAttributes = {\n((.|\n)*)\n\t+};\n\t+};/.match(pbxproj)
File.write(pbxproj_path, pbxproj.sub!(attributes[1], "#{target_attributes}\n#{attributes[1]}"))
以上を fastlane action にしたものがこちら
flunity/manualize.rb at master · thedoritos/flunity
lane から action を使うときは、以下のような感じになる。
manualize(
project: './path/to/Unity-iPhone.xcodeproj',
style: 'Manual'
)
gym でビルドするために
ProvisioningStyle = Manual;
に設定した場合、gym
の引数に xcargs
を渡す必要がある。
key | value |
---|---|
DEVELOPMENT_TEAM | 証明書の Team ID |
CODE_SIGN_IDENTITY | 'iPhone Distribution' |
PROVISIONING_PROFILE_SPECIFIER | 証明書の名前 |
このうち、DEVELOPMENT_TEAM
については、 Team ID を AppFile
で設定していることが多いと思うので、そこから取得すれば良い。
CredentialsManager::AppfileConfig.try_fetch_value(:team_id)
ちょっと面倒なのは PROVISIONING_PROFILE_SPECIFIER
の方で、Xcode 8 からは証明書の指定を、 Bundle ID や証明書の UUID ではなく、証明書の名前で行うことになった。
fastlane のドキュメントを読んでも、証明書の名前の取得方法が分からなかったので、環境変数で渡して ENV
で読むことにした。
良い方法をご存知でしたら、ご教示くださると大変よろこびます。
まとめ・感想
- Xcode 8 から、証明書が自動取得されるようになったため、sigh と競合するのを解決した
- Xcode プロジェクトの設定を変更して、証明書の指定を手動にした
- Unity を使う場合
.xcodeproj
はビルドの度に生成されるので、設定を Git リポジトリにコミットしておくことができない(おそらくできないこともないがしたくない) - ビルドの度に毎回手動で設定を変更するのはつらいため、スクリプトで自動化した
- スクリプトを fastlane action 化して、lane から簡単に使えるようにした
- Unity を使う場合
ビルドパイプラインちょくちょく壊れるのまじでつらい。 エコシステム(Unity, Xocde, Android Studio, CocoaPods, Carthage, Gradle など)に複数依存していると、どこかが変更されるたびに壊れるからつらいという構図になっている気がする。