Azure DevOps ( Piplines ) を使って CI/CD 環境を構築してみる
CI / CD ...。2~3年前からよく耳にするようになりましたね。 大きなカンファレンスで自社プロダクトの開発環境に組み込んでいるという事例を聞くたびに 「 CI / CD かっこいいなぁ 」 と思う一方、小さなプロジェクト (1人) や Unity 開発には 不要なものだとばかり思っていました。ただ、そんなことを言っていたらいつまで経っても新しいテクノロジーを自分たちのプロダクトに組み込むことができない、「まずは小さくでも良いから使い始めてみるのが大事だ!」 ということで、今回は Azure DevOps ( Pipelines ) で試してみた内容をまとめたいと思います。 実際に運用する際には本記事に記載のない細かなチューニングを行う必要がありますが、とにかく触って動かしてみるということをテーマに書いていきます。( 下図: 実際に Azure Piplines を使って CI を実行している際の画面イメージです。 )

この記事を読んで実現できる内容
GitHub にソースコードのプッシュを行うと、Azure Piplines ( Azure DevOps ) が実行され、以下の処理を自動で行ってくれる CI 環境の構築。
- Azure Piplines を利用した Unity プロジェクトのビルド、エクスポート
- Azure Piplines を利用した Visual Studio 2019 でのビルド
- Azure Piplines を利用した UWPアプリパッケージファイルの生成 & 保存
なぜ CI / CD を導入すべきなのか?
そもそも 「なぜ CI/CD 環境を導入すべきなのか?」 この問いに対しての明確な答えを持っていないと、本記事がただの技術検証で終わってしまいそうだったので、CI/CD の初歩的な内容から導入メリットまで私が調査した内容を以下、簡潔にまとめてみたいと思います。
昨今 CI/CD が注目を浴びている最大の理由は、クラウドサービスの台頭によるシステム開発期間の短縮化 ( 初回リリース時まで ) に起因していると考えています。
クラウドサービスの普及 ( IaaS, PaaS, SaaS etc..) により以前より気軽に、そして迅速にシステム開発・デプロイを行えるようになりました。また、ITテクノロジーの進化の波も激しく、少し先の未来ですら予測が難しいという時代に突入しています。これらのテクノロジーと時代の潮流において、長時間かけてシステム設計・開発を行うことは無駄が発生するリスクが大きいと考えられます。 ( ソフトウェアを取り巻く状況が刻一刻と変わるため ) そこで注目を浴びている開発手法が 「 アジャイル (Agile) 」 です。アジャイルは小さく始めて、リリース後も継続してソフトウェアを育てていくという思想が強く反映された開発手法です。なにも 「 ウォーターフォール 」 より 「 アジャイル 」 が優れているという主張をしたいわけではありませんが、このような時代の背景から 「 アジャイル 」 や 「 CI/CD 」 が注目されているということです。( 個人的にはアジャイルであれウォーターフォールであれ、プロジェクトを進める本質的な部分は変わらないと思っていますが、、。 )
CI / CD の意味は、以下をご参照ください。
1. 継続的インテグレーション ( CI : Continuous Integration )
具体的には、ソースコードがGitなどのコードリポジトリにプッシュ(更新)されたことを起点に、ソースコードのビルドやユニットテストの実行、ビルドで作成された成果物の保存までのプロセスを自動化したものを指します。CIの仕組みを導入することで、手作業によるビルド手順の漏れや開発者ごとに微妙に異なるマシンでのビルドによる差異の発生など不具合に繋がる不安定な状況を排除し、何回実行しても同じようにビルドが行われる環境を提供することができます。
2. 継続的デリバリー ( CD : Continuous Delivery )
CI(継続的インテグレーション)で作成した成果物を仮想マシンなどの運用環境へデプロイする、リリース作業の自動化が目的となっています。CDの導入による効果もCIと同じ部分が多く、作業の効率化や人的ミスの軽減、リリースサイクルの高速化などが挙げられます。
では、具体的に今回 Azure DevOps を検証する Unity プロジェクト へ対する導入メリットはどういった点なのか?ここで少し深掘りして考えてみたいと思います。
今回 CI 環境を構築する Unity プロジェクトでの作業内容について考えてみました。
1. Unity でプロジェクトを新規作成 & 開発を行う ( Unity )
2. Unity プロジェクトのソースコードを GitHub にて管理する ( GitHub )
3. Unity 上でビルドを実行し、UWP向けのソリューションファイルをエクスポートする ( Unity )
4. Visual Studio を開き、ソリューションファイルをビルドする ( Visual Studio )
5. HoloLens へ デプロイを行う
これらの開発作業を行う際には、以下の問題が発生することが考えられます。
・ Unity、Visual Studio のバージョン違いによってビルド時にエラーが発生する
・ Unity → Visual Studio → HoloLens へのデプロイがすべて手作業である ( 環境構築しないとビルドできない )
・ 複数人がローカルマシンでビルドを実行するとアプリの品質が不均質になる ( 開発環境、設定の差異 )
個人の開発環境やノウハウに依存する内容が多く、属人性が高いので、開発担当者が変わると
継続的なインテグレーション、継続的なデリバリーを行うことが難しくなってしまいます。
そこで登場するのが 「 Azure DevOps 」 であり、 「 CI/CD 」 です。
CI/CD を導入すれば、上記手順 2.~ 4. を自動化することができます。また、クラウドリソースを使ったビルド手順の実行により、これまで環境差異によって発生していたコンパイルエラーの解消や、手動で実行していたアプリのリリース手順をコードベースで管理することができ、誰がリリース手順を実行しても同品質のアプリを提供できる環境が整います。CD ( 継続的デリバリー ) に関しては今回の記事では手動でのインストールになるので微妙ですが、Webアプリ等であれば自動でデプロイを行うこともできます。( ※ HoloLens へのデプロイもやり方次第ではできると思いますが、今回は省略します。 )
What's Azure DevOps !?
Azure DevOps とは、開発者向けの CI/CD に必要なツールをひとまとめにしたサービスです。
Azure Boards や Azure Piplines など、チーム開発、CI/CD を加速させるサービスを1つのダッシュボードで管理することができます。

Azure DevOps の サービスラインナップ ( 5つ +α )
Azure DevOps は、大きく5つのサービス ( 機能 ) に分けられています。

本記事では Azure DevOps の中でも、特に Azure Piplines を使用した CI 環境構築についてご紹介いたします。
Azure Piplines で実現できること
ビルド、テスト、デプロイの手順を統合して自動で処理を実行してくれるサービスです。今回のユースケースの場合、 Unity プロジェクトの ビルド & エクスポート から、Visual Studioでのビルドまでを一気にクラウドリソースを使って実行することができるサービスです。実行内容は yamlファイル ( .yml ) を用いて定義することができます。 「 クラウドリソースを使って実行する 」 という点に大きな特徴があり、Azure Pipliens で使用できるクラウドリソースは大きく以下2種類に分かれています。
1. Microsoft-hosted Agent
2. Self-hosted Agent
Microsoft-hosted Agent と Self-hosted Agent の違い
大きくビルド環境の差異と使用料金の2つに違いがります。
-
Microsoft-hosted Agents を使用する場合
-
Microsoft が用意しているビルド環境を使用する
-
ビルド環境のカスタマイズ性 : 低
-
初期導入時のコスト : 低
-
プライベートプロジェクト無料枠 : 1800分/月
-
Self-hosted Agents を使用する場合
-
ユーザー自身でビルド環境を用意する
-
ビルド環境のカスタマイズ性 : 高
-
初期導入時のコスト : 高
-
プライベートプロジェクト無料枠 : 分数制限なし (※)
※ ただし、VM環境のランニングコストは含まれない。
今回は、手軽に検証することが目的なので 「 Microsoft-hosted Agent (windows-2019) 」 を使用します。
ちなみに、Microsoft-hosted Agent には以下6つの種類が用意されています。
- Windows Server 2019 with Visual Studio 2019
- Windows Server 2016 with Visual Studio 2017
- Ubuntu 18.04
- Ubuntu 16.04
- macOS X Mojave 10.14
- macOS X Catalina 10.15
※ 上記いずれのイメージにも 「Unity」 はインストールされていないので、Microsoft-hosted Agent を使用する際は、毎回Unityのインストール (10分程度) が発生します。公式ページにも記載がありますが、まず「Microsoft-hosted Agent」で動作検証を行った後、独自のビルド環境 ( Self-hosted Agent ) を使用した CI / CD に取り組まれることを推奨いたします。
目次
- Azure DevOps Organization 概要
- Unity Tools for Azure DevOps インストール方法
- 新しいパイプラインを作成する方法
- パイプライン実行時のプロセス確認
- パイプラインによって生成されたファイルの確認
- HoloLens 2 への実機デプロイ方法 ( 手動 )
- GitHub の README.md に Azure Piplines のステータスバーを追加する方法
- Azure Piplines 料金体系について
- まとめ
- 備考
Prerequests : 前提条件
Azure DevOps ( Piplines ) で CI を構築するにあたり、以下の事前準備が必要になります。
- Azure DevOps Organaization を作成済み
-
Azure DevOps Extensions (
Unity Tools for Azure DevOps
) をインストール済み - Unity Pro ライセンス ( アカウントID, パスワード, シリアライズキー ) を保有している
- ( Piplines を実行する対象となる ) Unity プロジェクトファイル
※ Azure Piplines を使用して、Unity ビルドを実行するためには Unity Plus/Pro ライセンス が必要になります。

Unity Plus/Pro シリアライズキーは、公式ページにサインインすると確認することができます。
00. Azure DevOps Organization 概要
Azure DevOps は Organization 単位で管理され、Organization の下に Project を追加することができます。
( 以下、Azure DevOps Organizaion ログイン時の画面イメージ。 )
Marcketplace からインストール可能な Azure DevOps Extensions ( 拡張機能 ) は、Organizaion 単位で管理することになります。
01. Unity Tools for Azure DevOps インストール方法
Azure DevOps ( Piplines ) を使用して Unity プロジェクトをビルドするためには 「Unity Tools for Azure DevOps」 をインストールする必要があります。

Unity Tools for Azrue DevOps は、以下の機能を提供しています。
- Unity プロジェクトのバージョン取得
- Unity Plus/Pro ライセンスのアクティベート
- Unity プロジェクトのビルド
インストール手順は以下の通りです。
1. Organization トップページのグローバルメニューより、Marcketplace のアイコンボタンを押下します。

2. プルダウンメニューが表示されるので、「Browse marketplace」ボタンを押下します。

3. Extensions for Azure DevOps の検索バーに 「Unity Tools for Azure DevOps」と入力し、検索を実行します。

4. 検索結果より 「Unity tools for Azure .. 」 のサムネイルを押下します。

5. Unity Tools for Azure DevOps のページが開いたら、「Get it free」ボタンを押下します。

これで「Unity Tools for Azure DevOps」エクステンションのインストールは完了です。
02. 新しいパイプラインを作成する方法
ここからは、 Azure Piplines を活用してパイプラインを作成していきたいと思います。
Azure DevOps Extentions と違い、パイプラインは Project ごとの管理となるので対象プロジェクトへ移動します。

1. サイドメニューより「Piplines」を押下します。

2. Piplines ページ右上の「New Pipline」ボタンを押下します。

3. 対象となるソースコードの管理先に接続を行います。
今回は GitHub 上で管理しているソースコードを対象にパイプラインを生成するので、GitHub を選択します。
( Azure DevOps 内の Azure Repos でもソースコードの管理が可能なので各自の環境に応じた接続先を指定してください。 )
4. 対象となるリポジトリを選択します。

5. Pipline の設定を行います。
今回は既存のパイプラインではなく、新たに作成するので「Stater pipline」を選択してください。

6. azure-piplines.yml を HoloLens 2 向けにアップデートします。
と言っても、いきなり yaml ファイルを編集するのは難易度が高いので、Microsoft 公式のテンプレートを使います。

HoloLens 2 向けのビルド実行手順がテンプレート化された azure-piplines.yml ファイルは以下、Microsoft 公式 GitHub にて公開されています。

- microsoft/Azure-DevOps-YAML-for-Unity ( GitHub )
7. 上記ページの azure-piplines.yml をコピーし、そのままペーストします。

8. yml ファイル実行時に必要な変数を登録します。

登録が必要な変数は、以下3つです。
- unity.username ( Unity アカウントのメールアドレス )
- unity.password ( Unity アカウントのパスワード )
- unity.serialkey ( Untiy Plus/Pro のシリアライズキー )

Variables ウィンドウの「+」ボタンを押下することで変数の追加が可能です。

登録時に 「Keep this value secret」にチェックを入れておくとパスワード部分が別の文字列(*)に置換されます。
パスワード、シリアライズキー入力時にはチェックを入れておくと良いと思います。
9. 「save」ボタンを押下し、azure-piplines.yml をコミットします。

これにてパイプラインの新規作成は完了です。今回は master ブランチにコミットしたので、早速作成したパイプラインが実行されます。
10. yml ファイルの解説 ( azure-piplines.yml )
以下、パイプライン処理のトリガーの設定です。
この場合、masterブランチへの変更が入ったタイミングでパイプライン処理が実行されます。
trigger:
branches:
include:
- master
以下、ビルド環境 ( Agent ) の設定です。
この場合、Microsoft-hosted Agent (windows-2019) を使用してビルドを実行します。
pool:
vmImage: 'windows-2019'
以下の行 ( UnityBuildTask@3 ) で Unity でのビルドを実行します。
- task: UnityBuildTask@3
displayName: Calling UnityBuildTask@3 from unity-azure-pipelines-tasks extension
name: runbuild
inputs:
buildScriptType: existing
scriptExecuteMethod: '$(unity.executeMethod)'
buildTarget: '$(unity.targetBuild)'
unityProjectPath: '$(unity.projectPath)'
outputPath: '$(Build.BinariesDirectory)'
以下の行 ( MSBuild@1 ) で Visual Studio でのビルドを実行しています。
- task: MSBuild@1
displayName: 'Build solution'
inputs:
solution: '$(unity.projectPath)$(unity.outputPath)' # Change to '$(unity.projectPath)$(unity.outputPath)' to resume two jobs
configuration: Release
以下の行 ( PublishPiplineArtifact@0 ) で アプリパッケージの生成 ( Artifacts ) を行っています。
# Publish the Solution folder:
- task: PublishPipelineArtifact@0
displayName: 'Publish Pipeline Artifact'
inputs:
artifactName: 'sln'
targetPath: '$(unity.projectPath)$(unity.outputPath)'
03. パイプライン実行時のプロセス確認
パイプライン実行時のプロセスは処理ごとに確認することができます。
1. サイドメニューより「Piplines」タブを開き、対象のパイプラインを選択します。

2. 次に対象のパイプライン処理を選択します。
こちらの画面ではパイプラインの処理がいつ、どのブランチで行われたのか?処理時間などを確認することができます。
3. 各処理ごとのエラーログ、生成ファイル ( Artifacts ) を確認

4. 個別ジョブごとのステータスを確認
ステータスの確認を行いたい、ジョブを選択します。

各タスクを選択すると、以下のように実行されたコマンドとログを確認することができます。

04. パイプラインによって生成されたファイルの確認
各パイプライン実行時の生成物は、パイプライン詳細ページの「Artifacts」よりダウンロードすることができます。

このようなカタチでアウトプットファイルが生成されています。

05. HoloLens 2 への実機デプロイ方法 ( 手動 )
- PC と HoloLens 2 を USBケーブルにて接続
- デバイスポータル ( http://127.0.0.1:10080 ) へアクセス
- 生成された証明書をインストール
- アプリパッケージファイルをインストール
以上の手順にて実機へのデプロイを行うことができます。
06. GitHub の README.md に Azure Piplines のステータスバーを追加する方法
Piplines が処理ごとに表示されるページに遷移し、右上の設定ボタンを押下します。
README.md に追加するためのマークダウン ( サンプル ) が表示されるのでコピーし、対象リポジトリの README.md をアップデートします。

07. Azure Piplines 料金体系について
Azure Piplines の料金体系は、 Agent によって変わります。
- 無料枠
- 1つの Micrsoft-hosted Agent ( 1800分/月 無料 - それ以降は料金が発生 )
- 1つの Self-hosted Agent ( 毎月の分数制限なし )
Microsoft-hosted Agent を使用した場合、1回の処理におそよ40分程度かかるので、45回程度実行できる計算になります。
詳細は、以下 公式ページ をご確認ください。

※ Azure Artifacts に関しても料金が発生するので、パイプラインを繰り返し実行する場合は注意が必要です。
08. まとめ
以下、今回技術検証を行ってみて感じたことをまとめます。
- Azure Pipline を使って、アプリパッケージファイルが自動生成された時の感動は異常
!
- Microsoft-hosted Agent を使ってみて
- ソースコードを特定ブランチにプッシュするだけで自動でアプリパッケージを生成してくれるのでかなり便利だった。
- 開発時のイテレーションを回すのに非常に有効なツールだと感じました。
- 開発者以外も使用できるのでアプリのテストを実行する際などに共有が容易になると感じた。
- Azure DevOps 内の他サービスと組み合わせると開発のほとんどすべてを Azure DevOps 上で完結できると思う。
- ただし、 Microsoft-hosted Agent を使用すると処理完了までに30分以上かかるので運用は少し厳しそうである。
実際に動かしてみて、CI/CDについて理解が深まったので、細かなチューニング等、Selft-hosted Agent で CI 環境を実現すべく勉強に励みたいと思います。気が付くと凄い長い記事になってしまいましたが、Azure DevOps や Azure Piplines を始められる方の参考になれば幸いです。最後までお読みいただき、ありがとうございました。
09. 備考
※ Integration は 「 〔 要素の 〕 統合、統一 」、Delivery は 「 〔 物や情報の 〕 配送、配達、配信 」 という意味を持つ英単語。