(開発的な意味で)チームで働くことはほぼなくて1人でiOSアプリを開発していると、1件1件最新ビルドが欲しいという要望に応えるのが難しかったです。……というか、僕は限界だったのでJenkinsを導入してJenkinsおじさんを酷使していました。
それ以降、Xcodeプラグインを使ったり使わなかったりと試行錯誤の末、コマンドライン直叩きスタイルで落ち着きました。僕が使っているコマンドラインの一覧は一通り「Xcodeでのビルドを自動化するxcodebuildコマンドとIPAファイルを作成してiTunes Connect(Testflight)に投げる方法 - 酢ろぐ!」で書きました。
先日から着手した新しい案件で初めてCocoaPodsを使ってみました。CocoaPodsはVisual StudioでいうところのNuGetのようなものです。
今更かもしれませんが昔からのコードをメンテばかりしてきたので、CocoaPodsを導入できずにいたんですよね。導入してみると、これがかなり便利でPodfileに使いたいライブラリをペペーンって書くとインストールしてくれているという優れもので、 なんで今まで使ってなかったんだろうと思うレベルです。
CocoaPodsを使ったプロジェクトは、iPhoneシミュレータ上で実行している時には特に問題なく動いていました。Jenkinsでもアスタリスク(*)なAd-Hocプロビジョニングプロファイルでビルドしている時にもすんなりとビルドできていたため、今回の問題に気付きませんでした。
今日、In-houseなプロビジョニングプロファイルに差し替えたところJenkinsおじさんがアラートを吐き出すという現象が発生してしまいました。証明書のインストールでミスってるのかな?Build Settingsで諸々の設定を間違っているのか?と色々疑って無駄に時間を消耗してしまいました。
どんなエラーがでていたのか?
下記のようなエラーが発生していました。
CocoaPodsが生成したPod側のプロジェクトのBundle IDが'org.cocoapods.*'になっていたためにプロビジョニングプロファイルが持っているプリフィックスと相違しておりビルドに失敗しています。
=== BUILD TARGET Pods-Realm OF PROJECT Pods WITH CONFIGURATION Release === Check dependencies Code Sign error: Provisioning profile does not match bundle identifier: The provisioning profile specified in your build settings (“XXXXXXX In-house Distribution”) has an AppID of “jp.ch3cooh.*” which does not match your bundle identifier “org.cocoapods.Realm”. CodeSign error: code signing is required for product type 'Framework' in SDK 'iOS 8.3'
pod install
を実行すると元々のプロジェクト(ここではhoge.xcodeprojとする)とライブラリ群を抱えたPodsプロジェクトを含むxcworkspaceが生成されます。
━hoge.xcworkspace
┃
┣━hoge.xcodeproj (アプリが入ってる側)
┗━Pods.xcodeproj (ライブラリが入ってる側)
Jenkinsのログに残っていたのは下記のようなエラーでした。アプリのBundle Identifierはjp.ch3cooh.hoge
で、Pods側のBundle Identifierはorg.cocoapods.Realm
になっていました。
Xcodeを使っていると自動的に解決してくれるのですが、コマンドラインからビルドした場合は自動では解決してくれないので2時間ほど悩んでしまいました。
どんなコマンドで失敗したのか?
Jenkinsでgit clone
してpod install
してから以下のコマンドでビルドしています。
pod install # schemeがないので一旦Xcodeを開いて初期化する # てかここを自動化できていないの問題なのでは( pgrep -f "/Applications/Xcode.app" | xargs kill open hoge.xcworkspace sleep 10 pgrep -f "/Applications/Xcode.app" | xargs kill # ビルド開始する xcodebuild -sdk iphoneos \ -workspace hoge.xcworkspace -scheme hoge \ -configuration Release clean build \ CODE_SIGN_IDENTITY='iPhone Distribution: XXXXXXXXX.' \ PROVISIONING_PROFILE='XXXX-XXXXX-XXXXX'
解決したけど強引かも……
プロビジョニングプロファイルのIDと相違があることが署名できない原因なので、Podfileでなんらかのパラメータを指定すればインストール時のBundle Identifierを指定できるのではないか?と考えましたが見つからず。
最終的に「A post install script for CocoaPods that changes the bundle identifier of all pods to the one specified. · GitHub」を参考に、pod install
の完了後にPod側のプロジェクトのInfo.plistを書き換えるという手段に出ました。
post_install do |installer| installer.project.targets.each do |target| target.build_configurations.each do |config| if config.name == 'BREnterprise' config.build_settings['CODE_SIGN_IDENTITY[sdk=iphoneos*]'] = 'iPhone Distribution: XXXXXXXXX.' config.build_settings['PROVISIONING_PROFILE'] = 'XXXX-XXXXX-XXXXX' end end end # change bundle id of each pod to 'com.bottlerocketapps.*' bundle_id = 'jp.ch3cooh' directory = installer.config.project_pods_root + 'Target Support Files/' Dir.foreach(directory) do |path| full_path = directory + path if File.directory?(full_path) info_plist_path = full_path + 'Info.plist' if File.exist?(info_plist_path) text = File.read(info_plist_path) new_contents = text.gsub('org.cocoapods', bundle_id) File.open(info_plist_path, "w") {|file| file.puts new_contents } end end end end
もっと良い手段があれば知りたいです……というかCocoaPodsを使っている人はみんなここでつまづくと思うんだけどどうやって解決してるんだろう。良い方法があれば教えて下さい。