• 162
    いいね
  • 2
    コメント
この記事は最終更新日から1年以上が経過しています。

この記事は、第2のドワンゴ Advent Calendar 2015の記事です。

はじめに

ここ最近のiOS界隈のトレンドの1つとしてfastlaneがあります。
fastlaneは様々なアクションを組み合わせて使用することで、テストやipaの作成などを簡潔に記述し実行することができます。

2015年10月25日のニコニコ超パーティにてリリースされた「ニコナレ」などドワンゴでリリースしていくiOSアプリにも今後積極的に使用していく予定です。

今回実際にプロジェクトに取り入れた例を踏まえつつ、これからfastlaneを初めて触る人がこの記事を見ればfastlaneの使い方、actionの定義の仕方などがわかるような記事を目指します。
また、多くの紹介記事ではAppStoreへのリリース自動化やデプロイ等に焦点を当てていますが、今回はテストでの利用やipaの作成など、デプロイフロー以外でもfastlaneを導入するための入門記事としてfastlaneの根本となる機能や作成方法をまとめます。

インストール

まずは、fastlaneのインストールを行います。

gem install fastlane

この場合、インストールを行ったfastlaneのバージョン等はそれぞれのPCの環境等に依存することとなります。
個人の開発の場合はそこまで問題はありませんが、チームでの開発やCIの環境を常に同じバージョンで動作させるためには、Bundlerを使用します。

Bundlerをインストールしていない場合、以下のコマンドを使用しインストールしてください

gem install bundler

プロジェクト直下にGemfileを用意し、以下を記述します。

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

そして、fastlaneをvendor/bundle配下にインストールします。

bundle install --path=vendor/bundle

fastlaneをvendor/bundle配下にインストールすることで、することで各々の開発環境に依存することなくfastlaneを使用することができます。

Bundlerを使用して、fastlaneのインストールを行った場合、これからのfastlaneコマンドの前にbundle execを使用して、bundlerでインストールしたfastlaneを使用することを明記してください

ちょっとしたはまり

fastlaneインストール後、コマンドを使用しようとした所以下のエラーに遭遇しました。
https://github.com/fastlane/fastlane/issues/729

-bash: fastlane: command not found

システム標準のRubyを使用している場合に起きることがあるバグだそうです。
対応策
すでに対応策は明示されており、~/.bashrc~/.zshrcに以下を追加した所動作しました。

export GEM_HOME=~/.gems
export PATH=$PATH:~/.gems/bin

こういったシステム依存の問題を少なくするためにも、Bundlerを使用してのインストールをおすすめします。

初期設定

fastlaneのセットアップは以下のコマンドで行います。

fastlane init

バージョン管理(git等)を使用しているかの確認。
していればy、していなければgitを使ってバージョン管理を行って下さい。

Do you have everything commited in version control? If not please do so now!
(y/n)

fastlaneを使用するアプリのBundle Identifierを入力してください。
ここで入力するBundle IdentifierはfastlaneからiTunesConnect等に接続するときに使用されますので、もしIdentifierを切り替えて使用している場合は本番用のものを入力してください。

App Identifier (com.krausefx.app):

Developerアカウントのメールアドレスを入力してください。
もし、Developer固有の機能(プロビジョンの更新等)を行わない場合は空でも問題ありません。
また、設定はAppfileに書き込まれていますのでいつでも変更可能です。

Your Apple ID (fastlane@krausefx.com):

AppStoreへのデプロイなどに使用するdeliverコマンドを使用する場合はyを入力してください。
今回の記事ではデプロイを行わないため使用しません。

Do you want to setup 'deliver', which is used to upload app screenshots, app
metadata and app updates to the App Store? This requires the app to be in the App
Store already. (y/n)

アプリのスクリーンショットを取ってくれるsnapshotを使用する場合はyを入力してください。
snapshotコマンドはUIAutomationを使用して実行時にスクリーンショットを自動で撮影してくれます。
deliver同様今回の記事では含みません。

Do you want to setup 'snapshot', which will help you to automatically take
screenshots of your iOS app in all languages/devices? (y/n)

sighコマンドは自動でDeveloperサイトからプロビジョンニングファイルのダウンロードや更新などを行うことができます。
yを入力すると自動でsighを使用したサンプルがFastfileに追加されます。

Do you want to use 'sigh', which will maintain and download the provisioning
profile for your app? (y/n)

プロジェクト内でカスタムスキームを使用している場合は入力してください。
もし、Xcodeデフォルトのままですとなにも入力する必要はありません。

Optional: The scheme name of your app (If you don't need one, just hit
Enter): 

この時点で./fastlaneというフォルダが生成され、

  • Appfile
  • Fastfile

といったファイルが自動生成されています。

基本的にfastlaneを使用して処理を行うにはこのFastfileに様々な処理を記述していきます。

Fastfileの中身を見てみると基本的に4つの処理があることがわかります。

before_all

ここでは、fastlaneの処理が開始される前に一度だけ実行されます。

before_all do
  # ENV["SLACK_URL"] = "https://hooks.slack.com/services/..."
  cocoapods
  # increment_build_number
  # xctool # run the tests of your app
end

ENV["SLACK_URL"]にslackのincoming hook urlを設定しておくことにより、各アクションに設定された自動投稿やslackへの通知が簡単に行うことができます。

cocoapodsではpod installコマンドが実行されます.

このように処理の前に必ず行っておきたい初期化処理などはこのbefore_allで行います。

lane

fastlaneでは1つの動作の流れをlaneと呼んでいます。

fastlaneを実行する際は引数としてlane_nameを渡します。

fastlane [lane_name]

このlane_nameに対応したlaneが実行されるようになります。

desc "Runs all the tests"
lane :test do
  # snapshot
end

例えば、上記のlane :testを実行するためには以下のコマンドにより行うことができます。

fastlane test

after_all

処理の終了時にはafter_allが呼び出されます。

after_all do |lane|
  # This block is called, only if the executed lane was successful 
  # slack(
  #   message: "Successfully deployed new App Update."
  # )
end

ここでは、実行終了時の通知などをslackに通知したりします。
|lane|の中には実行したlaneの種類が格納されていますので、testというlaneだけ終了通知を行いたい場合は以下のような判定を行うことができます。

after_all do |lane|
  if lane == :test
    slack(message: "finish lane")
  end
end

error

処理中になんらかの理由でエラーが発生し処理が中断された場合はerrorが呼び出されます。
一度errorのブロックに入るとafter_allは呼び出されずここで終了するので気をつけて下さい。

error do |lane, exception|
    # slack(
    #   message: exception.message,
    #   success: false
    # )
  end

このようにFastfile自体は4つの基本的には動作のみで処理を記述することができ、各laneを拡張していくという流れになります。

laneの定義

前述したとおりfastlaneではlaneという流れを使用して処理を行います。
ここでは、cocoapodsのインストールとcathageのインストールのみを行うlaneを定義してみたいと思います。

lane :setup_library do 
  cocoapods
  cathage
end

このようにlaneの中で予め定められたアクションを記述するだけで、CocoapodsとCarthageを使用したライブラリのセットアップを簡単に行えます。

このlaneを実行させるためには以下のコマンドで実行できます

fastlane setup_library

laneの順次実行

定義したlaneはlane内で別のlaneを呼ぶことも可能です。

lane :deploy do
  build(release: true)
  # deploy code
end

lane :deploygate do
  build
  # update deploygate
end

lane :build do |options| 
  scheme = (options[:release] ? "Release" : "Staging")
  ipa(scheme: scheme)
end

ここでは、deploydeploygateのlaneでどちらもipaの出力を行いたい場合はbuildというlaneを別で定義して各lane内で呼び出しています。

laneの呼び出しは引数も取ることができ、deployのlaneではreleaseフラグを引数としてわたしています。

プロジェクトのビルドとipaの出力

プロジェクトのビルドとipaの出力は別々のアクションとして定義されていますが、gymというビルドとipaの出力を比較的に簡単に行えるアクションが用意されています。
gymを使用することでビルドとipaの出力のコードは以下の様な形となります。

gym(
  workspace: "MyApp.xcworkspace",
  configuration: "Debug",
  scheme: "MyApp",
  silent: true,
  clean: true,
  output_name: "my-app.ipa",   
)

ここではプロジェクト設定された値を使用してAppStore用のipadをmy-app.ipaという形でアーカイブしています。

テストの実行

fastlaneでのテストを実行はscanxctestxctool等複数のツールを使用することができます。
この中でも比較的新しく簡単にテストを行うことができるscanコマンドをおすすめします。

scanは以下の記述で使用することができます。

scan(scheme: "ApplicationSchemeName")

Slackへの通知を設定した場合は、テストに成功すると以下のような通知を自動で送信されます。
スクリーンショット_2015-12-10_05_27_16.png

失敗した場合は以下のような通知が送信されます。
スクリーンショット_2015-12-10_05_30_45.png

また、scan内部でxcprettyと呼ばれるログ整形ツールが使用されており、テストの結果はJUnitのレポート形式のhtmlファイルが./fastlane/test_output/report.htmlに出力されています。
出力される場所は別途指定可能です。

スクリーンショット_2015-12-10_05_34_13.png

scanコマンドは様々な引数を取ることが可能でありscan --helpコマンドで使用できる引数を見ることができます。
ここでは主に使用するであろう代表的なコマンドのみ抜粋します。

-w, --workspace 
-p, --project 
-a, --device 
-s, --scheme 
-c, --clean     
-q, --configuration  
--skip_slack 
--slack_only_on_failure  

上記のコマンドを組み合わせることにより、scan実行時の条件等を変更することができます。
例えば、
xcworkspaceを使用しているプロジェクト
・テスト前にクリーンを行う
・slackへの通知はテストに失敗した時のみ行う
ような設定を行いたい場合は

scan(
  workspace: "Application.xcworkspace",
  clean: true
  slack_only_on_failure: true
)

のような形となります。

レポートをSlackに通知

fastlane1.45.0より出力されたレポートのパスを取得することができます。
この機能により、簡単にslack等にテスト結果を通知することが可能です。

slack(
    message: "Tests results: " + ENV['FL_REPORT_PATH'] 
)

アクションを探す

fastlaneのアクションには様々な種類があり、日々開発者によってそのアクションの数は増大しています。
まず、行いたい動作がある場合は、action一覧がまとまっている
https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Actions.md
このページを参照してください。

fastlaneで使用できるアクションは基本的にすべてここにまとまっています。

アクションに使用できる引数を確認する

主要アクション

以下のようなfastlaneが公式に開発を行っている機能に関しては基本的には全て単体のコマンドとしてコマンドライン上で使用することができます。

  • fastlane
  • deliver
  • snapshot
  • scan
  • gym
  • etc.......

このコマンドに関しては引数の実装を確認するためにはscanの時と同様にコマンドライン上で--helpで確認するのが一番はやいと思います。

例えば、gymのコマンドはAction一覧で記述されている引数よりも多くの引数を指定することができます。

サンプルだけの引数を使用しているとipaのアーカイブの方法はAppStoreへのリリースのためのアーカイブとなってしまいます。

gym(
  workspace: "MyApp.xcworkspace",
  configuration: "Debug",
  scheme: "MyApp",
  silent: true,
  clean: true,
  output_name: "my-app.ipa",   
)

Deploygateなどに配布するためのAdHoc配信用のアーカイブをするためには

gym(
  workspace: "MyApp.xcworkspace",
  configuration: "Debug",
  scheme: "MyApp",
  silent: true,
  clean: true,
  output_name: "my-app.ipa",   
  export_method: "ad-hoc"
)

のようにexport_methodad-hocにする必要があります。

コマンドを実行し、何かエラーに遭遇することがあったらまず--helpを使用し、使用できる引数がないか確認してみてください。

その他カスタムアクション

fastlaneのアクションの実装ファイルは
https://github.com/fastlane/fastlane/tree/master/fastlane/lib/fastlane/actions
全てここに定義されています。

アクションの引数を確認する場合は各々のアクション実装ファイルを見ることで確認できます。
ここでは、Carthageを例に見ていきます。
https://github.com/fastlane/fastlane/blob/master/fastlane/lib/fastlane/actions/carthage.rb

cmd = ["carthage bootstrap"]

cmd << "--use-ssh" if params[:use_ssh]
cmd << "--use-submodules" if params[:use_submodules]
cmd << "--no-use-binaries" if params[:use_binaries] == false
cmd << "--no-build" if params[:no_build] == true
cmd << "--verbose" if params[:verbose] == true
cmd << "--platform #{params[:platform]}" if params[:platform]

Carthageの実装ファイルの7-12行目にこのようにパラメータからコマンドを作成している行があります。
params[:no_build]この:no_build

carthage(
  no_build: true
)

fastlane上の引数のno_buildに対応しています。

そのため、fastlane上でCarthageのビルドをiOSのみにする場合は

carthage(
  platform: "iOS"
)

のような形にすることでiOSのみのビルドでCarthageを動作させることができます。

このようにfastlaneはアクション毎にある程度定められたフォーマットで動作が定義されているため、比較的簡単に動作を確認したり、引数のチェックを行うことができます。

カスタムパラメータ

fastlane実行にカスタムパラメータを渡すことができます。
現在、自分はPullReuqestBuilderを使用してJenkinsでfastlaneを動作させテストを行わせています。
その際、テストの終了時に対象のプルリクエストのURLをSlackに通知するという処理を行っています。

PullRequestBuilderの説明は省略させてもらいますが、Jenkins上で${ghprbPullLink}でプルリクエストのリンクを取得することができます。

fastlane実行時にkey:valueのような形でパラメータを指定することができます。

fastlane jenkins prurl:${ghprbPullLink} key:value

渡されたたパラメータは|options|の中に格納されoptions[:key]で使用することができます。

lane :jenkins do |options|
  # テストの実行
  # scan

  # プルリクエストリンクをSlackに通知
  slack(
    message: "Succeed all tests: " + options[:prurl]
  )
end

Jenkins

今回初めにfastlaneを導入しようとしたきっかけはJenkins上でビルドやテストを走らせる際の設定がかなり属人化してしまい、管理者以外がいじりにくいという問題を解消させるために導入しました。
ビルドやテストなどの実行を各pluginやシェル上で行わずfastlaneに全て移行することで、プロジェクトが増えてもfastlaneを設定するだけでよく、JenkinsはあくまでもGithubからのプルリクエストの受け口やfastlaneの実行だけの役割を持つだけでよくなります。
また、開発機からのデプロイフローも自動化することができます。

このように、AppStoreへのリリース以外にもfastlaneは存分に使用できますので、fastlaneをまだ使用したことがない方はぜひこの機会にdeploygateやcrashlyticsへのデプロイ、テスト実行だけでもfastlaneに移行してみてください!

Jenkins実行時のはまり

  • 設定にかなり依存しますが、Jenkins上のコマンドラインから実行する際、LANGの設定でエラーが出る場合はあります。
export LANG=en_US.UTF-8
export LANGUAGE=en_US.UTF-8
export LC_ALL=en_US.UTF-8

その場合はfastlaneの実行前にexportを行ってやってやるか、Jenkinsの環境設定よりLANGを設定してください。

まとめ

ここまで、基礎の基礎となる紹介をしてあまり実践的な内容に触れることはできませんでしたが、一度fastlaneの基礎を学習することにより様々な拡張を行うことができるかと思います。
時間があれば、ここからもう少し実践的にAppStoreへのデプロイやプロビジョニングプロファイルの取り扱い等の内容を記事にできればと思っています。

iOSアプリ開発を行ううえで便利ツール等は年々増加しています。
適度にツールを導入し、快適なアプリ開発生活を送りましょう٩(๑❛ᴗ❛๑)۶