Edited at

署名なしでiOSアプリのビルド&単体テスト〜Pipelines編〜


「Azure Pipelines」とは?

Azure DevOps Servicesの一種です。

Microsoftが提供しているクラウドのCI/CDサービスです。

Azure DevOpsのアカウントを持っていれば使えます。

(以下「Pipelines」と呼ぶ)


環境


  • Xcode:10.1 (10B61)

  • Swift:4.2.1

  • Carthage:0.31.2

  • CocoaPods:1.6.0.beta.2


Pipelinesでジョブの作成

Azure DevOpsにログインしてプロジェクトを作成します。

https://dev.azure.com/

プロジェクトの作成については割愛します。

左のツリーで「Pipelines > Builds」を選択

「+ New」をクリック > 「New build pipeline」を選択


スクリーンショット_2019-01-12_12_35_33.jpg

「Use the visual designer」を選択

スクリーンショット_2019-01-12_12_39_10.jpg

PipelinesではジョブをYAMLファイルで作成することが推奨されていますが、GUIで作成することもできます。

YAMLファイルより直感的に作成できるため、今回はビジュアルデザイナーを使って作成します。

ソース、プロジェクト、リポジトリ、デフォルトのブランチを選択

「Continue」をクリック


スクリーンショット_2019-01-12_12_45_41.jpg

私はAzure DevOpsのReposでソース管理しているので、「Azure Repos Git」を選択します。

今回は単体テストを実行するのが目的のため、ブランチは「develop」を選択しています。

「Xcode」を検索して「Apply」をクリック

スクリーンショット_2019-01-12_12_57_15.jpg

iOSアプリを対象とするのでXcodeのテンプレートを選択します。

ビジュアルデザイナーのメイン画面が表示されます。

スクリーンショット 2019-01-12 13.05.54.png

情報量が多くて挫折しかけますが、諦めないでください

ひとつひとつ説明していきます。


ジョブの詳細([Tasks]タブ)

ジョブは複数のタスクを組み合わせることで成り立っています。

[Tasks]タブでタスクの編集が行えます。


Pipeline

ジョブの基本的な情報を入力する箇所です。

編集前はこのようになっています。

スクリーンショット_2019-01-12_13_05_54.jpg

Nameはジョブの名前です。

ジョブの内容を一言で表せる名前が望ましいです。

今回は単体テストの実行なので「{プロジェクト名}-iOS-UnitTests」のような名前がよさそうです。

スクリーンショット 2019-01-12 13.20.34.png

Agent poolは実行環境です。

iOSアプリはmacOSでしかビルドできないため、「Hosted macOS」一択です。

スクリーンショット 2019-01-12 13.21.48.png

「Pool information」をクリックすると、選択した環境の情報を参照できます。

スクリーンショット_2019-01-12_13_24_35.jpg

ローカルで使っているツールとバージョンが異なっていないか確認します。

CocoaPodsとCarthageのバージョンは特に重要です。

もし異なっている場合、ツールをインストールするタスクが追加で必要になることがあります。

Workspace or project pathはワークスペースまたはプロジェクトファイルのパスです。

[…]をクリックして選択します。

スクリーンショット 2019-01-12 13.30.40.png

Schemeは対象のスキーマです。

App Centerと異なり選択でなく手動で入力するので、間違えないように気をつける必要があります。

スクリーンショット 2019-01-12 13.32.54.png

Xcode versionは文字通りXcodeのバージョンです。

2019/01/12現在、「Xcode 10」を選択すると「10.0」が使われます。

私はXcode 10.1を使いたいため、パスを直接指定します。

パスは以下に記載されています。

https://github.com/Microsoft/azure-pipelines-image-generation/blob/master/images/macos/macos-Readme.md#xcode

スクリーンショット_2019-01-12_13_41_50.jpg

こちらに記載されていないバージョンは使えないので注意です。

全て入力すると以下のようになります。

スクリーンショット 2019-01-12 13.43.48.png


Get sources

ソースの所得先を選択する箇所です。

先ほど選択したので、基本的には変更不要です。

スクリーンショット_2019-01-12_13_47_36.jpg

ただ、先ほどは指定できなかった項目があるので、必要に応じて変更します。

スクリーンショット 2019-01-12 13.58.37.png


Agent job

ジョブの本体です。

この下に並んでいるのがジョブ内のタスクです。

スクリーンショット_2019-01-12_14_03_19.jpg

ジョブ自体の設定は必要に応じて変更します。

私は特に変更しませんでした。


タスクの詳細

ジョブ内のタスクを見ていきます。


不要なタスクの削除

まず、今回のジョブに不要なタスクを削除します。

右クリック > Remove seleceted task(s) から以下のタスクを削除

Install an Apple certificate

Install an Apple provisioning profile

∵今回は署名しないため

Copy Files to: …

Publish Artifact: drop

∵今回は何もダウンロードしないため

Test with Visual Studio App Center

∵今回はUIテストを実施しないため

Deploy */.ipa to Visual Studio App Center

∵今回はデプロイしないため


タスクの入れ替え

ビルドに成功した場合のみ単体テストを実行したいため、以下のタスクをドラッグ&ドロップで入れ替えます。

Xcode build

Xcode test

ここまで行うとタスクは以下のようになります。

スクリーンショット_2019-01-13_12_31_49.jpg


タスクの追加・編集

ここからはタスクを追加・編集していきます。


Set Xcode path

何も指定しない場合、Swiftはデフォルトのバージョンが使われます。

SwiftのバージョンはXcodeと紐付いているため、Xcodeのパスを指定することでSwiftのバージョンを決定します。

※Xcodeのパスを直接指定していない場合、このタスクは不要かもしれません。

ジョブの[+]をクリック > 「Command Line」タスクを検索して「Add」をクリック

スクリーンショット_2019-01-13_12_40_27.jpg

ドラッグ&ドロップで一番上に持っていき、以下の項目を編集します。


  • Display name(任意)

    Command Line Script→Set Xcode path

  • Script

sudo xcode-select --switch /Applications/Xcode_10.1.app/Contents/Developer

先ほど指定したXcodeのバージョンと合わせる必要があります。

スクリーンショット_2019-01-13_12_52_02.jpg


Install CocoaPods

デフォルトでインストールされているCocoaPodsと異なるバージョンを使う場合のみ必要なタスクです。

Set Xcode pathと同様に「Command Line」タスクを追加し、以下の項目を編集します。


  • Display name(任意)

    Command Line Script→Install CocoaPods

  • Script

sudo gem install cocoapods --pre

私はβ版のCocoaPodsを使いたいため、 --pre を付けています。


Pod install

CocoaPodsで管理しているライブラリをインストールするタスクです。

ジョブの[+]をクリック > 「CocoaPods」タスクを検索して「Add」をクリック

スクリーンショット_2019-01-13_14_05_08.jpg

以下の項目を編集します。


  • Display name(任意)

    pod install→Pod install

  • Working directory

    […]をクリックし、 Podfile が格納されているフォルダを指定します。

    ルートフォルダに格納されている場合は省略できます。

  • Force repo update

    OFF→ON

    ONにしないとビルドエラーになることがあります。

スクリーンショット_2019-01-13_14_09_24.jpg


Install Carthage frameworks

Carthageで管理しているライブラリをインストールするタスクです。

CocoaPodsのように専用のタスクは用意されていないため、「Command Line」タスクでインストールします。

以下の項目を編集します。


  • Display name(任意)

    Command Line Script→Install Carthage frameworks

  • Script

export GITHUB_ACCESS_TOKEN={GitHubのアクセストークン}

carthage bootstrap --platform iOS --cache-builds && echo '*** Resolved dependencies:' && cat 'Cartfile.resolved'

CarthageはGitHubへのアクセス数が多いため、アクセストークンを設定しないと呼び出し制限に引っかかってしまいます。

アクセストークンの取得方法はこちらの記事などを参考にしてください。


  • Working directory

    […]をクリックし、 Cartfile.resolved が格納されているフォルダを指定します。

    ルートフォルダに格納されている場合は省略できます。

スクリーンショット_2019-02-27_16_55_21.jpg


Xcode build

Xcodeでビルドするタスクです。

以下の項目を編集します。

スクリーンショット_2019-01-13_15_43_41.jpg


Xcode test

Xcodeでテストを実行するタスクです。

以下の項目を編集します。


  • Signing style

    Project defaults→Do not code sign

  • Simulator(任意)

    iPhone 7→iPhone XR

    OSも指定する場合は「iPhone XR,OS=12.1」

  • Arguments(任意)

    -skip-testing:○○UITests

    UIテストを実行したくない場合はこちらのパラメータを追加します。

  • Enabled

    OFF→ON


  • Run this task

    Custom conditions→Only when all previous tasks have succeeded

スクリーンショット_2019-01-13_16_00_48.jpg

スクリーンショット_2019-01-13_16_01_05.jpg


ジョブの完成形

こちらがジョブの完成形です。

スクリーンショット 2019-01-13 16.08.26.png


ジョブの保存・実行

ジョブを保存・実行するには「Save & queue」をクリックし、「Save & queue」を選択します。

保存のみ行う場合は「Save」を選択します。

スクリーンショット_2019-01-13_16_16_54.jpg

Save commentにジョブの変更点などを記述し、「Save & queue」をクリックするとジョブが保存されて実行されます。

スクリーンショット_2019-01-13_16_18_18.jpg


ジョブの実行結果

ジョブの実行が成功すると以下のように全てのタスクに緑色のチェックが付きます。

スクリーンショット 2019-01-13 16.24.05.png

各タスクをクリックすることでログを確認できます。

スクリーンショット_2019-01-13_16_26_01.jpg

[Tests]タブで単体テストの実行結果を確認できます。

スクリーンショット_2019-01-13_16_28_10.jpg


ジョブの自動実行([Triggers]タブ)

[Triggers]タブで[Enable continuous integration]チェックをONにし、ブランチを指定することで、そのブランチのプッシュ時に自動でジョブを実行させることができます。

スクリーンショット_2019-01-13_16_50_35.jpg


おわりに

これで「ソースをプッシュ→ビルド→単体テスト」を自動化できました!

App Centerによるビルドより手間が掛かりますが、タスクを組み合わせることでより複雑なジョブを実行できます。

正直難しかったので、App Centerの自動ビルドのログを参考にタスクを組みました。

何か過不足しているタスクがありましたら教えていただけると嬉しいです。


おまけ〜AppCenterとDevOpsの使い分け〜

両方使ってみて、以下のように使い分けるのがいいと感じました。


  • Wiki、ソース管理、(複雑なCI/CD) → Azure DevOps

  • (単純なCI/CD)、テストアプリの配布 → App Center

クラウドのCI/CDサービスは乱立気味で重複している機能もあるため、使い分けが難しいです。

他にオススメの使い分け方やサービスがありましたらコメント欄などに記載していただけると嬉しいです:relaxed:


参考リンク