Github Actions と fastlane で iOS アプリをアーカイブしてビルドを提出する
概要
Github Actions と fastlane を使って iOS アプリをアーカイブしてストアにアップロードしてみました。
Firebase App Distribution を使ってベータ版を配信したりする記事は結構ありますが、リリース前まで持っていくのはなかったので手順を残しておきます。
注: Github Actions の制限の関係もあるので、Private なリポジトリで試す時には無料枠に注意してください。
Secrets に設定するもの
証明書やパスワードなどリポジトリに直接コミットしたくない物はリポジトリの Secrets に設定して Github Actions から参照できるようにします。
Secrets の説明にある通り Github Actions からのみ参照されるっぽいですが、Public なリポジトリで使用する際は自己責任でお願いします 🙇♂️
シークレットは、暗号化され、選択したアクションにのみ公開される環境変数です。 このリポジトリへの共同編集者アクセス権を持つユーザーは、ワークフローでこれらのシークレットを使用できます。
シークレットは、フォークからのプルリクエストによってトリガーされるワークフローには渡されません。
※ リポジトリの Secrets にある説明を翻訳
今回設定した物は以下の通りです。
■ CERTIFICATE
リリースに必要な証明書です。キーチェーンから書き出します。
証明書はバイナリになっているようなので、BASE64 エンコードしてテキストにしたものを設定します。ワークフロー内でデコードして使います。
# 書き出した証明書を BASE64 エンコードする
# テキストファイルに文字列がずらっと並んでいるので、それをまるっとコピーして貼り付けます
openssl base64 -in <書き出した証明書の名前>.p12 -out certificate_base64.txt
本来この辺りは match を使う方がスマートに管理できると思いますが、
今回はサクッと試したかったので Secrets に登録してしまっています。
■ CERTIFICATE_PASSWORD
証明書をキーチェーンから書き出した際に設定したパスワードです。
■ PROVISIONING_PROFILE
アプリに紐づいているプロファイルです。
これも BASE64 エンコードして、ワークフロー内でデコードします。
■ KEYCHAIN_PASSWORD
キーチェーンで使用するパスワードです。
一時的なものなのでなんでもいいみたいです。
■ APPLE_ID
本来 fastlane の Appfile とかに記述する Apple ID です。
なんとなくコミットしたくなかったので Secrets に登録しています。
AppFile 等で既に設定してある場合は不要です。
■ FASTLANE_PASSWORD
後述する fastlane の deliver で Apple ID を使ってログインするので、
その際に使用する Apple ID のパスワードを設定します。
■ FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD
Apple の 2FA で使用する App 用パスワードを設定します。
App 用パスワードの発行については公式のサポートを参照してください。
■ FASTLANE_SESSION
fastlane 上で Apple の 2FA を通すために使用します。
App 用パスワードを発行し、以下のコマンドを実行することで得られる値を設定します。
fastlane spaceauth -u xxxxx@xxx.com
このコマンドは Apple ID の ログインセッションを取得していて、セッションが切れる度にこのコマンドを叩いて値を更新する必要があるみたいです。
どのくらいでセッションが切れるかまでは観測できていませんが、代替案として 2FA を設定していないアカウントを使用するという方法もあるみたいです。
Fastfile
fastlane にはアプリをアーカイブしてビルドをアップロードする部分をやってもらいます。
■ 前準備
まずはアーカイブするために必要な証明書とプロファイルを CI の環境にインポートするレーンを用意します。
private_lane :import_certificates_and_provisioning_profile do
create_keychain(
name: "ios_app_keychain",
password: ENV["KEYCHAIN_PASSWORD"],
timeout: 1800
)
import_certificate(
certificate_path: "distribution.p12",
certificate_password: ENV["CERTIFICATE_PASSWORD"],
keychain_name: "ios_app_keychain",
keychain_password: ENV["KEYCHAIN_PASSWORD"]
)
install_provisioning_profile(path: "distribution.mobileprovision")
end
■ アプリのアーカイブとアップロード
先ほど作成したレーンを実行して証明書等をインポートした後に、
アーカイブとビルドのアップロードを行います。
アーカイブには gym 、アップロードには deliver を使っています。
deliver を使ってメタデータ( アプリの説明文など )を一緒にアップできるみたいでしたが、今回は特に管理していないのでスキップしました。
lane :release do
import_certificates_and_provisioning_profile
build_app(
scheme: "ビルドするアプリのスキーム",
export_options: {
method: "app-store"
}
)
deliver(
username: ENV["APPLE_ID"],
app_identifier: "アプリのバンドルID",
submit_for_review: false,
force: true,
skip_screenshots: true,
skip_metadata: true
)
end
Github Actions のワークフロー
以下のワークフローでは master にプッシュされたタイミングで設定した Secrets を読み込んだり、CocoaPods や Carthage のキャッシュの設定などを行っています。
自分は CocoaPods と Carthage の両方を使用していたので、ここでは両方とも設定しています。
name: Swift
on:
push:
branches: [ master ]
jobs:
build:
runs-on: macos-latest
steps:
# 1. ソースのチェックアウト
- uses: actions/checkout@v2
# 2. 証明書を Secrets から取得
- name: Setup p12 certificate file
run: |
echo "${{ secrets.CERTIFICATE }}" > distribution.p12.txt
base64 --decode distribution.p12.txt > distribution.p12
# 3. アプリ本体用のプロファイルを Secrets から取得
- name: Setup provisioning profile
run: |
echo "${{ secrets.PROVISIONING_PROFILE }}" > distribution.mobileprovision.txt
base64 --decode distribution.mobileprovision.txt > distribution.mobileprovision
# 4. CocoaPods のキャッシュの設定
- uses: actions/cache@v2
with:
path: Pods
key: ${{ runner.os }}-pods-${{ hashFiles('**/Podfile.lock') }}
restore-keys: |
${{ runner.os }}-pods-
# 5. キャッシュから Pods ファイルを取得、なければそのまま pod install
- name: Install CocoaPods frameworks and build with custom scripts
if: steps.cache-cocoapods.outputs.cache-hit != 'true'
run: pod install
# 6. Carthage のキャッシュの設定
- uses: actions/cache@v2
with:
path: Carthage
key: ${{ runner.os }}-carthage-${{ hashFiles('**/Cartfile.resolved') }}
restore-keys: |
${{ runner.os }}-carthage-
# 7. キャッシュから Carthage 関連のファイルを取得、なければそのまま carhage bootstrap
- name: Install Carthage frameworks
run: carthage bootstrap --platform iOS --cache-builds
# 8. アーカイブして ipa をアップロード
- name: Upload a new build to App Store Connect
env:
FASTLANE_PASSWORD: ${{ secrets.FASTLANE_PASSWORD }}
FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD: ${{ secrets.FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD }}
FASTLANE_SESSION: ${{ secrets.FASTLANE_SESSION }}
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
CERTIFICATE_PASSWORD: ${{ secrets.CERTIFICATE_PASSWORD }}
APPLE_ID: ${{ secrets.APPLE_ID }}
run: fastlane release
最後に
CI を設定したことで、自分の Mac でアーカイブする作業がなくなり、より開発に集中できるようになりました。
実装してあとは指定のブランチにプッシュするだけなのでめちゃくちゃ楽です😎
参考にさせていただいた記事
- [iOS] GitHub Actionsでfastlaneのmatchを使わずにAdHoc書き出しをしてからFirebase App Distributionにアップロードする
- GitHub Actions+Firebase App DistributionでiOSアプリをAd hoc配布するための構成例
- BitriseでFastlane Pilotを実行してiOSアプリをアップロードする際に2FAでエラーが発生した時の対応