💨

【iOS/Fastlane】App Store Connectへのアップロードを自動化してみよう!

2024/12/11に公開

この記事は クラウドワークス グループ Advent Calendar 2024 シリーズ2の11日目の記事です。

初めまして!クラウドワークスにジョインしているソニックムーブ株式会社(以下SMV)にてiOS/Androidアプリ開発に従事しているShibuyaと申します。
今回はSMVが導入を進めているCI/CDの施策の中から自動化の肝の部分にあたるFastlaneをiOSアプリに導入する流れをまとめていきたいと思います。

そもそもFastlaneってなに?

FastlaneとはiOSやAndroidアプリの配布やテスト周りの作業など自動化することができるCI/CDツールです。Fastlaneではアプリを開発する上で行う定型的な作業をコマンドを実行するだけで動作させることができるようになります。

□ できること

  • 署名済みビルドのアップロード
  • ストアメタ情報の設定
  • テストの実行
  • ビルド番号のインクリメント
  • Firebase App Distributionと連携してテスターへ配布
  • Slackなどへの通知機能
  • etc..

ビルドからテストの実行、ストアへのアップロードなど時間のかかりがちな作業を自動化してくれるだけでなく、結果をSlackなどへ通知を送ることができる機能などをあるのでチームで開発する上でも便利な機能が満載のツールになります。

公式:Fastlane

自動化できることで作業時間を大幅短縮

「ビルド〜ストアへのアップロード」までにかかる時間を仮に以下とします。

  • 回数:週1回
  • 作業時間:1OS / 15分
  • 月4回 × 30分(15分 × 2OS) = 2時間

これがコマンド実行であとは放置しておくだけで良くなるので2時間がほぼ0分に短縮することができるようになります。
魅力しかないFastlaneを導入する流れを見ていきましょう。

Fastlaneの環境を整える

FastlaneはコマンドラインツールなのでまずはPCにFastlaneを使用できる環境を整える必要があります。FastlaneはRubyのGemパッケージマネージャーであるbundlerを使用して管理します。bundlerは以下のコマンドでインストールできます。

$ gem install bundler

インストールが完了したらXcodeプロジェクトにカレントディレクトリを合わせてbundle initを実行します。

$ bundle init

実行するとプロジェクトルートにライブラリを管理する役割を持つGemfileが生成されるのでここにgem "fastlane"を追加しておきます。

Gemfile
# frozen_string_literal: true

source "https://rubygems.org"
gem "fastlane"

追加できたらbundle installコマンドを実行することでFastlaneが使用できるようになります。

$ bundle install

ここまでの作業は最初に一回やっておけばOKです!これでiOSやAndroidアプリにFastlaneを導入する前準備が整いました。

iOSプロジェクトでFastlaneを使ってみる

実際にiOSプロジェクトでFastlaneを使用してみます。bundle exec fastlane initコマンドを使用することでFastlaneの初期セットアップを行うことができます。「ファストレーンを何に使いたいですか?」と問われるので4:手動セットアップを選択して進めていきます。

$ bundle exec fastlane init

# ファストレーンを何に使いたいですか?
What would you like to use fastlane for?
1. 📸  Automate screenshots
2. 👩‍✈️  Automate beta distribution to TestFlight
3. 🚀  Automate App Store distribution
4. 🛠  Manual setup - manually setup your project to automate your tasks

セットアップが完了するとプロジェクトルートにfastlaneディレクトリが生成されます。Fastlaneに関する設定などはこの中で管理していくことになります。デフォルトではAppFileFastfileファイルが自動生成されています。

  • Appfile・・・アプリケーションに関する基本的な情報を設定するためのファイル
  • Fastfile・・・実行するアクションやワークフロー(レーン)を定義するファイル

App Store Connectへアップロードするワークフローを作成する

セットアップが完了したのでApp Store Connectへアップロードするワークフローを作成していきます。手順は以下の通りです。

  1. AppFileにアカウント情報を登録
  2. App Store Connect APIキーの設置
  3. deliverコマンドのセットアップ
  4. ストア情報の準備
  5. レーン作成(deliverコマンド)

1.AppFileにアカウント情報を登録

App Store Connectへアップロードできるように対象アプリのバンドルIDやAppleアカウント情報をAppFileに追加します。それぞれの情報は以下から取得できるので確認してみてください。またここら辺の情報は秘匿情報にしておいた方が良いので間違えて公開してしまわないように注意してください。

・Apple Developer PortalのチームID・・・「メンバーシップの詳細」から確認可能
・App Store ConnectのチームID・・・ログイン後に「※1リンク」で取得できるJSONのcontentProviderIdの値

※1 https://itunesconnect.apple.com/WebObjects/iTunesConnect.woa/ra/user/detail

Appfile
# アプリのバンドルID
app_identifier "com.XXX.XXX"

# Apple ID 
apple_id "sample@sample.com"

# Apple Developer PortalのチームID
team_id "XXXXXXX"

# App Store ConnectのチームID
itc_team_id "XXXXXXX"

App Store Connectに対象アプリ自体が登録されていない場合は先に作成しておく必要があるので注意してください。後続の処理でエラーになってしまいます!

2. App Store Connect APIキーの取得

Fastlaneを使用してApp Store ConnectへビルドをアップロードするためにApp Store Connect APIを使用してJWT(JSON Web Token)を生成して認証する必要があります。JWTを生成するためには「APIキー(.p8ファイル)」を取得しておく必要があるので先に準備しておきます。

App Store Connectから「ユーザーとアクセス」>「統合」>「App Store Connect API」>「チームキー」を選択します。発行したことがなければ「アクセス権をリクエスト」と表示されているのでクリックしてリクエストを実行し、すぐに承認されます、


引用:Apple:ユーザーとアクセス

APIキーを生成」をクリックしてキーの名前と適切なアクセス権限を付与して生成をクリックします。


引用:Apple:ユーザーとアクセス>APIキーを生成

これでAPIキーの作成が完了したので「ダウンロード」をクリックして「APIキー(.p8ファイル)」をダウンロードします。(ダウンロードは一回しか行えないので大切に保管しておいてください)
また画面に表示されている「IssuerID」と「キーID」を後で使用するのでコピーしておいてください。

ダウンロードしたファイルはfastlaneディレクトリと同階層に設置しておきます。

プロジェクト
├── プロジェクト.xcodeproj
├── AuthKey_XXXXXXXXXX.p8
├── fastlane

deliverコマンドのセットアップ

続いてFastlaneで実際にApp Store Connectにビルドをアップロードを行うためのdeliverコマンドのセットアップを行います。以下コマンドを実行します。

$ bundle exec fastlane deliver init

実行するとfastlaneディレクトリの中に「DeliverFile」と「metadata」ディレクトリが生成されます。

fastlane
├── AppFile              
├── Fastfile             
├── DeliverFile              # デリバリーに関する設定ファイル
├── metadata                 # App Storeに必要なメタデータを格納するフォルダ
│   ├── en-US                # 英語のメタデータフォルダ
│   │   ├── description.txt    # アプリの説明
│   │   ├── release_notes.txt  # リリースノート
│   │   ├── copyright.txt      # 著作権
│   │   ├── review_information # アプリレビュー用の情報を含むフォルダ
│   │   │           ├── first_name.txt      # デモアカウントの名
│   │   │           ├── last_name.txt       # デモアカウントの姓
│   │   │           ├── demo_password.txt   # デモアカウントのパスワード
│   │   │           ├── demo_user.txt       # デモアカウントのユーザー名
│   │   │           ├── notes.txt           # レビュー用の追加メモ
│   │   │           ├── email_address.txt   # アカウントのメールアドレス
│   │   │           └── phone_number.txt    # アカウントの電話番号
│   │   └── screenshots        # スクリーンショットを格納するフォルダ
│   └── ja-JP                  # 日本語のメタデータフォルダ
│   │   ├── ・・・

ストア情報の準備

metadata」ディレクトリの中にストアに記載する情報を記載します。
それぞれの項目ごとに専用の空のtxtファイルが用意されているのでその中にストアに反映させたい情報を記述して行けばOKです。

copyright.txt(例)
2024 SonicMoov

レーン作成(deliverコマンド)

実際にdeliverコマンドを実行するレーンを作成していきます。まずはFastfileの中にuploadレーンを追加します。
このレーンの中では以下のような処理を記述していきます。

Fastfile
default_platform(:ios)

platform :ios do
  desc "App Store Connectに署名済みビルドをアップロードします"
  lane :upload do
      # 自動署名設定
      # ビルド
      # 認証キーの生成(JWT)
      # アップロード
  end
end

自動署名や認証キー(JWT)を生成するためにはチームIDなどのアカウント情報が必要になります。
諸々の秘匿情報を管理するために以下のような「.env」ファイルをfastlaneディレクトリと同じ階層に設置して管理しやすくしておきます。

.env
TEAM_ID=XXXXXXXXXX
KEY_ID=XXXXXXXXXX
ISSUER_ID=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXX
KEY_FILE_PATH=AuthKey_XXXXXXXXXX.p8

これで「自動署名〜認証キーの生成(JWT)」までが記述できるようになります。

  • 自動署名:automatic_code_signing
  • ipaファイルを生成:gym
  • JWT生成:app_store_connect_api_key
Fastfile
default_platform(:ios)

platform :ios do
  desc "App Store Connectに署名済みビルドをアップロードします"
  
  lane :upload do
  
    # 自動署名設定
    automatic_code_signing(
      use_automatic_signing: true,   # 自動署名を有効にする
      team_id: ENV['TEAM_ID']        # 環境変数から取得したチームIDを使用
    )
    
    # アプリのビルドを実行(ipaファイルを生成)
    gym(
      scheme: "MyTestApp",            # 使用するXcodeのスキーム名
      output_directory: "./build",    # ipaファイルを出力するディレクトリ
      output_name: "MyTestApp.ipa",   # 生成されるipaファイルの名前
      export_xcargs: "-allowProvisioningUpdates" # プロビジョニングプロファイルを自動的に更新を許可
    )
    
    # App Store Connectのための認証キーを生成(JWT)
    api_key = app_store_connect_api_key(
      key_id: ENV['KEY_ID'],             # 環境変数から取得したAPIキーのID
      issuer_id: ENV['ISSUER_ID'],       # 環境変数から取得した発行者ID
      key_filepath: ENV['KEY_FILE_PATH'] # 環境変数から取得したAPIキーのファイルパス
    )
  end
end

最後にアップロードするためのdeliverコマンドを記述していきます。
記述する前に「DeliverFile」に対象のApple IDのメールアドレスを記述します。

DeliverFile
username "Apple IDのメールアドレス"

deliverコマンドを以下のように記述して完成です。

Fastfile
default_platform(:ios)

platform :ios do
  desc "App Store Connectに署名済みビルドをアップロード"
  lane :upload do
  
    # 自動署名
    automatic_code_signing(
      use_automatic_signing: true,
      team_id: ENV['TEAM_ID']
    )
    # ビルド(ipaファイル生成)
    gym(
      scheme: "FastlaneTest",
      output_directory: "./build",       # 出力先ディレクトリ
      output_name: "FastlaneTest.ipa",   # 出力ファイル名
      export_xcargs: "-allowProvisioningUpdates"  # プロビジョニングプロファイルを自動的に更新
    )
    # 認証(JWTの生成)
    api_key = app_store_connect_api_key(
      key_id: ENV['KEY_ID'],
      issuer_id: ENV['ISSUER_ID'],
      key_filepath: ENV['KEY_FILE_PATH']
    )
    # App Store Connectにアップロード
    deliver(
      api_key: api_key,                       # 認証に使用するAPIキー
      force: true,                            # 以前のビルドを強制的に上書き
      # 提出情報に関する設定
      submission_information: {
        export_compliance_uses_encryption: false,    # 輸入コンプライアンス:暗号化を使用しない
        export_compliance_encryption_updated: false, # 暗号化の状況が更新されていない
        add_id_info_limits_tracking: false,          # ID情報によるトラッキング制限を追加しない
        add_id_info_uses_idfa: false,                # IDFAを使用しない
        add_id_info_serves_ads: false,               # 広告を提供しない
        add_id_info_tracks_action: false,            # アクションをトラッキングしない
        add_id_info_tracks_install: false            # インストールをトラッキングしない
      }
    )
  end
end

実際にアップロードしてみる

ここまで準備が完了したらあとは以下のコマンドを実行するだけです。これでApp Store Connectにビルドが自動でアップロードされストア情報なども自動で設定されるようになります。

$ bundle exec fastlane upload

あとはFastlaneが頑張ってくれている間にコーヒーブレイクの時間がたくさん取れますね!(?)

まとめ

Fastlaneってすごい!!

Fastlaneを使用することでエンジニアの定型的な作業を簡単に効率化することができました。
SMVで取り組んでいるCI/CD施策ではCircleCIを活用して、特定のブランチにマージされたことをトリガーにビルド生成から静的解析の実行、テスト、配布までを完全自動化する仕組みを構築しています。

個人ではなかなか自動化まで触れる機会も少ないかも知れませんが、この記事をきっかけに興味を持ってもらえると嬉しいです。

株式会社ソニックムーブ

Discussion