Travis CIでつくるiOSのCI環境（テスト・アップロード編）

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

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

# はじめに
「[Travis CIでつくるiOSのCI環境（準備編）](http://qiita.com/akaimo/items/44c873808b1ad74ee494)」の続きです。

前の記事ではTravis CIでiOSアプリのテスト・アップロードをするための環境構築をしました。
今回は実際にテストを実行して、iTunes ConnectとHockeyAppへのアップロードを行います。

# テストの実行
テストは`xcodebuild test`というコマンドで実行します。
プロジェクトの環境によって、適切なオプションを指定しないと動作しないので、オプションの解説から入ります。

## xcodebuild testのオプション
#### -project \<projectname\>
- `xcodebuild test`を実行するディレクトリに複数のプロジェクトファイルが存在する場合は、
どのプロジェクトに対して実行するか指定しなければいけません。

#### -target \<targetname\>
 - 特定のtargetに対して実行する場合は指定する必要があります。

#### -workspace \<workspacename\>
- CocoaPodsなどでworkspaceを使っている場合は指定する必要があります。
- `sample.xcworkspace`のようにドット以下も必要です。

#### -scheme \<schemename\>
- workspaceを使用している場合は必須項目です。

#### -destination \<destinationspecifier\>
- `platform=iOS Simulator,OS=10.1,name=iPhone 7`のようにテストする端末とOSを指定します。
- `-destination destinationspecifier`は複数付けることができるので、一回のコマンドで複数の環境に対してテストを行うことができます。
- シミュレーター名、OS名は`xcrun simctl list`で確認できます。
- Travis CIで実行することができるシミュレーターは[こちら](https://docs.travis-ci.com/user/osx-ci-environment/#OS-X-Version)でMac OSのバージョンごとに確認できます。

#### -configuration \<configurationname\>
- 実行するtargetのconfigurationを指定します。


テストで主に使用するオプションは以上になりますが、その他のオプションや詳細については[ドキュメント](https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man1/xcodebuild.1.html)を確認してください。

## 実行例
```bash
xcodebuild test -workspace Sample.xcworkspace \
  -scheme Sample \
  -destination 'platform=iOS Simulator,OS=10.1,name=iPhone 7' \
  -configuration Debug \
  | xcpretty -c
```
Travis CIでは実行ログの容量に制限があり、xcodebuildをそのまま実行するとたくさんのログが出力されてしまい、エラーになってしまいます。
そのため、`xcpretty`を使用してログを加工しています。

# ipaの作成
ipaを作成するためには、一度アーカイブを書き出す必要があります。
その後アーカイブをipaに変換します。

## アーカイブの書き出し
アーカイブは`xcodebuild archive`コマンドで書き出すことができます。
これもテストと同様に、プロジェクトごとに適切なオプションをつける必要があります。

### xcodebuild archiveのオプション
testで紹介したオプションは省略します。

#### -archivePath \<xcarchivepath\>
- アーカイブ(`.xcarchive`)の出力先のpathを指定します

#### CODE_SIGN_IDENTITY
- アーカイブに使用する証明書を指定するときにつかいます
- リリース版とAdhoc版で証明書が異なってくるので、複数の対象に対してアーカイブする場合は指定する必要があります

#### PROVISIONING_PROFILE
- provisioning profileのidを指定します

### 実行例
```bash
PROVISIONING="xxxx-xx-xx-xx-xxxx"
IDENTITY="iPhone Distribution: Sample (xxxxxx)"

xcodebuild archive \
  -workspace Sample.xcworkspace \
  -scheme Sample \
  -configuration Release \
  CODE_SIGN_IDENTITY="${IDENTITY}" \
  PROVISIONING_PROFILE="${PROVISIONING}" \
  -archivePath ./build/Sample.xcarchive \
  | xcpretty -c
```

## xcarchiveからipaの作成
先ほど作成した`xcarchive`から`ipa`を作成していきます。
`ipa`作成に関する設定を`plist`で指定する必要があり、以下の記事で詳しく書かれているのでプロジェクトにあった内容で作成します。
[xcodebuildでipa作成 -exportOptionsPlist対応版](http://qiita.com/roworks/items/7ef12acabf9679561d84)

そして、`xcodebuild -exportArchive`コマンドで`ipa`を作成します。

### 実行例
```bash
xcodebuild -exportArchive \
  -archivePath ./build/Sample.xcarchive \
  -exportPath ./build \
  -exportOptionsPlist exportOptions.plist \
  | xcpretty -c
```

# iTunes Connectへのアップロード
いよいよ`ipa`をアップロードしていきます。
まずはリリース版のアップロード先であるiTunes Connectにアップロードします。

## バリデーション
iTunes Connectにアップロードするために`altool`というコマンドをたたきます。
`altool`には、バリデーション用のコマンドがあり、プライベートAPIなどを使用していないかのチェックをすることができます。
少し時間がかかってしまいますが、せっかくなのでチェックします。

```bash
'/Applications/Xcode.app/Contents/Applications/Application Loader.app/Contents/Frameworks/ITunesSoftwareService.framework/Support/altool' \
  --validate-app \
  -f build/Sample.ipa  \
  -u $ITUNES_NAME \
  -p $ITUNES_PASS
```

## アップロード
バリデーションで問題がなければアップロードをしていきます。
アップロードにはバリデーション以上に時間がかかるので注意が必要です。

```bash
'/Applications/Xcode.app/Contents/Applications/Application Loader.app/Contents/Frameworks/ITunesSoftwareService.framework/Support/altool' \
  --upload-app \
  -f build/Sample.ipa \
  -u $ITUNES_NAME \
  -p $ITUNES_PASS
```

以上でiTunes Connectへのアップロードは完了です。

# HockeyAppへのアップロード
続いて、社内配布などのAdhoc版のアップロードです。

## dSYMsの用意
HockeyAppでは、クラッシュログを取得するために`dSYMs`も一緒にアップロードする必要があります。
アップロードするために、`.xcodebuild`の下にある`dSYMs`を圧縮します。

```bash
zip -r build/Sample.app.dSYM.zip build/Sample.xcarchive/dSYMs/
```

## アップロード
HokeyAppはアップロード用のAPIを公開しているので、それを利用します。
オプションの詳細などは[公式のドキュメント](https://support.hockeyapp.net/kb/api/api-apps#upload-app)を参照してください。

```bash
curl \
  -F "status=2" \
  -F "notify=0" \
  -F "notes=Sample upload" \
  -F "notes_type=0" \
  -F "ipa=@build/Sample.ipa" \
  -F "dsym=@build/Sample.app.dSYM.zip" \
  -H "X-HockeyAppToken: $HOCKEY_APP_TOKEN" \
  https://rink.hockeyapp.net/api/2/apps/upload
```

# 終わりに
以上でTravis CIでのビルド・アップロードは終了です。
ここまでで最低限の運用はできますが、実行時間や配布したアプリの管理などに課題が残ります。
そんな課題の解決をする、運用のコツ編を23日に公開します。

明日は弊社デザイナー @UomoriAtsushi の「デザイナーが事業責任者になったら」です。

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