「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」を選択
PipelinesではジョブをYAMLファイルで作成することが推奨されていますが、GUIで作成することもできます。
YAMLファイルより直感的に作成できるため、今回はビジュアルデザイナーを使って作成します。
ソース、プロジェクト、リポジトリ、デフォルトのブランチを選択
「Continue」をクリック
私はAzure DevOpsのReposでソース管理しているので、「Azure Repos Git」を選択します。
今回は単体テストを実行するのが目的のため、ブランチは「develop」を選択しています。
iOSアプリを対象とするのでXcodeのテンプレートを選択します。
情報量が多くて挫折しかけますが、諦めないでください 。
ひとつひとつ説明していきます。
ジョブの詳細([Tasks]タブ)
ジョブは複数のタスクを組み合わせることで成り立っています。
[Tasks]タブでタスクの編集が行えます。
Pipeline
ジョブの基本的な情報を入力する箇所です。
Nameはジョブの名前です。
ジョブの内容を一言で表せる名前が望ましいです。
今回は単体テストの実行なので「{プロジェクト名}-iOS-UnitTests」のような名前がよさそうです。
Agent poolは実行環境です。
iOSアプリはmacOSでしかビルドできないため、「Hosted macOS」一択です。
「Pool information」をクリックすると、選択した環境の情報を参照できます。
ローカルで使っているツールとバージョンが異なっていないか確認します。
CocoaPodsとCarthageのバージョンは特に重要です。
もし異なっている場合、ツールをインストールするタスクが追加で必要になることがあります。
Workspace or project pathはワークスペースまたはプロジェクトファイルのパスです。
[…]をクリックして選択します。
Schemeは対象のスキーマです。
App Centerと異なり選択でなく手動で入力するので、間違えないように気をつける必要があります。
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
こちらに記載されていないバージョンは使えないので注意です。
Get sources
ソースの所得先を選択する箇所です。
先ほど選択したので、基本的には変更不要です。
ただ、先ほどは指定できなかった項目があるので、必要に応じて変更します。
Agent job
ジョブの本体です。
この下に並んでいるのがジョブ内のタスクです。
ジョブ自体の設定は必要に応じて変更します。
私は特に変更しませんでした。
タスクの詳細
ジョブ内のタスクを見ていきます。
不要なタスクの削除
まず、今回のジョブに不要なタスクを削除します。
右クリック > 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
タスクの追加・編集
ここからはタスクを追加・編集していきます。
Set Xcode path
何も指定しない場合、Swiftはデフォルトのバージョンが使われます。
SwiftのバージョンはXcodeと紐付いているため、Xcodeのパスを指定することでSwiftのバージョンを決定します。
※Xcodeのパスを直接指定していない場合、このタスクは不要かもしれません。
ジョブの[+]をクリック > 「Command Line」タスクを検索して「Add」をクリック
ドラッグ&ドロップで一番上に持っていき、以下の項目を編集します。
- Display name(任意)
Command Line Script→Set Xcode path - Script
sudo xcode-select --switch /Applications/Xcode_10.1.app/Contents/Developer
先ほど指定したXcodeのバージョンと合わせる必要があります。
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」をクリック
以下の項目を編集します。
- Display name(任意)
pod install→Pod install - Working directory
[…]をクリックし、Podfile
が格納されているフォルダを指定します。
ルートフォルダに格納されている場合は省略できます。 - Force repo update
OFF→ON
ONにしないとビルドエラーになることがあります。
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
が格納されているフォルダを指定します。
ルートフォルダに格納されている場合は省略できます。
Xcode build
Xcodeでビルドするタスクです。
以下の項目を編集します。
- Destination platform(任意)
Default→iOS and watchOS - Simulator(任意)
iPhone 7→iPhone XR
シミュレータの種類は以下に記載されています。
https://github.com/Microsoft/azure-pipelines-image-generation/blob/master/images/macos/macos-Readme.md#device-types - Run this task
Custom conditions→Only when all previous tasks have succeeded
前のタスクが全て成功した場合のみビルドするようにします。
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
ジョブの完成形
ジョブの保存・実行
ジョブを保存・実行するには「Save & queue」をクリックし、「Save & queue」を選択します。
保存のみ行う場合は「Save」を選択します。
Save commentにジョブの変更点などを記述し、「Save & queue」をクリックするとジョブが保存されて実行されます。
ジョブの実行結果
ジョブの実行が成功すると以下のように全てのタスクに緑色のチェックが付きます。
ジョブの自動実行([Triggers]タブ)
[Triggers]タブで[Enable continuous integration]チェックをONにし、ブランチを指定することで、そのブランチのプッシュ時に自動でジョブを実行させることができます。
おわりに
これで「ソースをプッシュ→ビルド→単体テスト」を自動化できました!
App Centerによるビルドより手間が掛かりますが、タスクを組み合わせることでより複雑なジョブを実行できます。
正直難しかったので、App Centerの自動ビルドのログを参考にタスクを組みました。
何か過不足しているタスクがありましたら教えていただけると嬉しいです。
おまけ〜AppCenterとDevOpsの使い分け〜
両方使ってみて、以下のように使い分けるのがいいと感じました。
- Wiki、ソース管理、(複雑なCI/CD) → Azure DevOps
- (単純なCI/CD)、テストアプリの配布 → App Center
クラウドのCI/CDサービスは乱立気味で重複している機能もあるため、使い分けが難しいです。
他にオススメの使い分け方やサービスがありましたらコメント欄などに記載していただけると嬉しいです