1
/
5

iOSアプリ申請を驚くほど簡単に!fastlaneではじめる自動化入門

ユーザーグロースチームの永島 (@hedjirog) です。

fastlaneの登場により、iOSアプリ開発の様々な作業が簡単に自動化できるようになりました。

あなたがApp Storeへアプリを公開したことがあるなら、手順が多くて面倒なアプリ申請作業も経験したことがあるはずです。fastlaneを利用すれば、面倒なアプリ申請作業さえも簡単に自動化することができます。

今回は、Wantedlyでも実践しているfastlaneを利用したアプリ申請作業を自動化する手順を紹介します。

自動化のメリット

アプリ申請作業の自動化によるメリットはいくつもあります。

まず、申請作業に対する心理的な負担が減ります。iOSアプリは審査期間に時間を要することが多く(最近はAppleにより改善されつつありますが)、リリース後に不具合を含むと発覚した場合の迅速な対処が難しいことから、一定の検証を完了してから申請を行なうのが通例です。リリースサイクルは長くなりがちで、短くても2週間や1ヶ月に1度程度というのが大半ではないでしょうか。申請作業を行なう機会が少ないと、久々に申請作業を行なう際に手順の多い作業を行なうのは、どうしても億劫になってしまいます。申請作業を自動化して手順が簡略化できていると申請の度に作業を億劫だと感じることがありません。

他にも、申請作業の属人化を防いだり、申請の度に(SchemeやConfigurationの指定などを間違えることなく)同じ構成で繰り返しビルドできたりすることも、アプリ申請作業を自動化することにより得られるメリットだと言えます。

fastlaneのメリット

申請作業の自動化にfastlaneを利用すると、自動化すること自体によるメリットが得られるだけでなく、さらに以下の様なメリットも得られます。

fastlaneを利用すれば、iTunes Connectに入力するメタ情報(App Storeで表示されるバージョン情報、概要、スクリーンショット画像など)の変更履歴を管理することができるようになります。通常であればiTunes Connectの入力欄に直接入力するのですが、これではバージョン毎にどのような変更をしたのかを管理するのが困難です。一方、fastlaneを利用するとメタ情報がファイルに含まれる状態で管理されるので、プロジェクト全体がGitなどで管理されていれば自然とメタ情報の変更内容も管理対象となり、バージョン毎にどこを変更したのかを容易に管理することができます。

このような特徴から、GitHubのPull Requestを利用することで、バージョン情報やスクリーンショットの変更をレビューした上でマージするといったこともできるようになります。Wantedlyでは、スクリーンショット画像の差し替えをデザイナーに依頼してGitHubのPull Requestを出してもらうといったことも日常的に行なっていたりします。

スクリーンショット画像の差し替え時のPull Request:


自動化の準備

手順1:fastlaneのインストール

まずは、fastlaneをインストールしましょう。

fastlaneはrubyのライブラリ(gem)として提供されています。通常であれば、fastlaneのドキュメントにあるコマンドでfastlaneをインストールすることができます。

通常のインストールコマンド:

sudo gem install fastlane

Wantedlyでは通常のインストールコマンドではなく、Bundlerを利用することで、チーム内で同じバージョンのfastlaneを利用するようにしています。

まず、Bundlerがどのgemをインストールするかを指定するGemfileをプロジェクトのディレクトリに配置します。Gemfileにはfastlaneの指定を追加します。

source 'https://rubygems.org'

gem 'fastlane'

Gemfileの指定ができたら、Bundlerを利用してfastlaneをインストールします。

また、rbenvなどのrubyのバージョン管理ツールを併用してOS X標準のrubyを利用しなければ、通常のインストールコマンドで必要だったsudoによるコマンド実行の必要ありません。Wantedlyではrbenvを利用してruby関連のコマンド実行時にsudoを指定しない運用にしています。

Bundlerとrbenvを利用することで、ターミナルから以下のコマンドを実行してfastlaneのインストールが完了します。

インストールコマンド(Bundler利用):

gem install bundler
bundle install

fastlaneは様々なツール群で構成されており、アプリ申請作業(の一部であるメタ情報やバイナリのアップロード)はdeliverというツールを介して実行されます。deliver単体で利用する方法もありますが、ここではfastlaneを利用するのを前提に説明を続けます。fastlaneをインストールすることで、依存するdeliverも自動的にインストールされます。

deliver単体でなくfastlaneを利用するようにしておけば、後からfastlaneの他のツールを利用するのが容易になったり、カスタマイズした作業をFastfile(rubyによって記述されるテキストファイル)に記述していつでも実行できるようになります。

手順2:fastlaneの初期化

まずは、初期化コマンドを実行する必要があります。fastlaneの初期化コマンドには、申請作業の自動化のために必要となるファイルの配置や生成なども含まれます。初期化コマンドを実行するだけで申請作業の自動化はほぼ完了してしまうのです。

実際に初期化コマンドを実行しましょう。ターミナルを開いて、プロジェクトのディレクトリで以下のコマンドを実行します。(前述した通り、Bundlerに依存した環境でコマンド実行をするので、先頭にbundle execを指定していることに注意してください。)

初期化コマンド(Bundler利用):

bundle exec fastlane init

以下は初期化処理を実行結果の例です。すでにApp Storeへのアプリ申請作業を行なったことがあり、新たにfastlaneを利用して自動化を試みる想定です。

初期化の実行結果の例(序盤の一部のみ):

コマンドを実行するといくつか入力を求められるので、適切に入力をします。もし、あなたが過去にApp Storeへのアプリ申請作業を行なっているなら、初期化はスムーズに完了します。実行結果の例では、Apple IDの指定と確認時のコマンドのみを入力をするだけで入力が完了しているのがわかります。

さらに初期化処理は続き、iTunes Connectへログイン処理が実行されます。このタイミングで、過去にiTunes Connectで入力したメタ情報とスクリーンショット画像のダウンロードが実行されます。

初期化の実行結果の例(終盤の一部のみ):

初期化が完了するとfastfileディレクトリが新たに作成され、メタ情報はmetadataディレクトリへ、スクリーンショット画像はscreenshotsディレクトリへと配置されたのがわかります。この例の場合は、初期化完了後に以下のようなディレクトリ構成になります。

初期化後のディレクトリ構成の例:

.
├── Gemfile
├── Gemfile.lock
├── Wantedly
│   └── ...
├── Wantedly.xcodeproj
│   └── ...
├── ...
└── fastlane
    ├── Appfile
    ├── Deliverfile
    ├── Fastfile
    ├── metadata
    │   ├── copyright.txt
    │   ├── ja
    │   │   ├── description.txt
    │   │   ├── keywords.txt
    │   │   ├── marketing_url.txt
    │   │   ├── name.txt
    │   │   ├── privacy_url.txt
    │   │   ├── release_notes.txt
    │   │   └── support_url.txt
    │   ├── primary_category.txt
    │   ├── primary_first_sub_category.txt
    │   ├── primary_second_sub_category.txt
    │   ├── secondary_category.txt
    │   ├── secondary_first_sub_category.txt
    │   └── secondary_second_sub_category.txt
    └── screenshots
        ├── README.txt
        └── ja
            ├── 1_iphone6Plus_1.png
            ├── 1_iphone6_1.png
            ├── ...
            ├── 5_iphone6Plus_5.png
            └── 5_iphone6_5.png

あなたが過去にiTunes Connectで申請したことがなければ、メタ情報とスクリーンショット画像のファイルが初期化時に配置されることはありませんが、同様の配置をすることで変更内容の管理ができたり、iTunes Connectへの反映をfastlaneに任せることができます。

メタ情報については、ファイルを配置せずDeliverfileに情報を記述するという手段もあります。詳しくは、Deliverfileのドキュメントを参照すると良いでしょう。

スクリーンショット画像のみをiTunes Connectからダウンロードしてファイルを配置するコマンド(deliver download_screenshots)も存在します。必要に応じて利用してください。詳しくはヘルプコマンド(deliver --help)の内容を参照すると良いでしょう。

Appfileにはアプリの情報が記載されています。複数のアプリを申請する必要がない限り、特に編集することはないかも知れません。

Appfileの例:

app_identifier "com.wantedly.app" # The bundle identifier of your app
apple_id "***@wantedly.com" # Your Apple email address

team_id "**********"  # Developer Portal Team ID

Fastfileには自動的に生成された作業内容が記述されています。ファイル内に以下のようなappstoreというlaneが生成されていますが、これはアプリ申請の作業を表現するものです。

Fastfileの例:

fastlane_version "1.98.0"

default_platform :ios

platform :ios do

  # 中略

  desc "Deploy a new version to the App Store"
  lane :appstore do
    # match(type: "appstore")
    # snapshot
    gym(scheme: "Wantedly") # Build your app - more options available
    deliver(force: true)
    # frameit
  end

  # 中略

end

このlaneを利用することで、fastlaneによるアプリ申請作業の自動化を実現することができます。laneはカスタマイズ可能で、Wantedlyでは多少のカスタマイズをした上で利用しています。この点については後述します。

fastlaneの初期化が終われば最低限の準備は完了です。

手順3:fastlaneによるアプリ申請作業の実行

準備ができれば、あとはターミナルから以下のコマンドを実行するだけで申請作業ができるようになります。(先頭のbundle execの指定については初期化コマンドで前述したのと同等の理由で必要となります。)

申請作業の実行コマンド(Bundler利用):

bundle exec fastlane appstore

驚くべきことに、今までアプリ申請時に行なっていたような、iTunes Connectに申請するバージョンの情報を新しく入力する、Xcodeを起動してアプリのアーカイブをする、アーカイブによって生成されたバイナリをiTunes Connectにアップロードする、といった一連の作業はこのコマンドだけで完結します。一連の作業は自動実行され、あなたはコマンドの実行の完了を待っているだけで良いのです。

自動化のカスタマイズ

準備が適切に完了していれば、Fastfileに記述された作業内容を自由にカスタマイズしてコマンドから実行できるようになっているはずです。

ここではWantedlyが行なっている申請作業のカスタマイズを紹介します。

Wantedlyのカスタマイズ事例

Wantedlyでは、アプリ申請に以下のようなlaneを利用しています。fastlaneの初期化ではappstoreという名称のlaneが生成されていましたが、Wantedlyではdeployという名称のlaneを利用しています。

WantedlyのFastfile:

lane :deploy do |options|
  ensure_git_status_clean

  custom_increment_build_number
  commit_version_bump(
    xcodeproj: "app.xcodeproj",
    message: "Bump bundle version to #{Actions.lane_context[Actions::SharedValues::BUILD_NUMBER]}",
    force: true
  )

  scheme = options[:scheme] || "app"

  gym(
    scheme: scheme,
    configuration: "Release",
    use_legacy_build_api: true,
    include_bitcode: true
  )

  case scheme
  when "app"
    app_identifier = "com.wantedly.app"
    app = "*********"
  when "student"
    app_identifier = "com.wantedly.student"
    app = "*********"
  end

  deliver(
    app_identifier: app_identifier,
    app: app,
    metadata_path: "./fastlane/#{scheme}/metadata",
    screenshots_path: "./fastlane/#{scheme}/screenshots",
    force: true
  )
end

いくつか、説明を加えます。

Fastfileの説明1- オプションの指定:

lane :deploy do |options|
  ...
end

deployというlaneはオプションの指定を可能にしています。Wantedlyでは単一のプロジェクトで2つのアプリの開発を進めています。コマンド実行時にオプションを指定することで、2つのアプリのどちらを申請するかを切り替え可能にしています。オプションを指定する場合、例えば、コマンドは以下のように実行します。

bundle exec fastlane deploy scheme:student

Fastfileの説明2- Gitのコミット状況の確認:

  ensure_git_status_clean

Gitでコミット漏れの変更があると、後から申請時にどのようなソースコードの状態でビルドをしたのか追えなくなってしまいます。予めコミット漏れの差分がないことを確かめてから申請作業を開始します。

Fastfileの説明3- ビルド番号の変更:

  custom_increment_build_number
  commit_version_bump(
    xcodeproj: "app.xcodeproj",
    message: "Bump bundle version to #{Actions.lane_context[Actions::SharedValues::BUILD_NUMBER]}",
    force: true
  )

custom_increment_build_numberというアクションは独自定義したもので、Wantedlyの運用ルールに従ってビルド番号をインクリメントします。アプリ申請時にバイナリをアップデートした後、実装の不備に気付き再度バイナリをアップロードする際は前回のビルド番号と異なっている必要があるという制約があります。この問題を回避するため、申請の度にビルド番号のインクリメントを行なっています。

ビルド番号のインクリメントを行なった場合には差分が発生するので併せてコミットも行なうようにしています。

Fastfileの説明4- オプションの値の取得:

  scheme = options[:scheme] || "app"

コマンド実行時に指定されたオプションを取得します。無指定の場合でもデフォルト値が設定されるようにしています。

Fastfileの説明5- アプリのビルドとパッケージ化:

  gym(
    scheme: scheme,
    configuration: "Release",
    use_legacy_build_api: true,
    include_bitcode: true
  )

fastlaneのツールのgymを利用して、iTunes Connectへアップロードするバイナリ生成のためのビルドとパッケージ化を行なっています。ビルド時にエラーが出ることがあり暫定的な対処としてuse_legacy_build_apiオプションを利用しています。bitcode対応の有無の指定なども併せて行なっています。

Fastfileの説明6- メタ情報とバイナリのアップロード:

  deliver(
    app_identifier: app_identifier,
    app: app,
    metadata_path: "./fastlane/#{scheme}/metadata",
    screenshots_path: "./fastlane/#{scheme}/screenshots",
    force: true
  )

fastlaneのツールのdeliverを利用して、iTunes Connectにメタ情報とバイナリのアップロードを行ないます。Wantedlyでは申請するアプリ毎にメタ情報とスクリーンショットを格納するディレクトリを分けています。metadata_pathオプションやscreenshots_pathオプションを利用してディレクトリの振り分けを行なっています。

まとめ

fastlaneの初期化コマンドを実行するだけで驚くほど簡単に申請作業の自動化ができることを説明しました。初期化コマンドをひとつ実行するだけなので、まずは自分のプロジェクトで試してみても良いかも知れません。

また、カスタマイズの例として、Wantedlyで利用しているFastfileを紹介しました。fastlaneには日々新しい機能が追加されていて、Wantedlyでもまだ利用できていない機能があるかも知れません。fastlaneのドキュメントを見れば新しい機能や詳しいカスタマイズ方法を見付けることができます。

余談ですが、Wantedlyはfastlaneが1.0になる前から利用していて、使い始めた当時は申請作業をする度にコマンドの実行が失敗し、2, 3時間は原因究明に時間を充ててFastfileなどを修正するといった対処をしていました。明らかに手作業で申請するよりも時間が掛かっていたように思います。

fastlaneがメジャーアップデートをして1.x系になってからは状況が変わり、かなり安定して動作するようになりました。申請時はコマンドひとつで申請作業が完了して、自動化した恩恵を十分に受けることができています。

fastlaneを利用したアプリ申請作業の自動化は、すごく簡単で便利なので、ぜひ今日からチャレンジしてみてください!

補足

チーム内で証明書を共有して管理するツールとしてmatchがあります。matchもfastlaneのツールなので、fastlaneを利用した申請作業に組み合わせて利用することができます。以前、Qiitaにmatchの使い方を書いたのでこちらも参考にしてみてください。


iOSアプリ開発に必要な証明書とプロファイルをGitHubのリポジトリで一括管理する - Qiita
WantedlyのUser Growthチームで開発をしている@hedjirogです。 これは、 Wantedly Advent Calendar 2015 19日目の記事です。 この記事では、 iOSアプリ開発に必要な証明書とプロビジョニングプロファイル(以下、プロファイル) をGitHubのリポジトリで一括管理する方法 を紹介します。 iOSアプリのチーム開発をしている現場では、メンバー間での証明書やプロファイルの管理が煩雑になりがちです。 この記事で紹介する内容は、チーム開発の現場で特に有効です 。
http://qiita.com/hedjirog/items/7ad4b85dce27cf673c44

Wantedly, Inc.では一緒に働く仲間を募集しています
45 いいね!
45 いいね!

同じタグの記事

今週のランキング

永島 次朗さんにいいねを伝えよう
永島 次朗さんや会社があなたに興味を持つかも