XamarinにVisual Studio Team Serviceを絡めて塩と胡椒で

このエントリは [Xamarin Advent Calendar 2017](http://qiita.com/advent-calendar/2017/xamarin) の13日目の投稿です。
実は2016年も13日目だったので、つい合わせてしまいました。

## XamarinをVisual Studio Team Serviceで

Visual Studio Team Service（以下、VSTS）というのは、リポジトリやバグトラッカーなどを含んだプロジェクト管理パッケージですが、その中でも自動ビルド＆テスト環境があるのです。
あるのです、とか初心者への説明風に書いてますが、以降はVSTSでリポジトリを触ったことがある、くらいのレベルの知識はあるとして書きます。

今回は、このビルド関連をXamrin用に使います。

…すみません。このエントリー、長いです。意味なく長いです。
（しかも読みにくいので尚更すみません）

### VSTSのビルドについて

VSTSのリポジトリに登録したプロジェクトから、自動処理を行うシステムです。
ビルド・テスト・デプロイとある程度の決まった手順を繋げて一連の処理として登録、実行するもの、です。

VSTSで手順を作り、ビルド用のホストを指定してビルドを行います。
このホストはVSTSであらかじめ用意されているホストと、自身で用意するホストがあり、定義時と実行時各々で指定することができます。

## サンプルプロジェクト

もうざっくりとプロジェクトが登録されているとして話を進めます。
説明用のプロジェクトを作りました。
VSTSだとクローズドのリポジトリになるので、同じものを[GitHubに登録](https://github.com/yakumo/XamarinHelloWorldTest)しておきます。
（単なるHello worldです）

![001.png](https://qiita-image-store.s3.amazonaws.com/0/59270/4882609f-5917-8519-0103-36c97f55503b.png)

ファイル構成的にはこうなっています。

![002.png](https://qiita-image-store.s3.amazonaws.com/0/59270/b48c9686-571e-5ad7-8a80-b09b05bf48e3.png)

全体でまとめている作業用の.slnと、各々のビルド用の.slnがあります。
どれも普通の.csprojをまとめるだけで、.slnとcommon/.csprojはdotnetコマンドでコマンドラインから作っています[^1]。

[^1]: Advent Calendarの２日目に田淵さんが **Shared Projectの方がいいです！** 的な事を書かれていて、以前は自分もそう思っていました。いましたが、相当前のXamarinのバージョンで、Shared Projectの場合どうしてもXAMLを読んでくれない、という体験があり、それ以来XamarinでShared Projectは避けています。

### ビルド定義

では、実際のビルド定義を作っていきます。

上部メニューの **Build and Release** を選ぶと、何もビルド定義がなければ以下の画面になります。

![003.png](https://qiita-image-store.s3.amazonaws.com/0/59270/209e9957-5f64-e47a-4a02-397a92a0b0ce.png)

ここで、「New definition」のボタンを押して、新規のビルド定義を作りましょう。
定義を作ったら、テンプレートを選択する画面になります。
XamarinのiOSやAndroid用のテンプレートもあります。

![004.png](https://qiita-image-store.s3.amazonaws.com/0/59270/2a536f20-f477-dc30-a002-7960c6289375.png)

しかし、作られたのが古いこともあり、このテンプレートは今回は使いません。
上部の **Empty process** の部分を選択し、空のビルド定義を作ります。

![005.png](https://qiita-image-store.s3.amazonaws.com/0/59270/d8178e2f-7e29-295c-4b7d-39ec205026b8.png)

作ると、以下のような画面になります。

![006.png](https://qiita-image-store.s3.amazonaws.com/0/59270/9f126bd2-6d15-e4e2-2243-99d060986cd9.png)

この画面がビルド編集の基本画面です。
左が各々のステップで、水色になっている部分が選択されており、右で設定していることを表しています。

テンプレートを反映した直後には **Process** が選ばれていて、ビルドの総合設定になっています。
右側で赤枠の部分は必須の設定項目です。
上記で赤枠になっている **Agent queue** の欄は、ビルドを行うホストを設定し、その上の **Manage** をクリックすることでホストの設定を行うことができます。
（詳細は後述）

まずは、赤枠内の「∨」をクリックしてメニューを出し、一旦 **Hosted macOS Preview** を選択しておきましょう。

次に、 **Phase 1** の右横の「＋」をクリックすることでビルドタスクを追加することができます。
右側がタスク一覧に切り替わるので、その中から行いたいタスクを選択、追加するわけですね。
今回はXamarin.iOSを選んで **Add** ボタンで追加します。

![007.png](https://qiita-image-store.s3.amazonaws.com/0/59270/d8a917c0-99ce-97ae-2611-94c20fff9ccd.png)

追加したら、Solutionの欄が必須項目として赤枠で表示されています。

![008.png](https://qiita-image-store.s3.amazonaws.com/0/59270/6c0161aa-4bc9-abd4-43cf-77745b43d8f3.png)

ここを `src/ios/XamarinHelloWorldTest.sln` に設定すれば上部の **Save & queue** が選べれるようになり、出てきたメニュー内から **Save & queue** を選んで次の画面で **Save & queue** のボタンをクリックすれば、ビルドが始まります。

ビルドが始まると、上部に

![009.png](https://qiita-image-store.s3.amazonaws.com/0/59270/66dbe4b3-3845-e34a-b592-f01eab76efb8.png)

などと表示されますので、 **#数字** の部分をクリックすると、ビルド中なら現在の状況が、ビルド終了していればログが表示されます。

## 正常にコンパイルさせるために

### ビルドできません

上記の設定をしただけでは、残念ながらエラーで終了します。
設定しなければいけないことは、

- **Agent queue** でビルドができるホストを指定する
- **Signing & Provisioning** でプロビジョニング情報を設定する

です。

### ビルドができるホストを指定する

実は、最初に Agent queue で選んだ Hosted macOS Preview では、XamarinのiOSプロジェクトをビルドすることはできません。（2017/12/12現在）
Signing & Provisioningを正しく設定しても、

```
error MT2101: Can't resolve the reference 'System.Void UIKit.UINavigationBar::set_PrefersLargeTitles(System.Boolean)', referenced from the method 'System.Void Xamarin.Forms.Platform.iOS.NavigationRenderer::UpdateUseLargeTitles()' in 'Xamarin.iOS, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065'.
```

というエラーで終了してしまいます。

なんという塩対応。
しょっぱいです。
さすがはPreviewです。
これさえなければMac実機がなくてもVSTSでiOSアプリが作れるのに。

## 自マシンをビルドホストに設定する

開発で使用している自分のマシンを、VSTSのAgentとして登録してビルドさせることができます。
やることとしては、

* VSTSにAgent queueの接続口を作成
* その接続口にマシンから接続する

ということになります。

### VSTS側の接続口を作る

接続口を作るには、歯車メニューから **Agent queue** を選んでAgent queueの設定画面を開きます。

<img width="206" src="https://qiita-image-store.s3.amazonaws.com/0/59270/afa1f1f1-d21a-25d9-2485-fa944add6216.png">

画面が切り替わったら、右上の **New queue...** を選び、新規作成します。

<img width="297" src="https://qiita-image-store.s3.amazonaws.com/0/59270/4e45dabb-3d29-5b2c-d5d1-f6761d7fea78.png">

ダイアログが開いたら、名前を設定してOKボタンで決定することでVSTS側の口が出来上がります。
日本語だと面倒臭そうなことになりそうなので、英数字で設定する事をお勧めします。

### 接続口に接続するように設定する

Agent queueの設定画面上部中央付近にある **Download agent** のボタンを押すしてください。

<img width="253" src="https://qiita-image-store.s3.amazonaws.com/0/59270/d9f87bfd-b05c-ab68-ebaf-5213bf7306ab.png">

Agent用アプリのダウンロードボタンとインストール方法の解説画面が開きます。

<img width="794" src="https://qiita-image-store.s3.amazonaws.com/0/59270/efa9737d-0689-8b63-9390-7de292ddd994.png">

もし、MacでAgentアプリのバージョンが2.125以下の場合、接続できなかったり、Xamarinアプリをビルドできない場合がありますので、2.125.1以上を使うようにしてください。（2017/12/12現在、上記画面のDownloadボタンからダウンロードできるのは2.126になっています）

最初に設定した時は2.124がダウンロードされて、接続できない、と相当悩みました…。
しょっぱいしょっぱい。

基本的に使用方法はインストールの解説の通りで問題ありません。
ダウンロードして、Terminalを開き、解凍し、解凍したディレクトリに移動、基本設定を行います。
解説画面では `./config.sh` を実行するようになっていますが、このコマンドには色々オプションがあります。一気に設定するには、以下のコマンドでできます。

```shell
$ ./config.sh --unattended --url https://myaccount.visualstudio.com --auth pat --token myToken --pool default --agent myAgent --acceptTeeEula
```

`--agent` で設定するのは接続口として設定した名前になります。

Agent登録には、セキュリティ確保のため認証が必要になっています。
`--token` パラメータで設定しているキーですが、VSTS上のセキュリティキー（Personal access token : pat）を取得する必要があります。

### Agent用セキュリティ設定（pat）

patの取得方法は、各ユーザーの設定から取得します。
右上のユーザー部分をクリックすると、メニューが出るので、その中から **Security** を選択してください。

<img width="258" alt="014.png" src="https://qiita-image-store.s3.amazonaws.com/0/59270/d0ebce3e-538a-744c-cba1-f73a17087041.png">

画面が切り替わったら、 **Personal access tokens** を選び、右側の **Add** で新しいキーを追加します。
設定では、権限と期限を設定できます。
権限は「全て」でも構いません。
表示されるpatは以降再確認できませんので、必ずコピーして、上記の `./config.sh` で設定してください。

### Agent起動

`./config.sh` で設定ができたら、Agentを起動します。
説明書通りに、

```shell
$ ./run.sh
```

でAgentが起動します。
歯車メニューからの **Agent queue**　を表示し、ちゃんと設定ができていれば、　

<img width="194" src="https://qiita-image-store.s3.amazonaws.com/0/59270/7f529d13-75dd-0ab1-154f-46d2e0eed7d2.png">
<img width="190" src="https://qiita-image-store.s3.amazonaws.com/0/59270/4b49f6e0-9e92-1ebc-d947-2d03198d120e.png">

OfflineからOnlineに状態が変わります。

*毎回起動が面倒くさい！* という方は、

```shell
$ ./svc.sh install
$ ./svc.sh start
```

とする事で、Agentが自動的に起動するようにできます。

## プロビジョニング設定

Agentの設定が済んだら、iOS系のビルドを通すためにプロビジョニング設定を行います。
キーチェーンアクセスを起動し、ビルドを行う証明書を「ログイン」から選択し、右クリックで「書き出す…」を選択します。

![016.png](https://qiita-image-store.s3.amazonaws.com/0/59270/439edf4a-c549-ca1a-d90f-29b73168d334.png)

保存ダイアログでは、フォーマットを「個人情報交換（.p12）」を選び、その後パスワードを設定してください。
このファイルを保存、リポジトリに混ぜておきます。

また、 **Apple Developer** のサイトから、ビルドに使う **.mobileprovisioning** ファイルをダウンロードし、これもリポジトリに混ぜておきます。

これらのファイルのリポジトリ内の相対パスとパスワードを以下の欄に設定する事で、ビルドができるようになります。

![017.png](https://qiita-image-store.s3.amazonaws.com/0/59270/b55c5e13-9b87-e3bc-fe13-dcb0e887f8ad.png)

## App Center

実は、 **App Center** のビルドなら、VSTSのHosted macOS Previewのようなエラーは出ません。
何が違うのだ…。

App Centerはソース元をVSTSのリポジトリに設定できるので、VSTSでプロジェクト管理、App Centerでビルド & テスト & beta配布までこなしてしまうことができるのです。

[3日目にfumiya-kumeさんが](http://kuxumarin.hatenablog.com/entry/2017/12/04/012645)、[4日目にyamachuさんが](http://teitoku-window.hatenablog.com/entry/2017/12/04/233304)それぞれ書いておられるので、そちらも参考にしてください！

### VSTSのビルドからApp Centerへデプロイする

VSTSのiOSパッケージビルドの設定で、 **Create App Package** のチェックを入れておく事で、.ipaファイルを作ってくれます。
その出力パスは `[.csprojパス]/bin/iPhone/Release/[出力ファイル名].ipa` です。
なので、このファイルをVSTSのタスク、 **App Center Test** や、 **App Center Distribute** に設定する事で、そちらでテストしたりデプロイしたりできます。

特に、Distributeは無料枠で使えるようなので、仲間内に配布するにはいいかもしれません。
（App Centerはクローズβ、deploy gateはオープンβ、的な）

## 結論

お手軽にやれるので、VSTSを使うより、App Centerを使いましょう！
そちらの方が絶対楽です！（ぉぃぉぃ）

## おしまい

そういえば、塩は出てきたけど、胡椒はなかったよね？
という。はてさて。それはそれは。

コンパイル用自ホストもそうですが、なんでもクラウドにつながってしまうこのご時世。
**故障がないのが一番だよね？** …と。

お後がよろしいようで。