アプリの各種作業自動化ツール、fastlaneの導入


iOS (Android) アプリのテストやリリースフローの自動化を行うツール、[fastlane](https://github.com/fastlane/fastlane)を導入した時のメモ。

## 試した環境
- Xcode 7.3.1
- fastlane 1.95.0

※少し前に試したので、最新版のfastlaneではないです

## fastlane追加

```ruby:Gemfile
gem  'fastlane'
```

```
> bundle
```

## 初期設定
```
> fastlane init
```

対話的にいろいろ聞かれるので、答えていく。(Apple IDなど）
これで初期設定完了。`./fastlane`以下にファイルが作成される。

## laneの作成
自動化したいタスクを、RubyのDSL形式で作成していく。fastlaneではこのタスクのことをlane（レーン）と呼ぶらしい。タスクは、`./fastlane/Fastfile`に記述していく。

今回は、

- テストの実行
- Deploygateへのアップロード
- TestFlightへのアップロード

のタスクをとりあえず作成してみた。

### テストの実行

```rb:./fastlane/Fastfile
platform :ios do
  before_all do
    cocoapods
  end

  desc "Runs all the tests"
  lane :test do
    scan(
      workspace: <WORKSPACE NAME>,
      scheme: <SCHEME NAME>,
      configuration: <BUILD CONFIGURATION NAME>,
      device: 'iPhone 6 9.3'
    )
  end
end
```

`before_all`ブロックで、テスト実行前に`pod install`の実行。この処理は全てのタスクの実行前に走る。

`device`に何も指定しないとエラーが出たので、デバイス名とiOSのバージョンの両方を指定することで動いた。

```
fastlane ios test --verbose
```

で実行。`--verbose`オプションで、詳細なログが見れる。

### deploygateへのアップロード
```rb:./fastlane/Fastfile
platform :ios do
  desc "Submit a new AdHoc Build to Deploygate"
  lane :deploygate do
    increment_build_number
    gym(
      workspace: <WORKSPACE NAME>,
      scheme: <SCHEME NAME>,
      configuration: <BUILD CONFIGURATION NAME>,
      clean: true,
      use_legacy_build_api: true
    )
    deploygate(
      api_token: <DEPLOYGATE API TOKEN>,
      user: <DEPLOYGATE USER NAME>,
      message: last_git_commit[:message]
    )
  end
end
```

`gym`コマンドでビルド作成 & パッケージング。ビルドを作成するときに、`use_legacy_build_api: true`にしないとエラーになった。
このようなオプションが用意されている理由は、ヘルプによると以下。

- https://openradar.appspot.com/radar?id=4952000420642816

`increment_build_number`は、laneの実行時に自動でビルド番号をインクリメントしてくれるオプション。少し事前の設定が必要で、以下を参考に変更。

- [Technical Q&A QA1827: Automating Version and Build Numbers Using agvtool](https://developer.apple.com/library/ios/qa/qa1827/_index.html)

そして、`deploygate`コマンドでDeploygateにアップロード。

```
fastlane ios deploygate --verbose
```

のコマンドを実行すると、Deploygateに最新版のビルドがあがる。

### TestFlightへのアップロード
```rb:./fastlane/Fastfile
ENV['DELIVER_ITMSTRANSPORTER_ADDITIONAL_UPLOAD_PARAMETERS'] = '-t DAV'

platform :ios do
  desc "Submit a new Beta Build to Apple TestFlight"
  desc "This will also make sure the profile is up to date"
  lane :beta do
    increment_build_number
    gym(
      workspace: <WORKSPACE NAME>,
      scheme: <SCHEME NAME>,
      clean: true,
      use_legacy_build_api: true
    )
    pilot(
      skip_submission: true,
      team_id: <TEAM ID>,
      team_name: "Atrae Inc.",
      itc_provider: <ITC PROVIDER>,
      skip_waiting_for_build_processing: true
    )
  end
```

ここの設定にけっこう苦労した。

`pilot`コマンドでTestFlightにアップロードが可能になる。
※アップロードだけでなく、配布やテスターの追加などもできる、[こちら](https://github.com/fastlane/fastlane/tree/master/pilot)参照

複数のteamに所属してると、`pilot`実行時に`team_id`, `team_name`をセットしておかないと、コマンドの実行中にプロンプトで聞かれてしまい自動化にならない。初めから値を渡しておく。

また、`itc_provider`というオプションも設定しないといけないのだが、これの値がなかなかわからず苦労した。`iTMSTransporter`コマンドで取得可能。

```
> /Applications/Xcode.app/Contents/Applications/Application\ Loader.app/Contents/itms/bin/iTMSTransporter -m provider -account_type itunes_connect -p <APP SPECIFIED PASSWORD> -u <APPLE USER ID>
```

```
Provider listing:
   - Long Name -  - Short Name -
1  Atrae Inc.     XXXXXXXX
2  YUSUKE AONO    XXXXXXXXXXXXXXX
```

こういうのが返ってくる。`itc_provider`には、↑のShort Nameを指定すれば良い。

最後にもう1個ハマった。もう間違ってるとこなさそうなのに、iTunes Connectへのアップロードでエラーが出る。

- https://github.com/fastlane/fastlane/tree/master/deliver#firewall-issues

ここを見て、もしやと思って試したらアップロード成功。ファイアウォールの問題だったようだ。

というわけで、`Fastfile`の冒頭で、`ENV['DELIVER_ITMSTRANSPORTER_ADDITIONAL_UPLOAD_PARAMETERS'] = '-t DAV'`を指定している。

```
fastlane ios beta --verbose
```

で実行。

## おわり
fastlaneで簡単なタスクを自動化してみた。地味に面倒な作業がコマンド一発で実行できるようになり楽。

もう少し設定が必要だが、CI as a Serviceで実行させることもできる（いまはMacのローカル環境で実行）。さらに、TestFlightへのアップロードにとどまらず、リリース作業も自動化出来そうなので活用していきたい。