こんにちは、GANMA!の開発を行っているtakezawa(@to4iki)です。
今回は、fastlaneの紹介と導入方法・簡易的な使用例を紹介します。
また、ブログ内で使用しているサンプルコードは公開しているので良かったら参考にしてみて下さい。
Sandbox-iOS/FastlaneBox
fastlaneとは
fastlane/fastlane: The easiest way to automate building and releasing your iOS and Android apps
fastlaneは主にiOS/Androidアプリのビルド、テスト、デプロイを行うためのRuby製のタスクランナーであり、
アプリ開発の様々なフローにおける自動化をサポートしてくれます。
Twitter傘下のFabricに取り込まれており、また幾つかのCIサービスにも標準搭載されるなど今とても勢いのあるツールです。
action, lane
fastlaneではアクションと呼ばれる機能(タスクコマンド)を組み合わせたレーンにおいて自動化を実現します。
主なアクションをfastlane/READMEから抜粋しました。
iOS
アクション | 説明 |
---|---|
deliver |
スクリーンショット、メタデータ、アプリをApp Storeにアップロードする |
snapshot |
全デバイスを対象にアプリのスクリーンショット撮影を自動化する |
frameit |
スクリーンショットを各デバイス画像にはめ込む |
pem |
プッシュ通知用のプロファイルを自動生成したり更新する |
sigh |
プロビジョニングプロファイルの生成、更新、修復する |
produce |
新しいアプリをiTunes ConnectやDev Portalで作成する |
cert |
証明書の作成と管理をする |
spaceship |
Apple Dev CenterやiTunes Connectにアクセスする |
pilot |
TestFlightのテスターを管理する |
boarding |
TestFlightのbetaテスターを招待する |
gym |
アプリをビルドする |
match |
Gitを使って証明書とプロファイルを管理する |
scan |
iOSアプリ、Macアプリのテストを実行する |
Android
アクション | 説明 |
---|---|
supply |
アプリ、メタデータをGoogle Playにアップロードする |
screengrab |
全デバイスを対象にアプリのスクリーンショット撮影を自動化する |
この他、公式で提供しているアクションはActions - fastlane docsにて確認できます。
など痒いところに手が届くようなアクションも用意されているので、組み合わせの幅も広がりますね。
導入
faslaneをinstallしてみましょう(ここから先はiOSプロジェクトを例に説明します)。
versionを固定するためにBundlerを使用し、Gemfileに依存を定義。
source 'https://rubygems.org' gem 'fastlane'
install
$ bundle install --path=vendor/bundle
$ bundle exec fastlane -v fastlane 1.102.0
セットアップ
プロジェクトのルートでinitコマンドを実行し、雛形の設定ファイルを作成します。
$ bundle exec fastlane init
ターミナル上でApp Identifier, iTunes Connectへのログイン情報など幾つかの質問を答えます(Androidプロジェクトの場合も同様にGooglePlayの情報を入力します)。
完了すると、
./fastlane/Fastfile
: レーン定義を記述するための雛形ファイル./fastlane/Appfile
: Developerに関する情報が記載されているファイル
が作成されます。
簡易的なレーン作成
雛形で生成されたFastfileをベースに少しだけいじってみます(RubyのDSLを書いていきます)。
因みに$ bundle exec fastlane actions
でアクション一覧$ bundle exec fastlane list
で現在のレーンの一覧が見れます。
今回はテストを実行 > Slackに成功/失敗を通知するだけのシンプルなフローを定義してみます。
Fastfile
require "yaml" fastlane_version "1.102.0" default_platform :ios CONF = YAML.load_file('conf.yml') platform :ios do before_all do ENV["SLACK_URL"] = CONF["slack"]["webhookurl"] end desc "Runs all the unit and ui tests" lane :test do # cocoapods # cathage scan( scheme: "FastlaneBox", clean: true ) end after_all do |lane| slack(message: "Successfully") end error do |lane, exception| slack( message: exception.message, success: false ) end end
conf.yaml
slack: webhookurl: "https://hooks.slack.com/services/#{your_webhook_url_path}"
Slackのwebhookurlはconf.yamlファイルを作成しそちらに定義。
また、実運用の際はローカルで実行した場合にもSlackに通知が飛ぶのはやり過ぎなので、CI環境下で実行した場合にのみ結果を通知するよう設定した方が良いでしょう。
# https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Actions.md#is_ci if is_ci? scan(skip_slack: false) else scan end
では、実行してみます。
$ bundle exec fastlane test
成功/失敗の件数が整形された状態で表示されました。
(テスト結果表示用JUnitのレポート形式のhtmlファイルが./fastlane/test_output/report.html
に出力されています)
Slackにも良い感じに結果が表示されましたね!
Travis CIとの連携
Travis CI上でfastlene経由のテスト実行を試してみます。
まず、Travisから流すレーンをシェルスクリプトとして定義(実行scriptは肥大化する恐れがあるので、事前に別ファイル等に分割しておくのをお勧めします)
fastlane/travis.sh
#!/bin/sh fastlane test
実行権限を付与
$ chmod a+x fastlane/travis.sh
.travis.yml に諸々定義(fastlaneは最新版にupdateしておく)
language: objective-c osx_image: xcode7.3 env: global: - LC_CTYPE=en_US.UTF-8 install: - gem update fastlane --no-ri --no-rdoc --no-document script: - ./fastlane/travis.sh
最後に、TravisからBuildする必要があるのでターゲットのスキームは公開しておいてください(Xcode > Manage Schemes… > Sharedチェックボックスをオン)。
これで、$ git push
のタイミングでfastlane経由のテストが走るようになりました。
他にも、xcov用のアクションを組み合わせればカバレッジの計測ができるので良かったら試してみてください。
カスタムアクション
用意されたアクションの呼び出しだけではなく、独自のアクション定義も可能です。
次のコマンドを実行しカスタムアクションの雛形を生成します。
$ bundle exec fatlane new_action
現在時刻を標準出力するだけのsampleアクションを書いてみましょう。
actions/sample.rb
module Fastlane module Actions class SampleAction < Action def self.run(params) puts Time.now end # only iOS def self.is_supported?(platform) platform == :ios end ... end end
./fastlane/actions/
配下のファイルはfastlane実行時にロードされ、既存のアクションと同様に使用出来ます。
desc 'Custom action' lane :my_action do sample end
より具体的な実装例はfirefox-ios-build-tools/fastlane/actionsなどを参考にして見て下さい。
プロジェクト固有の設定/処理などはカスタムアクションを作成し、レーンで使い回すといった使い方が出来そうですね。
プラグイン
fastlaneにはプラグイン機構が存在します。
試しに、Xcodeのグループに合わせてファイル/ディレクトリ構造を同期してくれるsynxをアクションとして提供しているプラグインをinstallしてみます。
$ bundle exec fastlane add_plugin fastlane-plugin-synx
実行すると、gemfileライクな依存解決用のファイルを自動生成してくれます。
Pluginfile
# Autogenerated by fastlane # # Ensure this file is checked in to source control! gem 'fastlane-plugin-synx'
Gemfileにもブリッジが定義されるので、$ bundle install
で自動的にプラグインもinstallされます。
plugins_path = File.join(File.dirname(__FILE__), 'fastlane', 'Pluginfile') eval(File.read(plugins_path), binding) if File.exist?(plugins_path)
これで、レーンからsynxアクションを呼び出すことが出来るようになりました。
desc "Runs synx to folderize the Xcode project" lane :sync do synx end
snapshot
次にfastlaneが提供するスクリーンショット作成用のアクションを試してみます。
fastlane/snapshot
XCUITextを利用してスクリーンショットを撮るので、プロジェクトにUITests用のビルドターゲットを新設しておきましょう。
準備
下記コマンドで、どのデバイス/言語をターゲットにしたスナップショットを撮影するか指定するための設定ファイル(Snapfile)の雛形を作成します。
$ bundle exec snapshot init
devicesに設定する名前は$ xcrun simctl list
を実行して確認が出来ます。
検証用にiPhone6sの日本語環境下のみをターゲットにします。
Snapfile
devices([ "iPhone 6s" ]) languages([ "ja-JP" ])
自動生成されたSnapshotHelper.swiftはUITestsのターゲットに含めます。
あとは、UITests中の任意のタイミングでsetupSnapshot
関数を呼び出しましょう。
override func setUp() { super.setUp() continueAfterFailure = false let app = XCUIApplication() setupSnapshot(app) // 起動時のスクリーンショットを撮影する app.launch() }
実行
runコマンドでスクリーンショットの撮影を行います
$ bundle exec snapshot run
実行後はscreenshots/screenshots.htmlがブラウザで開かれ、スクリーンショットを一覧出来ます。
またレーンとして定義も可能です。
desc "Creates new screenshots and uploads them to iTunes Connect" lane :screens do snapshot end
より実践的な使い方
- iTunes Connectへアップロードするバイナリ生成のためのビルドやパッケージ化
- プロビジョニングプロファイルの管理
- テスト用のAdHoc配信(deploygateやcrashlyticsなど)
- リリース前の外部テスト配信 in TestFlight
- iTunes Connectのメタデータ更新
などリリースフローの自動化を始めとする実践的なfastlaneの使い方は試せていませんので、参考資料を貼らせて頂きます。
iOSアプリ開発に必要な証明書とプロファイルをGitHubのリポジトリで一括管理する
iOSアプリ申請を驚くほど簡単に!fastlaneではじめる自動化入門
まとめ
fastlaneの紹介と簡単な使い方を紹介しました。
リリースフローの自動化もそうですが、オレオレシェルスクリプトによる車輪の再開発を防げる、属人化しがちなビルドやテストなどの実行をfastlane内だけで完結することで保守性が高くなります。
皆さんもfastlaneを使って快適で安全なリリースフローを運用しましょう!