はじめに
こちらは「コドモン Adevent Calendar 2024」の6日目の記事です。
こんにちは、エンジニアの重田です。2024年はモバイルアプリの基盤をCapacitorに移行しました。ビルド周りにも手を入れてiOSアプリのCloud Signingを導入したところ、地味に面倒な作業から解放されました!
🎉年に1回の証明書やProvisioning Profileの更新作業がゼロに🎉
🎉検証用のデバイスを追加するたびにProvisioning Profileを更新する作業がゼロに🎉
🎉CIマシンにProvisioning Profileなど必要なファイルを設置する作業がゼロに🎉
前提
- Xcode Cloudは使っていません
- Xcodeで、Automatically manage signingのチェックをいれる必要があります
- Github ActionでiOSアプリをビルドし、AppStoreConnectにアップロードしています
- 今回ビルドしているアプリは、純粋なネイティブアプリではなく、Capacitorを利用しています
本記事で紹介する内容は、純粋なネイティブアプリでも、クロスプラットフォーム技術(Flutter, ReactNative, Capacitorなど)を使ったアプリでも同じように使えると思います。
Cloud Signingとは?
これまでローカルやCIマシンで行っていたiOSアプリのコード署名を、クラウド(Appleのサーバー)で行う技術です。
基本的な処理の流れ
xcodebuild archive
でアーカイブを作成- このとき通常はコード署名を行うが、Cloud Signingの場合はスキップする
xcodebuild -exportArchive
でipaファイルをエクスポート- このときクラウド上で署名する
- AppStoreConnectにアップロード
Cloud Signingを利用する場合、証明書や秘密鍵をCIマシンに配置する必要はありません。なので、年に1回の証明書の更新作業や、デバイスを追加するたびにprovisioning profileを更新する作業から開放されます!
処理の詳細
1. Archive
- name: archive run: | xcodebuild archive \ -workspace ios/App/App.xcworkspace \ -scheme App \ -sdk iphoneos \ -configuration $BUILD_CONFIGURATION \ -archivePath App.xcarchive \ CODE_SIGNING_REQUIRED=NO \ CODE_SIGNING_ALLOWED=NO shell: bash
※workspace, schemeなどの値は、プロジェクトにあわせて書き換えてください ※$BUILD_CONFIGURATIONはビルドの種類に応じてDebug/Releaseなどを設定してください
ここでのポイントはCODE_SIGNING_REQUIRED=NO
と CODE_SIGNING_ALLOWED=NO
です。アーカイブ時にはコード署名をスキップすることで、エクスポート時にCloud Signingを利用できるようになります。
2. Entitlementsの指定
このステップは情報が少なく、一番苦労しました。
当初、この処理無しで進めていたところ、プッシュ通知が届かなくなりました。プッシュ通知を利用するためにはEntitlementsの設定が必要ですが、Entitlementsはコード署名に埋め込まれるので、前述のArchiveステップでコード署名をスキップしたことにより未設定の状態になっていたのです。
この問題は、次のようにEntitlementsを設定して解決しました。
- name: Specify entitlements run: | ENTITLEMENTS_PATH="ios/App/App/App.entitlements" codesign --entitlements $ENTITLEMENTS_PATH -f -s "-" \ App.xcarchive/Products/Applications/App.app shell: bash
※Entitlementsやappのパスは、プロジェクトにあわせて書き換えてください
ここでのポイントはcodesign
のオプションに指定している-s "-"
です。
通常だと、-s
オプションにはiPhone Distribution
のようなSIGNING IDENTITYを指定する必要があります。そのためには証明書や秘密鍵も必要だったりして、せっかくのCloud Signingのメリットがなくなってしまいます。
そのとき、よくよくman codesign
を見てみると"-"
を指定するやり方を発見しました。ad-hoc signingとして処理され実質コード署名されないようですが、今回はEntitlementsを設定したいだけで、実際の署名はクラウドで行われるためこちらを利用しました。
3. Export
Exportについては、WWDCのこの動画がわかりやすいです。 https://developer.apple.com/jp/videos/play/wwdc2021/10204/
16:30秒あたりからの「Automating distribution」の部分です。
※動画の20:41のところから引用
アーカイブファイル、Exportの設定を記述したplist、AppStoreConnectのAPIキーの3つをつかって、xcodebuild -exportArchive
を実行します。
- name: export IPA id: export-ipa run: | xcodebuild \ -exportArchive \ -archivePath App.xcarchive \ -exportOptionsPlist ios/App/App/ExportOptions/Debug.plist \ -exportPath dist \ -allowProvisioningUpdates \ -authenticationKeyPath $AUTH_KEY_PATH \ -authenticationKeyID ${{ inputs.apple-api-key-id }} \ -authenticationKeyIssuerID ${{ inputs.apple-api-issuer-id }} shell: bash
※archivePathやexportOptionsPlist等は実際のパスにあわせて書き換えてください
ここでのポイントは2つあります。
-exportOptionsPlist
エクスポートするときの設定をplistに記載し、そのパスを指定しています。最低限以下の内容があれば大丈夫です。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>method</key> <string>developmentやapp-storeなどをしてください</string> <key>destination</key> <string>export</string> <key>teamID</key> <string>ご自身のチームIDを設定してください</string> <key>signingStyle</key> <string>automatic</string> </dict> </plist>
-allowProvisioningUpdates
以下
allowProvisioningUpdates
を指定することでクラウドでprovisioing profileの更新が許可され、Cloud Signingが有効になります
その下のauthenticationKeyPath
authenticationKeyID
authenticationKeyIssuerID
はAppStoreConnectのAPIを利用するために必要なAPIキー等の情報です。ドキュメント等を参考に生成してください。Cloud Signgingを利用するため、APIキーのロールはAdminにしてください(参考: ロールごとの権限の一覧表)。
これらは秘匿値なので別の場所においておき、ワークフローのなかでそれを取得して利用します。
authenticationKeyPath
はファイルのパスを指定する必要があります。Github Actionsのシークレットを利用する場合は、base64エンコードした文字列を保存しておき、ワークフローのなかでdecodeしてファイルに書き出すとよいです。
- name: create Auth Key run: | echo -n '${{ inputs.apple-api-auth-key-base64 }}' | base64 --decode > ./AuthKey_${{ inputs.apple-api-issuer-id }}.p8 shell: bash
Exportが成功するとipaファイルが生成されるので、テスト配布用のサービスやAppStoreConnectにアップロードできます。
これで地味に面倒な証明書等の更新作業から解放されました!
おわりに
面倒な作業はどんどん自動化して、本来やるべき開発に注力する時間を増やしていきましょう!
もしコドモンのモバイルアプリやフロントの基盤改善にご興味のある方いれば、Pittaからお話できるとうれしいです。
それでは、コドモンアドベントカレンダーの明日の記事もお楽しみに〜!