Xcode Server(Xcode サービス)のセットアップとCI

macOS Server とXcode の組み合わせで継続的インテグレーションできるよって話。

macOS Server は前回エントリ参照。要するにアドオンパッケージという理解で問題ない。

a244.hateblo.jp

なお、元ネタは以下の書籍。

Test-Driven iOS Development with Swift 3

Test-Driven iOS Development with Swift 3

Xcode Server (Xcode サービス)

日本語のマニュアルでは表記が「Xcode サービス」になっている。

Xcode経由で実行できるテストターゲットに限定されるが、いわゆる継続インテグレーションを実現できる。

前提としては、下記の通り。

  • macOS Server が動作するホストにXcode がインストールされていること
  • Gitリポジトリから対象のソースコードをチェックアウトできること(HTTP or SSH)
  • テスト実行用のアカウントが対象ホストにログインできること(実行時はログインしている必要あり)

テストの実行開始はリポジトリへのコミット、または指定された時刻のいずれか。

マニュアルを見る限り、 macOS Server をインストールするホストと普段開発作業を行うホストは別のホストで問題ない。

試しに実行後にテスト実行アカウントでログインすると、iOSシミュレーターが起動していることが確認できる。

設定

macOS Server

Application フォルダの、Server.appをダブルクリックしてmacOS Server の管理ツールを起動する。

f:id:atuyosi:20170701220201p:plain

有効化と Xcode の選択

まず、「サービス」カテゴリーの、「Xcode」というメニューをクリックする(①)。

f:id:atuyosi:20170702190638j:plain

「Xcodeを選択…」というボタンがあるのでクリック(②)。

f:id:atuyosi:20170702220524j:plain:w480

ファイル選択ダイアログでXcode.appをクリックして「選択」をクリック。

ユーザー作成

ユーザー作成のためのダイアログが表示されるのでパスワードを入力して「ユーザーを作成」

f:id:atuyosi:20170702192033j:plain

管理者権限は不要なので、チェックボックスはオフのまま。


しばらく待つ。 f:id:atuyosi:20170702192248j:plain

ユーザーの切り替え

バックグラウンドの処理の関係で作成したユーザーに切り替えることを要求されるので「ログイン」をクリック。

現在のユーザーがログアウトする訳ではないので神経質になる必要はない。

f:id:atuyosi:20170702192408j:plain

別ユーザーでのログイン

ログイン画面が表示されるので先ほど設定したパスワードでログイン。

f:id:atuyosi:20170704112543p:plain:w480
本来は背景が透けて見えるんですが……

新規アカウントでの初回ログイン時の設定画面が表示される。

テスト実行用のアカウントなので、普段使いのアカウントのように設定する必要はない。

  • Apple IDの入力要求は「サインインしない」を選択して「続ける」クリック
  • Siri は無効にして「続ける」をクリック。

一連の初期設定が完了するとデスクトップが表示され、同時にスクリーンロックについての警告ポップアップが表示される。

f:id:atuyosi:20170703164749p:plain

Screen Lock is enabled for the Xcode Server integration user

Screen Lock may prevent UI Tests from interacting with your application. To restrict access to this account, use Fast User Switching to switch to another user.

唐突に英語のメッセージ*1で面食らうが、要するに、

Xcode Serverの継続インテグレーション用のユーザーのスクリーンロック設定が有効になっている。
(このままだと)スクリーンロックがアプリケーションのUIテストを妨げる可能性がある。
このユーザーの制限を変更しない場合は「Switch User」を選択して他のユーザーに切り替え可能。

さあ、「どうします?」というメッセージ。

  1. "Ignore": 無視して続行
  2. "Switch User":このユーザーの制限はそのままにして別のユーザーに切り替え
  3. "Open Security Preferences":環境設定画面を開いて設定を変更

UIテストを実行しない場合は1. の”Ignore” 。そうでない場合は3. "Open Security Preferences"をクリックして設定画面にアクセスして無効化する。

スクリーンロックを無効化するのはセキュリティ上好ましくないので、管理者権限を持たないアカウントの方が望ましい。
もしくは、UIテストの自動実行は諦めるか、物理的にmacOS Server のコンソールに自由にアクセスできないようにする*2


ひとまず普通のユニットテストをさせたいなら「Ignore」で一旦ポップアップを閉じ、しばらく待ってバックグランドの処理が終わるのを待つ。

画面右上に処理管理用の通知が表示されたら、同じく画面右上のユーザー名をクリックして元のユーザーにスイッチする。

設定変更を行う場合は、「環境設定」から「セキュリティとプライバシー」をクリック。

f:id:atuyosi:20170703170628j:plain

f:id:atuyosi:20170703170214j:plain
チェックを外す(上記の3. を選ぶとここの画面に移動するはず)

f:id:atuyosi:20170703170756p:plain
パスワードの入力(先ほど設定したもの)

f:id:atuyosi:20170703170804p:plain
「画面のロックを切りにする」をクリック

f:id:atuyosi:20170703170816p:plain
設定変更完了


上記の1. or 3. の場合は、画面右上のユーザー名をクリックして元のユーザーのデスクトップに戻る。

f:id:atuyosi:20170704114516j:plain

リポジトリの設定

ソースコードをGitリポジトリからチェックアウトしてビルド、テスト実行、リポジトリの情報を設定する。

ただ、参照するGitリポジトリがリモートかローカルかによってそれぞれ追加の作業が必要になる。

  • 外部のGitリポジトリ
  • ローカルマシンのGit リポジトリ

前者は話が簡単だが、後者はmacOS Serverの動作するホスト側でリポジトリを作成し、開発用のリポジトリと同期する必要がある。

このエントリは後者のケース。

この記事のケースでは開発マシン自体にmacOS Server をインストールしているので、そのままプロジェクトのフォルダでGit リポジトリを作成して使用。

ローカルのGit リポジトリからXcode Server のリポジトリにgit pushして、データを同期したうえでリポジトリからテストが実行される。

画面中央やや上にある「リポジトリ」タブをクリックし、「リポジトリへのアクセスを編集…」をクリックしてSSHを有効に。

f:id:atuyosi:20170704150358j:plain

f:id:atuyosi:20170704150900j:plain

SSHによるリモートログインの可否を訊いてくるので、「許可」をクリックする。

f:id:atuyosi:20170704152747j:plain:w420

Xcode側の設定 その1

Xcodeを起動して、Preferenceへ。

左から2番目のAccountsタブへ移動。

f:id:atuyosi:20170704155511j:plain

左下の「+」マークをクリックして「Add Server」。ローカルマシンがリストに表示されているので選択して「Next」。

f:id:atuyosi:20170704155518j:plain

管理者権限を持ったアカウントのユーザー名とパスワードを入力する。

※ 今回作成したテスト実行用のアカウントとは別のユーザーアカウント。

Gitリポジトリ追加

同期用にリポジトリを追加する必要がある。

f:id:atuyosi:20170704165342j:plain

Server.appに戻って、画面中央左下の「+」マークをクリック。

f:id:atuyosi:20170704163849j:plain
プロジェクト名を入力して「作成」をクリック。

このタイミングでSSHのアクセス権を確認しておく方がいいかも。「編集…」をクリックすると確認できる。

f:id:atuyosi:20170704164552j:plain 追加が完了すると、中央やや下のリストにリポジトリのパスが表示されるのでその行をダブルクリック。

f:id:atuyosi:20170704220316j:plain テスト対象のソースコードを同期するために、リポジトリのパスが必要になるので、ssh://で始まる行をドラッグして選択、右クリックでコピー。

Xcode の設定 その2

もう一度Xcode側で設定を行う。

f:id:atuyosi:20170704202945j:plain:w480
Source Control からプロジェクトのリポジトリの"master"から「Configure <プロジェクト名>」。

f:id:atuyosi:20170704221156j:plain
画面上部の、Remoteタブをクリック。

f:id:atuyosi:20170704221605j:plain
左下の 、十字のアイコンをクリックして表示されるメニューから"Add Remote"をクリック。

f:id:atuyosi:20170704221629p:plain

f:id:atuyosi:20170704222208j:plain

先ほどコピーしたsshで始まるssh://で始まるURLをペースト。

f:id:atuyosi:20170704222635j:plain

"Done"で閉じる。

Botの追加

そのままXcodeで作業を続行。

メニューの"Product "から「Create Bot...」 。

f:id:atuyosi:20170705000129j:plain

f:id:atuyosi:20170705000444j:plain

f:id:atuyosi:20170705000852p:plain

f:id:atuyosi:20170705000953j:plain

f:id:atuyosi:20170705001353p:plain

"Integrate"のプルダウンメニューから設定を変更できる。特定の時刻か、コミット時、または手動でテストが実行されるように設定できる。

f:id:atuyosi:20170705001919p:plain

  • Periodically
  • On Commit
  • Manually

f:id:atuyosi:20170705002923p:plain

f:id:atuyosi:20170705002929p:plain
"All iOS Devices and Simulators" というプルダウンメニューをクリック。個別に指定したい場合は"Specific iOS Devices"をクリックしてテスト対象のデバイスを選択(詳細は下図参照)。

f:id:atuyosi:20170705003111p:plain

iOSデバイスの実機が接続されていればテスト対象として指定できる。

f:id:atuyosi:20170705003722p:plain

環境変数の設定。追加したい場合は左下の十字のアイコンから。

f:id:atuyosi:20170705003944p:plain
Triger Script の設定。テスト実行前、テスト実行後に動作するスクリプトを設定できる。テスト結果のレポート送信の設定もこの画面で。

f:id:atuyosi:20170705004218p:plain

特に追加しなくても問題ないので右下の"Create"を押す。

最後に”Create"を押すとBotが作成され、commit windowが表示されるので、適当なメッセージを入力してCommit。

f:id:atuyosi:20170705004449p:plain

「接続先のホスト鍵(?)が信頼できねー(超意訳)」とか文句を言われたら"Trust"をクリックする。

f:id:atuyosi:20170705004509p:plain

環境によってはユーザー名とパスワードを訊いてくる。

f:id:atuyosi:20170705004710p:plain

XcodeのPreferencesで登録したID(テスト実行用ではないアカウント)で問題ないはず。

問題なくテストが実行されれば、Xcodeの”Report Navigator"から結果を確認できる。

f:id:atuyosi:20170705010326p:plain

Warning が表示されているがテスト自体は成功している*3


開発中は

トラブルシューティング

ネットワーク接続設定

Server.app側のXcodeサービスの画面を開き、「アクセス権を編集」をクリックしてネットワークアクセスの設定を確認する。

f:id:atuyosi:20170705005909j:plain

f:id:atuyosi:20170705005300p:plain
許可する接続元を変更。

f:id:atuyosi:20170705010034p:plain

テストとは無関係だが面倒なので素直に「Webサイトへのアクセスを変更」をクリック。

「続ける」を選んでも問題はないはず。

ユーザーの権限の確認

リポジトリのアクセス権、サービスへの接続についての制限に引っかかっていないかチェックする。

その他

テスト実行ユーザーでログインしているかどうか、確認する。

ホストの再起動後など、テスト実行ユーザー(この記事の場合はxcodeserver)がログインした状態になっている必要がある。

おわりに

Xcode経由でテストを走らせる分には悪くない選択肢ではないでしょうか。

開発中は特定の機種を前提に作業して、夜間などに各iOSデバイスの画面サイズにおける動作チェックをまとめて行う、ということができる。

テスト実行時にiOSシミュレーターで画面サイズを切り替えてテストを実行することを繰り返すのは大変。

iPadとiPhoneの両方をサポートするユニバーサルアプリやある程度規模大きいアプリの方がありがたみが大きいと思う。

複数のアプリを並行して開発する場合にも役立ちそう。

ただ、そのままではプロジェクト管理ツールの類と連携できないのがネックか。


それではまた。

*1:無生物主語構文ですね

*2:高速ユーザー切り替えの場合はパスワードの入力を要求される

*3:複数回失敗しているけど画面サイズの関係でボタンがキーボードに隠れるために失敗している。とりあえず気にしない