OTTサービス事業部で iOSアプリ開発を担当しております片山です。
プライベートで使用しているのはAndroidです。
今回の主題
今回の主題はずばり アプリバイナリ作成の自動化 です。
iOS/Androidアプリを開発する上で避けては通れないものとして、アプリケーションを1つに固める作業があります。
Archive
や Generate Signed Bundle
などいろいろ名称はありますが、これを行わなければApp StoreやGoogle Playに公開することはできません。
また、社内テストや(エンドユーザーではない)顧客への受け入れ確認などを考えると、この作業の回数は途方もなく多くなります。
そしてこの作業は、Xcodeから行うと1環境分を作るのにビルドで待たされ、終わったあとにまたGUIでの操作が必要になります。
本番環境用にArchiveを始め、10分ほど待たされ、コーヒーを淹れて帰ってきたらOrganizerが開いていてそこからExportして、ステージング用にArchiveを始めて…
ときにはOrganizerが開いたことに気付かずいつの間にかビルドが終わっていた、なんてこともしばしば。
CLIでコマンドを一つ叩くだけでビルドからファイル化、アップロードまでを自動化をすることでそれらを解決する、それがfastlaneなのです。
fastlaneで自動化へ
ゴール
今回はiOSをターゲットとし、プロジェクトディレクトリ直下のDeploy配下
に、[project-name].ipa
ファイルを作成する環境を作成することをゴールにします。
fastlaneを使用すれば、Firebaseと接続しApp DistributionやAWS S3の特定ディレクトリへのアップロードまで自動化が可能です。
scp等を使用して会社で管理されているサーバーにアップロードする等も実現できます。
これについては今後の記事でお話させていただければと思います。
前提
Xcodeがインストールされていること
導入
弊社プロダクトでは、fastlaneを利用しています。
導入方法をざっくりと説明すると下記の5ステップ。
ruby
とrubygems
をインストールrubygems
を使ってbundler
をインストールbundle init
をし、Gemfile
を生成Gemfile
にgem 'fastlane'
を追記bundle install
でfastlaneをインストール
これでプロジェクトディレクトリで fastlane
コマンドが使えるようになります。
bundler
でインストールをしたため、今後はbundle exec fastlane 〜
というコマンドになります。
Xcodeを認識させる xcode-install
自動化ビルドを進めるにあたって、XcodeのGUIを使用しないようには出来ますが、 ビルドにはxcodebuild
というXcodeコマンドが必要になります。Command Line Toolsと呼ばれております。
なので、fastlaneにCommand Line Toolsを認識させるためのライブラリもインストールしておきます。
Gemfile
にgem 'xcode-install'
を追記し、再度bundle install
をターミナルで打ちます。
このライブラリは、fastlaneの設定ファイルを編集するときに使用します。
実際に環境を作る
bundle exec fastlane init
とコマンドを打つとこのような表記が出ます。
fastlane can help you with all kinds of automation for your mobile app We recommend automating one task first, and then gradually automating more over time 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
上から
- スクリーンショットの自動化
- ベータ版やTestFlightへの自動アップロード
- App Storeへの自動アップロード
- 自分で設定する
となっています。今回は 4. を選びます。
いろいろなことが流れますが、すべてEnterで問題ありません。
以下は内容を意訳したものです。
新しいファイル`fastlane/Fastfile`と`fastlane/Appfile`を作成しました、gitに追加すればチーム全員がfastlaneの恩恵を受けることができます。 fastlaneでは「Fastfile」を使って自動化設定が保存できます。 スクリーンショットやコードサイニング、新しいリリースの作成などの様々な異なるタスクを自動化するために存在します。 お好みのエディタで作成されたFastlaneを開いてみてください。 利用可能なレーンやアクションを編集し、自分のニーズに合わせてカスタマイズすることが出来るようになりました。 利用可能なアクションを学びたい場合、https://docs.fastlane.tools/actions にアクセスしてください。 スクリーンショット自動化については https://docs.fastlane.tools/getting-started/ios/screenshots/ ベータ版のアップロードについては https://docs.fastlane.tools/getting-started/ios/beta-deployment/ App Storeへのリリースについては https://docs.fastlane.tools/getting-started/ios/appstore-deployment/ コードサイニングについては https://docs.fastlane.tools/codesigning/getting-started/ を参照してください。
最初にあるとおり、今後は fastlane/Fastfile
を編集して、自動化タスクを作成していきます。
ここからは実際のサンプルを提示しながら進めていきます。
laneの作成
bundle exec fastlane init
をした直後のFastfileには以下のような記述があります。
platform :ios do desc "Description of what the lane does" lane :custom_lane do # add actions here: https://docs.fastlane.tools/actions end end
ターミナルで bundle exec fastlane [lane_name]
と打ったときの lane_name
となるのが、上記で言うところの custom_lane
の部分になります。
# add actions here: https://docs.fastlane.tools/actions
となっているネスト内に書かれたアクションを記入していきます。
これで、記入されたアクションがbundle exec fastlane custom_lane
のコマンドを打つことで自動的に走るようになります。
この lane: 〜 end
を増やすことで、コマンドの種類を増やすことができます。
platform :ios do desc "Description of what the lane does" lane :custom_lane_1 do # add actions here end lane :custom_lane_2 do # add actions here end lane :custom_lane_3 do # add actions here end end
とすることで、
bundle exec fastlane custom_lane_1 bundle exec fastlane custom_lane_2 bundle exec fastlane custom_lane_3
のコマンドが認識されるようになります。
Xcodeのバージョンを指定する
前述した手順でxcode-install
というライブラリをインストールしています。
xcversion(version: "14.1")
このように記述することで、fastlaneにCommand Line Toolsを認識させることができます。
versionを指定することでどのXcodeでビルドを行うかを指定することが可能です。
アプリケーションのビルドやArchiveを一括対応するアクション gym
gym()
メソッドにいろいろなパラメータを与えることで、アプリケーションのビルドやArchiveをすべて自動で行ってくれる頼もしいアクションです。
ビルドの自動化という要件は、このアクションを使うことでほぼ完遂できると言っても過言ではないでしょう。
公式ページには使用できるパラメータ等が網羅されています。コンパクトにまとめたサンプルがこちらです。
gym( # ターゲットとなるworkspace # 省略するとカレントディレクトリの.xcodeprojファイルを参照する workspace: "MyApp.xcworkspace", # Build Configrationを指定 configuration: "Debug", # プロジェクトのSchemeを指定 scheme: "MyApp", # 出力先 dsymやxarchiveファイルもここにまとめて出力される output_directory: "path/to/dir", # 出力バイナリのファイル名 iOSの場合は.ipaを拡張子にする output_name: "my-app.ipa", # Organizerでdistributionする際に指定するメソッド # 省略するとapp-store(ストア向き)の出力方法に切り替わる export_method: "enterprise" )
これを先程の # add actions here: https://docs.fastlane.tools/actions
部分に挿入します。
platform :ios do desc "Description of what the lane does" lane :custom_lane do gym( workspace: "MyApp.xcworkspace", configuration: "Debug", scheme: "MyApp", output_directory: "deploy", # deployに変更 output_name: "my-app.ipa", export_method: "enterprise" ) end end
こうすることで、
- ワークスペースが
MyApp.xcworkspace
- Schemeが
MyApp
- Build Configurationが
Debug
- 出力方法は
enterprise
- 出力ディレクトリが
deploy
- 出力ファイル名が
my-app.ipa
のビルドが自動的に行われ、ファイルが出力されます。🎉
また、export_options
というキーを指定することで、ProvisioningProfileを指定することもできます。
export_options: { # Organizerでdistributionする際に指定するメソッド export_method: "enterprise", # 発行しているProvisioningProfile名 # Apple Developerで確認できる名前でOK provisioningProfiles: "ProvisioningProfile Name" }
TIPS
使用できるコマンドを確認する
laneに追加したコマンドの内容はfastlane/README.md
にまとまっています。
Fastfileを書き換えたのちbundle exec fastlane
関連のコマンドを打つことで、fastlane側でFastfileから自動で生成されます。
desc
のキーで指定されている文字列もここに表示されます。
また、 bundle exec fastlane
とコマンドで打つことで、コマンドを対話的に指定することも可能です。
その際にもコマンドの内容やdesc
で指定した文字列が表示されます。
複数環境を同時にビルドするには
laneの中で複数回gymをコールしてもいいのですが、Fastfileはrubyで解釈されるためrubyの記述に倣うことでサブルーチンなどを作成することもできます。
以下の例ではBuild Configuration
で環境が切り替わるようになっていることが前提条件になっています。
コメントアウト部分を切り替えて環境を切り替えるタイプの場合は対応していないので、適宜実装を組み替えてください。
ステージング/本番の2環境の各ビルドと2環境同時ビルドを実現するFastfileを書いて、この記事を締めとさせていただきます。
# 本番環境向けのipaを作成する bundle exec fastlane release_prod # ステージング環境向けのipaを作成する bundle exec fastlane release_stg # 本番/ステージング環境向けのipaを同時に作成する bundle exec fastlane release_multi
default_platform(:ios) xcversion(version: "14.1") # Xcodeバージョンは適宜書き換える WORKSPACE_NAME = "MyApp" SCHEME_NAME = "MyApp" # Build Configurationを記入する module Configuration PRODUCTION = "Release" STAGING = "Staging" end platform :ios do desc "release for Production" lane :release_prod do build(Configuration::PRODUCTION) end desc "release for Staging" lane :release_stg do build(Configuration::STAGING) end desc "release for Staging/Production" lane :release_multi do build(Configuration::PRODUCTION) build(Configuration::STAGING) end end def build(configuration = Configuration::PRODUCTION) # deploy/Release と deploy/Staging のディレクトリ配下に出力 output_directory = "deploy/#{configuration}/" # MyApp-Release と MyApp-Stagingというファイル名で出力 output_name = "#{SCHEME_NAME}-#{configuration}" gym( workspace: "#{WORKSPACE_NAME}.xcworkspace", configuration: configuration, scheme: "#{SCHEME_NAME}", output_directory: output_directory, output_name: "#{output_name}.ipa", export_method: "enterprise" ) end