IPA ファイルを作成して DeployGate へアップロードまでを自動で on TravisCI

個人制作のアプリで、github に push したら、TravisCI で ipa ファイルを作成して DeployGate にアップロードするまでの流れを自動で行うようにしました。

# 前提

- p12 ファイルなどを扱うので全て<font color="Red">**自己責任**</font>で注意して行ってください。
- 今回は **ipa 作成 〜 deploygate へアップロード** の流れにフォーカスしているので、その他の詳しい説明 (プロファイルの作成方法、DeployGate・TravisCIの使用方法等) は割愛します。

## バージョンや状況

|Xcode|CI|
|:--:|:--:|
|9.3|TravisCI|

- 記事執筆日時: 2018/04/22
- **Manual signing** を使用しています
- **Cocoapods** も **Carthage** も使っています
- 今回自分が試したプロジェクトには **TodayExtension** と **watchOS系** の target が含まれています


# **.travis.yml** ファイル

細かな手順などは後に書いてます。
便宜上最低限の記述のみにしています。

```yaml
language: objective-c
osx_image: xcode9.3

script:
  # keychain
  - sudo security import <証明書>.cer -k /Library/Keychains/System.keychain -T /usr/bin/codesign
  - sudo security import <証明書>.p12 -k /Library/Keychains/System.keychain -P <PASSWORD> -T /usr/bin/codesign

  # provisioning profile
  - mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
  - mv <PPFILE_PATH> ~/Library/MobileDevice/Provisioning\ Profiles

  # xcodebuild
  - xcodebuild -workspace <PROJECTNAME>.xcworkspace -scheme <SCHEME_NAME> -configuration <Release> archive -archivePath <ARCHIVE_PATH>
  - xcodebuild -exportArchive -archivePath <ARCHIVE_PATH>.xcarchive -exportPath ./build -exportOptionsPlist <PLIST_PATH>.plist

  # deploygate
  - curl -f -F "token=<API_KEY>" -F "file=@build/<IPA_FILE>.ipa" https://deploygate.com/api/users/<OWNER>/apps
```

# 手順

## 1. cer, p12 ファイルの用意

既に用意できてる場合は大丈夫です。ない場合は下記の **3つの手段のいずれか** で用意してください。
**p12** ファイルを書き出す際にはパスワードを設定しますので、忘れないようにしてください。

用意したファイルを git 管理下に移動してください。

### A. Mac の キーチェーンアクセス から書き出す (for cer & p12)

キーチェーンアクセス.app を開いて、該当の証明書を右クリックし、cerとp12ファイルを書き出します。

### B. Xcode から書き出す (for p12)

Preferences > Accounts > 該当のアカウント > ManageCertificates > 該当の証明書を右クリック > Export Certificate

### C. Apple の Developer サイトからダウンロード (for cer)

[こちら](https://developer.apple.com/account/ios/certificate/) にアクセスし、該当の cer ファイルをダウンロードしてください。

### コマンドの説明

TravisCI で下記を実行しています。
`<証明書>` と `<PASSWORD>` は書き換えてください。

```sh
sudo security import <証明書>.cer -k /Library/Keychains/System.keychain -T /usr/bin/codesign
sudo security import <証明書>.p12 -k /Library/Keychains/System.keychain -P <PASSWORD> -T /usr/bin/codesign
```

ログの24行目あたりに下記のように記されています。
本来WWDRCA証明書が必要なのですが、TravisCI上の macOS の Keychain には既に登録されています。なのでこの Keychain を使用しています。

```sh
Fix WWDRCA Certificate
Unable to delete certificate matching "<省略>"security: AppleWWDRCA.cer: already in /Library/Keychains/System.keychain
```

## 2. ProvisioningProfile を用意

Xcode の signing 設定に指定している Provisioning Profile を用意します。
拡張子は`.mobileprovision`です。
複数の target を用いているプロジェクトではその数分 Provisiong Profile も必要です。
既に用意できてる場合は大丈夫ですが、ない場合 **下記の2つの手段のいずれか** から用意してください。

用意したファイルは git 管理下に移動して下さい。


### A. Apple の Developer サイトからダウンロード

ProvisioningProfile はここで作成します。既に作られている場合はダウンロードしてください。

### B. Xcode の管理場所から持ち出す

Xcodeでは `~/Library/MobileDevice/Provisioning Profiles` の場所で全て管理されています。
この中から該当のファイルをコピーして下さい。

### コマンドの説明

`-p` オプションを付けて ProvisioningProfile を置くべきディレクトリを用意し、ファイルをそこまで移動しましょう。

```sh
mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
mv <PPFILE_PATH> ~/Library/MobileDevice/Provisioning\ Profiles
```


## 3. xcodebuild で ipa 作成

1行目で archive を作成し、2行目で ipa を作成します。
`<>` 内はご自分のものに書き換えてください。

```sh
xcodebuild -workspace <PROJECTNAME>.xcworkspace -scheme <SCHEME_NAME> -configuration <Release> archive -archivePath <ARCHIVE_PATH>
xcodebuild -exportArchive -archivePath <ARCHIVE_PATH>.xcarchive -exportPath ./build -exportOptionsPlist <PLIST_PATH>.plist
```

### archive 作成

archive 作成コマンドを実行すると拡張子 `.xcarchive` のファイルが作成されます。
今回私のプロジェクトではcocoapodsを使用していたので workspace オプションで行っていますが、各自でコマンドは調整してください。
`<ARCHIVE_PATH>` は拡張子を**含めず**書きます。

### ipa 書き出し

ipa ファイル作成時には、オプションを記述した plist ファイルが必要です。
下記に最低限を示しておきますが、詳しくは [こちら](https://qiita.com/roworks/items/7ef12acabf9679561d84) が参考になります。
Xcode 上で管理すれば編集しやすいと思います。

作成した plist ファイルの場所を `<PLIST_PATH>` に記述しましょう。


```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>method</key>
	<string>ad-hoc</string>
	<key>compileBitcode</key>
	<false/>
	<key>provisioningProfiles</key>
	<dict>
		<key>BUNDLE ID をここに</key>
		<string>Provisioning Profile の名前をここに</string>
	</dict>
</dict>
</plist>

```


## 4. DeployGate へアップロード

[DeployGate の プロフィールページ](https://deploygate.com/settings) の下部に `API Key` があります。
`<OWNER>` は あなたのユーザ名です。

[公式ドキュメント](https://docs.deploygate.com/reference#upload) を参考にして下さい。

```sh
curl -f -F "token=<API_KEY>" -F "file=@build/<IPA_FILE>.ipa" https://deploygate.com/api/users/<OWNER>/apps
```

# 補足

## 証明書などの扱い

`.p12` や `cer` などの扱いは各自で注意してください。
特に`.p12`は<font color="Red">秘密鍵</font>を含んでいるので注意してください。

TravisCI でのファイルの暗号化は [公式の説明](https://docs.travis-ci.com/user/encrypting-files/) を参考にしてください。

## パスワードの扱い

パスワードや API Key を `.travis.yml` にべた書きするのは避けるべきです。

`https://travis-ci.com/<UserName>/<ProjectName>/settings` の [Environment Variables](https://docs.travis-ci.com/user/environment-variables/#Defining-Variables-in-Repository-Settings) を使用する、[`travis encrypt` コマンド](https://docs.travis-ci.com/user/encryption-keys/)を利用する、などなんらか別の安全な方法で行うべきです。


## ライブラリ管理
`carthage` や `cocoapods` を使用している場合は当然ながら install コマンド等を `.travis.yml` に書いてください。
キャッシュの設定などもするといいと思います。

## その他
- 私は xcpretty を使用していますが今回は省略して記述しています。
- 当然 Provisioning Profile には実行したい端末の UDID が含まれてないといけません。


# 参考
- https://docs.travis-ci.com/user/encrypting-files/
- https://dev.classmethod.jp/smartphone/iphone/apple-certificates-summary-and-etc/
- https://eng-entrance.com/linux-command-mkdir#-p--parents
- https://stackoverflow.com/questions/27671854/travis-ci-fails-to-build-with-a-code-signing
- https://qiita.com/roworks/items/7ef12acabf9679561d84
- https://docs.deploygate.com/reference#upload

# 後記

人によって環境が結構異なるでしょうし、詳しくなければ xcodebuild の認証周りで手こずる可能性が高いなど、一筋縄ではいかないことが多いと思います。
他のサイトなども参考にしながら、沢山試行錯誤しながら、頑張ってください。