Travis CIでつくるiOSのCI環境（運用のコツ編）

この記事は[WHITEPLUS Advent Calendar](http://qiita.com/advent-calendar/2016/whiteplus "")  2016 23日目になります。

株式会社ホワイトプラス、エンジニアの @akaimo です。
ホワイトプラスでは主にリネットのiOSアプリを担当しています。

# はじめに
[WHITEPLUS Advent Calendar](http://qiita.com/advent-calendar/2016/whiteplus "")の中で以下の記事のように、iOS開発用のTravis CIを構築してきました。

- [Travis CIでつくるiOSのCI環境（準備編）](http://qiita.com/akaimo/items/44c873808b1ad74ee494)
- [Travis CIでつくるiOSのCI環境（テスト・アップロード編）](http://qiita.com/akaimo/items/9612041c50b1898dedc0)

今回は最後の仕上げとして、運用する上でのコツを書いていきたいと思います。

# 実行時間の短縮
Travis CIの環境を構築したら、一番始めに課題となって立ちふさがるのは、実行時間の問題だと思います。
時間がかかるポイントとしては、

- 環境構築（ビルドまでの準備）
- ビルド
- アーカイブ
- アップロード

があります。
アップロードはこちらではどうすることもできないので除外し、アーカイブはビルド時間に依存するので、
今回は環境構築とビルドにかかる時間を短縮していきます。

## 環境構築にかかる時間の短縮
iOSの環境構築で時間がかかるのは外部ライブラリ、
つまりCocoaPodsとCarthageのセットアップです。

### 最短の方法
一番速くする方法は、ライブラリの管理をCarthageにして、ビルド済みのバイナリをリポジトリに入れてしまうことです。

クローンするだけで環境の構築が完了しますが、ライブラリのバージョンアップ以外にも、
Swiftが安定していないこともあり、Xcodeのバージョンが変わるたびにライブラリを更新しなければならず、
リポジトリの肥大化が予想されるため、あまりオススメしません。

開発の体制によっては、リポジトリに含めたほうが良い場合もあると思うので、適切な判断をお願いします。

### Travis CIのキャッシュを使用する
リポジトリに含めないとなると、Travis CIのキャッシュを利用する方法が効率的です。
`.travis.yml`に以下のように記述すると、`Pods`と`Carthage`ディレクトリをキャッシュしてくれます。

```
cache:
  directories:
  - Pods
  - Carthage
```

キャッシュを取得した後に、

```
$ pod install
```

を実行して、更新があれば新しいバージョンのライブラリを入れ、
無ければそのまま`.xcworkspace`を生成して完了です。

Carthageは、変更があったものを検知して、それだけを自動的にビルドする方法がないので、
変更があったときだけ、ビルドをするようなスクリプトを書いています。
以下の簡単なスクリプトで検知・再ビルドを行っています。

```bash:
#!/bin/bash

if ! diff Cartfile.resolved Carthage/Cartfile.resolved &>/dev/null; then
  echo '--- Carthage checkout ---'
  carthage checkout --no-use-binaries
  echo '--- carthage build ---'
  carthage build --platform ios
  echo 'copy Cartfile.resolved'
  cp Cartfile.resolved Carthage
  echo '--- carthage install success ---'
fi
```

簡単に解説すると、Carthageの依存管理に使用している、`Cartfile.resolved`をキャッシュする`Carhage`ディレクトリに含め、
クローンしてきたほうの`Cartfile.resolved`と比較して、異なっていればビルドをするというものです。
もう少しきちんと比較をすれば、変更があったときに、変更があったライブラリのみをビルドし直すこともできると思いますが、そんなに頻繁に更新はしないので、全て更新しています。

変更がなければ、`carthage`コマンドは一回も使用せずに、プロジェクトのビルドに行けます。

キャッシュが機能している状態ならば、リポジトリに全て含める方法と同等のスピードで実行できるので、オススメです。

## ビルド時間の短縮
CocoaPodsはソースからビルドするためクローン直後などのキャッシュが効いていない状況だと、とても時間がかかってしまいます。
そのため、まずはCocoaPodsからCarthageに移行します。
これだけでも十分に時間の短縮が体感できると思います。

さらなる短縮をするには、Swiftで書かれているコードを改善していく必要があるので、個人的にはあまりオススメしません。
1秒でも短縮したい場合は、以下の記事を参照してください。

- [Xcode8でビルドが遅すぎるのを解消した件（Swift パフォーマンス改善）](http://qiita.com/you_matz/items/e95f30023eccc8d96357)
- [Swiftのビルド時間を減らしてCI環境でのデプロイも早くしたお話](http://techblog.timers-inc.com/entry/2016/07/06/183632)

型推論や`??`, `$0`, 三項演算子などがビルドに時間がかかっているようですが、せっかくSwiftで書いているのに、ビルド時間を減らすために使わないのは、いろいろと残念です。

# 社内配布版アプリの管理
ホワイトプラスではHockeyAppを使用して社内配布を行っていますが、社内配布版は1日に数回は新しいものになります。

適切にバージョンの管理を行わないと、テストしてもらった人と適切なコミュニケーションがとれなくなってしまいます。どのバージョンにどのバグがあり、いつ直ったのかなど明示的に示せたほうが、気持ちいいコミュニケーションがとれます。

しかし、毎回手動でバージョンを管理するのは手間です。
そこで、アプリのビルド番号をTravis CIのビルド番号と同じにするように、CI上で書き換えています。

このようにすると、アプリのビルド番号からTravis CIを経由して、gitのコミットまで追うことができます。

やることとしては、以下のコマンドをTravis CIで実行するだけです。

```
agvtool new-version -all $TRAVIS_BUILD_NUMBER
```

リリース版のビルドでも実行しているので、iTunes Connectにアップロードするときにビルド番号で怒られる心配もありません。
アプリのバージョンも`agvtool`で書き換えられますが、規則性がないので手動で書き換えています。

Ubuntuのようなバージョン指定の方法をとれば全部自動化できそうです。

# Carthageのフルビルド
時間短縮のところでCarthageのビルドコマンドを

```
carthage bootstrap --platform ios
```

ではなく、

```
carthage checkout --no-use-binaries
carthage build --platform ios
```

のように書きました。

これは、`carthage bootstrap`だと、ビルド済みのバイナリをダウンロードしてしまう可能性があり、
ビルドしたSwiftのバージョンと、開発に使用しているバージョンが異なっているとプロジェクトのビルドに失敗してしまうからです。
そのため、一度クローンしてチェックアウトしたソースコードからビルドするようにしています。

今後、Swiftが安定してきたらこのようなことはする必要がなくなるので、
できるだけ早く安定してほしいものです。

# Sierraで実行するために
[Travis CIでつくるiOSのCI環境（準備編）](http://qiita.com/akaimo/items/44c873808b1ad74ee494)にも書きましたが、Sierraに対応するのに苦労したため、こちらにも書いておきます。

Sierraでキーチェーンに仕様変更が入り、キーチェーンを作成したままだとパーミッションの確認がでてハングしてしまいます。
そのため、キーチェーンを作成後に許可する必要があります。

```
security set-key-partition-list -S apple-tool:,apple: -s -k <password> <keychain name>
```


# 終わりに
全3回に渡ってTravis CIをiOSの開発で使用していく方法を書きました。
CI環境の構築は、情報が少ないだけでなく移り変わりも早く、
その上iOSの場合はappleの変更にもついて行かなければならないので、苦労が多いと思います。
そんな苦労を少しでも減らすことができたらうれしいです。

明日は弊社エンジニア @kai-zoa の「2014〜2016 infrastructure as a code 流行振り返り」です。

#ホワイトプラスではエンジニアを募集しています
ホワイトプラスでは、[新しい技術にどんどん挑戦したい！という技術で事業に貢献したいエンジニアを募集](https://www.wantedly.com/projects/69257)しております。!