Azure DevOps で UE5 プロジェクトを自動ビルド化してみる

# はじめに

Azure DevOps を使用して Unreal Engine 5 (以下UE5) のプロジェクトのビルドを自動化してみようと思います。
内容は大きく分けると以下のようになります。

- [Azure DevOps とは？](#azure-devops-とは)
- [自動ビルドを行う端末をセットアップする](#自動ビルドを行う端末をセットアップする)
- [Azure DevOps Pipelines でビルドを自動化する](#azure-devops-pipelines-でビルドを自動化する)

# 事前準備

以下の内容については事前に準備していただいている前提で進めたいと思います。

1. 自動化に使用するビルドマシンの用意
    - Windows 10
    - Visual Studio or VS Code
    - UE4 もしくは UE5
1. Azure DevOps のアカウント
1. UE プロジェクト
    - UE4 または UE5 でビルドが通る前提のプログラム

**※今回は Self-hosted という環境で自動ビルド環境を構築しますのでビルドマシンが必要となります。**

# Azure DevOps とは？

Azure DevOps とはマイクロソフトが提供する開発者向けのクラウドサービスです。
CI/CD の一連の流れを全て、一つのサービスとして統合されています。

## Azure DevOps で使用可能なサービス一覧

- Boards (タスク)
- Repos (ソースコード管理)
- Pipelines (自動化)
- Test Plans (テスト)
- Artifacts (成果物)

## CI/CD 環境の比較

|サービス名|クラウド|費用|複雑さ|メンテナンス性|サービス詳細|
|:--|:-:|:-:|:-:|:-:|:--|
|Azure DevOps|◯|◯|△ (※1)|◯|タスク (Boards)<br>ソースコード (Repose)<br>自動化 (Pipelines)<br>テスト (Test Plans)<br>成果物 (Artifacts)|
|GitHub|◯|△ (※2)|◯|◯|ソースコード (Code)<br>課題 (Issues)<br>自動化 (Actions)<br>成果物 (Actions)<br>テスト (Actions)|
|AWS CodePipeline|◯|？ (※3)|△ (※4)|◯|ソースコード (CodeCommit)<br>自動化 (CodeBuild)<br>テスト (CodeBuild)<br>成果物 (CodeBuild/CodeDeploy)|
|Jenkins|△ (※5)|-|◯|✕ (※6)|自動化のみ|

※1：設定項目が詳細に設定出来る反面、複雑さが出ている。
※2：無料枠が Azure DevOps に比べて低い・少ない。
※3：実際に調べたり触っていないため不明です。
※4：統合環境があるわけではなく、複数のサービスを自前で統合する必要がある。
※5：VM などを使用することでクラウドに設置することは可能だが、自前でホストする必要がある。
※6：オンプレでホストする場合、ハードウェア側のメンテナンスが含まれる。また、基本的には GUI による設定のみ。

## Repos (ソースコード管理)

Azure DevOps の Repos は標準では Git

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/2a730993-fd9e-1f45-e143-682db99363f7.png)

# 自動ビルドを行う端末をセットアップする

Azure DevOps ではプロジェクト単位で管理されます。
一つのプロジェクトに Repos や Pipelines のサービスが含まれています。
そのため Azure DevOps でははじめにプロジェクトを作成することから始めます。

## プロジェクトの作成

Azure DevOps のアカウント画面の右上にある『New project』をクリックしてプロジェクトの作成の設定画面に移ります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/005df552-3c53-98b1-828c-f555cb6f5c33.png)

プロジェクトの設定画面では以下の設定が可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/48dbc8c1-64f2-98e8-7d18-df5024f1be7d.png)

|設定名|説明|
|:--|:--|
|Project name|プロジェクトの名前|
|Description|プロジェクトの説明|
|Visibility|公開範囲。<br>Public: インターネット上に公開されます。一部の機能は制限されます。<br>Private: アクセス権を与えた人だけに公開されます。|
|Version control|バージョン管理に使用するアプリケーション。<br>Git または Team Foundatoin Version Control|
|Work item process|作業に使用するワークアイテムプロセスの種類。<br>Basic/Agile/Scrum/CMMI|

※Work item process については今回は説明しませんのでデフォルトの Basic で問題ありません。

今回は以下の設定にしております。

- Project name：UE
- Description：Azure DevOps で UE5 プロジェクトを自動ビルド化してみる
- Visibility：Private
- Version control：Git
- Work item process：Basic

作成が完了すると以下のような画面になると思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/5130bb3a-7cff-75cf-fcf7-2da1d3ba2590.png)

サイドバーでは Overview が選択されおり、プロジェクトの概要が表示されていると思います。

## リポジトリの初期化

次にサイドバーから Repos を選択すると以下のような画面になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/9c3ed929-a42b-5f8a-1281-8008b929bf80.png)

この状態では Repos には何もコミットされていない状態ですので初期化を行います。
画面下部にある『Initialize main branch with a README or gitignore』で README.md と .gitignore をコミットするかの選択が出来ますので、今回は『Add a README』にチェックを入れ、『Add a .gitignore: None』のプルダウンから『Unreal Engine』を選択し『Initialize』をクリックします。

処理が完了すると README.md と .gitignore がコミットされた状態で main ブランチが初期化されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/929a9d39-c4b5-21c2-9c59-665bc72d42e3.png)

これでリポジトリが使える状態になりました。

## ビルドを実行する環境構築

ビルドを実行する環境を構築する上で以下の手順が必要となります。

- ホスト環境の用意 (ビルドするハードウェア)
- Personal Access Tokens (PAT) の取得
- エージェントの登録 (ビルドマシンを認識させる)

### ホスト環境の種類

ビルドを実行するホスト環境は大きく分けて二種類あります。

- Microsoft-hosted
- Self-hosted

それぞれの機能や比較はこの後に記載しますが、今回は Self-hosted 環境で構築します。

#### 機能

||Microsoft-hosted|Self-hosted|
|:--|:--|:--|
|ハードウェアの提供|Microsoft|自前|
|ハードウェアのメンテナンス|Microsoft|自前|
|ハードウェアのスペック|固定|自由|
|ソフトウェア|スクリプトでインストールなどのセットアップが必要|予めインストールしておくなどが可能|

#### 比較
||Microsoft-hosted|Self-hosted|
|:--|:--|:--|
|メリット|ビルドを実行するハードウェアは Microsoft が予め用意しているものを利用するため、自前でハードウェアを用意しなくてもよいため、購入費用や管理コストが下がる。常にクリーンな環境でビルドする事が出来るため環境依存の設定などを把握しやすい。|ビルドを実行するハードウェアを自前で用意するため、好きなソフトウェアや設定などを予めセットアップしておくことが可能ため、セットアップ時間の短縮が出来る。|
|デメリット|ビルドを実行するハードウェアが用意されているものを利用するため、必要なソフトウェアなどのセットアップをスクリプトで行う必要がある。予め用意されているハードウェアのスペックが固定ため、より早くビルドを回したいなどの融通がきかない。|自前でハードウェアを用意する必要があるため、そのハードウェアの管理・メンテナンスを行う必要がある。|

Microsoft-hosted はハードウェアを用意しなくても良いのでメンテナンスなどの手間が少なくて良いのですが、スペックの融通が利かないやセットアップの手間などがあります。

### Personal Access Tokens (PAT) の取得

Personal Access Tokens (PAT) とは Azure DevOps へのアクセスを行う際に必要なトークンです。
トークンはユーザーごとに生成しますので、プロジェクト管理者などのアカウントで発行するのが良いです。

#### トークンの種類

トークンには一つのトークンで様々なアクセス権を付加することが可能です。

例えば…

- ソースコード管理 (Repos) の閲覧のみが可能なトークン
- タスク管理 (Boards) の読み書きが可能なトークン
- 全権限があるトークン

などがあります。

今回の Self-hosted ではエージェント登録に必要なアクセス権である『Agent Pools』という権限を付与したトークンを生成します。

#### PAT の生成方法

トークン生成には Azure DevOps の管理画面の右上にあるアカウントアイコンを選択し『Personal access tokens』をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/5f44af9c-a047-d90a-d4d1-f845dd9fb21d.png)

画面が遷移すると以下のような画面になると思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/3fc256cd-5f21-52d1-ee68-c3561068d025.png)

画面左上にある『New Token』を選択することで『Create a new personal access token』というウィンドウが開きますので、必要項目を入力してトークンを生成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/f4cf34a8-73a2-ab9f-ae3d-3e62981fd84d.png)

トークン生成で必要な権限は前述しましたが『Agent Pools』の権限なのですが、デフォルトでは表示されていません。
画面下部に『Show all scopes』を選択することで『Agent Pools』の項目が表示されます。

今回の設定は以下となります。

|設定項目|設定値|
|:--|:--|
|Name|UE_Build_Agent|
|Organization|デフォルトで設定されている値|
|Expiration (UTC)|30days|
|Scopes|Custom defined|
|Agent Pools|Read & manage|

`Name` はトークン一覧で表示されるもので、何に使用しているトークンか分かりやすい名前を付けるのが良いと思います。

上記の設定が完了したら『Create』でトークンが生成されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/edbd0de4-49a4-cea8-77df-0f97914eff10.png)

このウィンドウにも表示されていますが、このトークンは同じ値のものは作成や保存はされません。
紛失した分からなくなった場合は再生成が必要になりますので、一時的にどこかにコピーしておくのが良いです。

### エージェントの登録

Azure DevOps ではホスト環境の事を『エージェント』と呼び、Self-hosted 環境のビルドマシンを自動ビルドが行えるホスト環境としてエージェント登録を行います。

#### エージェントプールの作成

エージェントはエージェントプールというグループで管理されます。
エージェント単体では使用することはなく、エージェントプールにエージェント登録をすることで自動ビルドの対象として扱われますので、そのエージェントプールを作成します。
エージェントプールは組織ごとやプロジェクトごとに分けて使用するなどが良いです。

プロジェクト管理画面の左下にある『Project settings』を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/7f3e9d66-6324-606e-d5ce-b919fbe456eb.png)

この画面ではプロジェクトの設定を行いますが、今回はサイドバーにある『Agent pools』を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/35755052-7aee-e79b-cdbb-6aa2b1769cb3.png)

そうするとデフォルトでは『Azure Pipelines』と書かれた『Azure Pipelines』や『Default』が存在しているかもしれません。
デフォルトのエージェントプールは無視して、新しくエージェントプールを作成しますので『Add Pool』を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/fa696fae-77db-7c7f-8f2c-16ae3ccb679e.png)

ウィンドウが立ち上がりエージェントプールの種類が選択できると思いますが、今回は『Self-hosted』を選択してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/cef0d7cc-c754-db56-f687-810f6ba9cc44.png)

そうすると選択項目が新しく表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/d2dd77ce-47b2-50d9-3db7-da2b50df6b00.png)

今回の設定は以下となります。

|設定項目|設定値|
|:--|:--|
|Pool type|Self-hosted|
|Name|UE_Build_Agent|
|Description|空欄|
|Grant access permission to all pipelines|`true`|

社内で使うだけであれば全てのパイプラインに対してアクセス権限を付与するで良いかと思いますが、細かくアクセス制御をしたい場合はチェックボックスは適時変更してください。

エージェントプールが作成されると先程入力した『UE_Build_Agent』と言うエージェントプールが一覧に表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/e367ab17-5603-401d-f024-04ff039ce07f.png)

#### エージェントをエージェントプールに登録

エージェントプールが作成できましたので、次はエージェントプールにエージェントを登録します。
先程作成した『UE_Build_Agent』を選択すると登録されているエージェント管理画面が表示されますので、上部のタブから『Agents』を選択してエージェント一覧を表示します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/f119643a-c71f-f949-5c7e-9c89ac9a9157.png)

そこではまだエージェントが登録されていませんので『Add your first agent』と表示されており、『New agent』が選択できる状態ですので選択をしてください。

以下のウィンドウが表示されますので『Download』を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/53807feb-5f06-c6cc-44b3-1d6f4b1e5ad7.png)

これはビルドマシンをエージェントとして動作させるためのエージェントプログラムです。
ダウンロードが終われば、次は PowerShell を起動します。

**※PowerShell 起動の際には管理者権限を持っているユーザーで起動してください。**

ここからはコマンドラインによるセットアップですが基本的には上記の画像にある通りに進めるだけでセットアップは完了します。

PowerShell ではエージェントをインストールしたいドライブに移動します。
今回はデータディスクとして F: を使用しておりますので F: で進めますが C: ドライブでも各自の好きな環境で実行していただいて問題ありません。

```PowerShell
PS C:\> mkdir agent ; cd agent
```

と表示されていますが、作業ディレクトリのルートに移動する必要があります。
今回は以下のような作業ディレクトリで設定します。

```
F:\DevOps\agent
```

エージェントプログラムは上記のディレクトリに展開されます。

```PowerShell
PS F:\> mkdir DevOps ; cd DevOps
PS F:\DevOps> mkdir agent ; cd agent
```

次に先程ダウンロードしたエージェントプログラムを展開します。
とは言え、表示されている内容をそのままコピペするだけで構いません。

```PowerShell
PS F:\DevOps\agent> Add-Type -AssemblyName System.IO.Compression.FileSystem ; [System.IO.Compression.ZipFile]::ExtractToDirectory("$HOME\Downloads\vsts-agent-win-x64-2.204.0.zip", "$PWD")
```

しばらく待つとファイルが展開されますので次の指示を実行します。

```PowerShell
PS F:\DevOps\agent> .\config.cmd
```

そうすると設定プログラムが起動します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/013e89e3-d05f-ad47-c2f1-4b2b409e8f5a.png)

ここでは必要項目を入力します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/c4cf79d7-a6c9-8fbd-3ea6-a7c268e16a44.png)

今回の設定は以下となります。

|設定項目|設定値|
|:--|:--|
|Enter server URL|https://dev.azure.com/[Organization]|
|Enter authentication type|PAT (そのままエンターで空行)|
|Enter agent pool|UE_Build_Agent|
|Enter agent name|端末名 (そのままエンターで空行)|
|Enter work folder|_work (そのままエンターで空行)|
|Enter run agent as service? (Y/N)|Y|
|Enter User account to use for the service|そのままエンターで空行|
|Enter whether to prevent service starting immediately after configuration is finished?|N (そのままエンターで空行)|

今回は Windows のサービスとして自動実行を有効にしています。
サービスとして実行しない設定にした場合、自前で `.\run.cmd` を実行する必要があります。

無事に起動すると先程のエージェント一覧画面では以下のようになっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/6e42472a-2e66-e437-808c-49687b74eef8.png)

設定直後は『Online』と表示されている箇所が『Offline』の可能性もありますが、しばらく経つと『Online』に切り替わります。
もし、切り替わらない場合はビルドマシンを再起動してみてください。

以上で自動ビルドを行う端末をセットアップするが完了です。

# Azure DevOps Pipelines でビルドを自動化する

では、次は UE プロジェクトをリポジトリにインポートしたいと思います。

## Repos からクローン

Repos からのクローンはサイドバーから『Repos』を選択するとデフォルトブランチの `main` が選択されていますので、右上の『Clone』から URL を取得します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/119ec775-9557-33c5-e555-da1fcca97853.png)

Clone Repository ウィンドウが開きますので、URL をコピーするかクローンする IDE を選択することが出来ます。
今回は『Visual Studio』を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/c9fe23b4-1416-a761-3755-729e7b5fbd8a.png)

インストール済みの Visual Studio でクローンの画面が表示されます。
以下のような認証画面が開く場合があるかもしれませんが、必要な認証を行います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/692cda90-5b45-18ac-e0fc-ef7c6e43abcc.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/1eabd535-508c-44ef-6807-7753a6470cf8.png)

無事にクローンが出来ました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/e8d4ae62-05a3-aad3-9208-230af543fe97.png)

UE プロジェクトをインポートします。
インポートの方法はディレクトリ配下にあるファイルやディレクトリ一式をコピーするだけです。
Azure DevOps 側の Repos で UE プロジェクトが正常にインポートされていることが確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/823f3170-a55d-1461-4320-6fee1d375b09.png)

## 自動化を試してみる

Azure DevOps の自動化のロジックは YAML ファイルによって記述します。
この YAML ファイルはプロジェクトを同じディレクトリに配置 (ルートディレクトリ) し、必要な処理を書いていくことになります。
まずは簡単な自動化をしてみたいと思います。

### YAML ファイルを追加する

Visual Studio のソリューションエクスプローラー上で新しく『azure-pipelines.yml』を追加します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/cd8b2b7b-3442-28d3-3e7a-9505f246d886.png)

作成した YAML ファイルを開いてまずは以下の内容を記載してください。

```yml
trigger:
- main
pool: 'UE_Build_Agent'
jobs:
  - job: UE

    steps:
    - checkout: self
      clean: true
```

上記のファイルを保存し、ファイルをコミット＆プッシュします。

### YAML ファイルを Pipelines で実行させる

次は Azure DevOps の Pipelines を開きます。
サイドバーから『Pipelines』を選択すると以下のような画面になりますので、中央にある『Create Pipeline』をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/6d06207a-58dd-147f-7fa8-5c66e966d861.png)

以下のような画面が表示されますので、今回は一番上の『Azure Repos Git』を選択します。
画像からも分かる通り、Azure Repos Git 以外でもソースコード管理では利用することが可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/4bd8d2f0-34e0-2e60-c924-259b1b94ac8c.png)

次はリポジトリ選択です。
一つしか作成していませんので『UE』を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/fca6b8a1-07de-f268-fd5f-810dad9de309.png)

そうすると次の画面では自動的に先程コミットした『azure-pipelines.yml』が表示されます。
画面の右上にあるボタン『Run』を実行すると自動化のプログラムを手動で動かすことが出来ます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/98688f12-5019-79a1-cd10-63a3dbe687c2.png)

実行すると以下のような画面になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/8ceacd63-88ee-3fb4-6391-851296e10683.png)

ただ、この画面では下の方で『Azure DevOps for UE』の左側に青色時計が表示されているはずです。
これはパイプラインが待機状態となっています。
画面更新すると以下のような画面になると思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/7f700e38-6127-4e6f-3225-7876bd657320.png)

この状態はパイプラインのパーミッションの設定が出来ていない状態ですので右側にある『View』ボタンをクリックして設定を行います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/c10f55ed-bd2a-44f0-a157-f4a001b5c94a.png)

『Waiting for review』というウィンドウが開くと思いますが、これは事前に設定しているエージェントプールをこのパイプラインで使用してもよいかの確認待ち状態になっていますので『Permit』をクリックして許可します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/f31a1c83-69b6-c638-674c-6c85cb49aff0.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/cf46899f-ac3c-3c3c-2ff7-919ce10f1e6a.png)

と表示された後、先程は青色時計だった部分が緑のチェックに変わっていると思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/7ada581d-45d7-382b-0b8d-8d55020262a6.png)

これで自動化のための事前設定が完了している状態です。

パイプラインの中身の説明をしていませんでしたので説明をしたいと思います。
今回の内容は簡単に言うと『リポジトリにコミットされるとチェックアウトする』だけのパイプラインです。

```yml
# Repos の main ブランチにファイルがコミットされた時にトリガーする
trigger:
- main

# パイプラインを走らせるエージェントプールは『UE_Build_Agent』を利用する
pool: 'UE_Build_Agent'

# ジョブを定義しジョブの名前は『Auzre DevOps for UE』とする
jobs:
  - job: 'UE'
    displayName: 'Azure DevOps for UE'

    # ジョブのステップ
    steps:
    # 自分自身のリポジトリからチェックアウトする
    - checkout: self
      clean: true
```
`pool` の `name` にはエージェントプール名を指定しています。
`jobs` には複数のジョブのグループを記述しますが、今回は一つのジョブで全てが完了するため一つのジョブを記載します。
`job` に名前をつけますが、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/70219a32-1687-a6c2-3011-365d6b2c5210.png)

## UE のビルド

では、ここから UE によるビルドを行いたいと思います。

### AutomationTool

UE のビルドは AutonationTool を利用します。

https://docs.unrealengine.com/4.27/ja/ProductionPipelines/BuildTools/AutomationTool/Overview/

AutomationTool は以下のフォルダに配置されています。

```
<UE Path>\Engine\Build\BatchFiles\
```

`<UE Path>` は各自のインストールしたディレクトリやドライブによって変わります。

### AutomationTool を YAML で記述する

それでは AutomationTool を YAML で呼び出すコードを追加した内容を記述します。

```yml
trigger:
- main
pool: 'UE_Build_Agent'
jobs:
  - job: UE
    displayName: 'Azure DevOps for UE'

    steps:
    - checkout: self
      clean: true

    # 以下、追記したコード
    - script: |
        "E:\Epic Games\UE_5.0\Engine\Build\BatchFiles\RunUAT.bat" BuildCookRun -project="$(Build.SourcesDirectory)\UE.uproject" -platform=Win64 -clientconfig=Development -noP4 -cook -allmap -build -pak -partialgc -stage -staginddirectory="$(Build.BinariesDirectory)" -archive archivedirectory="$(Build.ArtifactStagingDirectory"
```

上記が AutomationTool を呼び出すコードです。
はい、ものすごく長いコマンドですね…。

では、この状態でとりあえずコミットします。
そうすると Pipelines がコミットをトリガーにして走り出していると思いますが、今回は AutomationTool の起動が確認できると思います。
`CmdLine` というのが追加されていると思いますが、こちらが AutomationTool が走っている状態です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/41e15c4f-7157-46d4-474c-ccf26ffec018.png)

## 環境変数を設定する

前章では AutomationTool を使うコードを書きましたが、パスを直書きしていましたので、環境によって変わるパスなどに対応できませんでしたので、その部分を環境変数に置き換えたいと思います。

Azure DevOps では端末に割り当てられている環境変数とは別に Pipelines 内でのみ有効な環境変数を `variables` で定義することが可能です。
環境変数を使用する理由は…

- 同じパラメーターを変数にすることで使いまわしが出来るようにする
- ハードウェアごとに違う設定を吸収する（パスなど）

が上げられます。

それではコードを以下のように書き換えてください。

```yml
trigger:
- main
variables:
  PROJECT_NAME: UE
  TARGET: Win64
  CONFIGURATION: Development
pool: 'UE_Build_Agent'
jobs:
  - job: UE
    displayName: 'Azure DevOps for UE'

    steps:
    - checkout: self
      clean: true

    - script: |
        "E:\Epic Games\UE_5.0\Engine\Build\BatchFiles\RunUAT.bat" BuildCookRun -project="$(Build.SourcesDirectory)\$(PROJECT_NAME).uproject" -platform=$(TARGET) -clientconfig=$(CONFIGURATION) -noP4 -cook -allmap -build -pak -partialgc -stage -staginddirectory="$(Build.BinariesDirectory)" -archive archivedirectory="$(Build.ArtifactStagingDirectory"
```

今回の修正では特に前回の内容と結果は変わらないと思いますが以下の環境変数が追加されています。
それと前回も実は出ていた環境変数の説明も合わせてしたいと思います。

### 定義済み変数

環境変数とは少し違うのですが Pipelines では『定義済みの変数』があります。
先の例で出てきていましたが `$(Build.SourcesDirectory)` などです。
`Build` には様々なパラメーターがありますが、今回は `Build.SourcesDirectory`、`Build.BinariesDirectory`、`Build.ArtifactStagingDirectory` を使用しています。

それぞれの変数の説明を以下に記載します。

|変数名|説明|
|:--|:--|
|`Build.SourcesDirectory`|ソース コード ファイルがダウンロードされるエージェントのローカルフルパス。例: `c:\agent_work\1\s`|
|`Build.BinariesDirectory`|コンパイル済みバイナリの出力フォルダーとして使用できるエージェントのローカルフルパス。例: `c:\agent_workd\1\b`|
|`Build.ArtifactStagingDirectory`|成果物がコピー先にプッシュされる前にコピーされるエージェントのローカルフルパス。例: `c:\agent_work\1\a`|

他のパラメーターは以下を参照してください。

https://docs.microsoft.com/ja-jp/azure/devops/pipelines/build/variables?view=azure-devops&tabs=yaml#build-variables-devops-services

### 環境変数

これは事前にシステムに設定しておくか `variables` によって定義します。
今回の説明では『プロジェクト名』『ビルドターゲット』『構成』を環境変数化して、切り替えを行えるようにしています。

ただ、今回の内容は YAML ファイルに直接記載していますので、コミットし直しが必要になります。
コミットせずに変更したい場合がありますが、その場合は Pipelines で設定を行うことが可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/48999ba6-df73-eb11-01c1-742169a4eddf.png)

『Edit』を選択することで右上に『Variables』という項目がありますが、こちらから設定が可能になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/bc8025b0-4ca0-b3a4-f47f-3a524b148b8a.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/4ea3fda2-d70c-8fb1-b27e-9f3a0542b17a.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/fb6e8378-e410-f2bf-f089-7426d78bfa02.png)

順に進んでいくと環境変数名とその値を指定可能です。
今回は `TARGET` に `Win64` を設定しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/4e9d8cff-0fca-7475-6bb9-cc739c61449d.png)

これで `TARGET` は Pipelines の設定に含まれましたので YAML ファイルから削除できますので、削除してコミットしてみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/7e87bc34-362e-399a-5ac0-8bca59a9e291.png)

無事に設定されているのが確認できると思います。

### システム環境変数

では、次に『システム環境変数』を設定します。
今回は UE を使用していますが、UE のインストールディレクトリは端末ごとに違う可能性がありますので、それを端末側で設定したいと思います。

とは言え、これはこれまでに環境変数を使ったことがある人がいれば、全くそれです。
システム環境変数の設定に設定するだけです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/72bdf3ba-478e-4333-b453-14e11135dcc7.png)

システム環境変数に `UE_PATH` と `UE_BATCH_FILES_PATH` を設定しています。
私の環境では UE は `E:\Epic Games\UE_5.0` にインストールされていますので、そのパスを設定しています。
`UE_BATCH_FILES_PATH` には UE のルートディレクトリからの相対パスを指定します。

これを YAML に適用します。

```yml
trigger:
- main

variables:
  PROJECT_NAME: UE
  CONFIGURATION: Development

pool: 'UE_Build_Agent'

jobs:
  - job: 'UE'
    displayName: 'Azure DevOps for UE'

    steps:
    - checkout: self
      clean: true
    
    - script: |
        "$(UE_BATCH_FILES_PATH)\RunUAT.bat" BuildCookRun -project="$(Build.SourcesDirectory)\$(PROJECT_NAME).uproject" -platform=$(TARGET) -clientconfig=$(CONFIGURATION) -noP4 -cook -allmap -build -pak -partialgc -stage -staginddirectory="$(Build.BinariesDirectory)" -archive archivedirectory="$(Build.ArtifactStagingDirectory"
```

`RunUAT.bat` の部分が置き換わりました。
これをコミットします。

**※システム環境変数の変更はシステムの再起動が必要になりますので注意してください。**

これで複数のエージェントを登録した場合でも環境変数に `UE_BATCH_FILES_PATH` を設定しておけば、YAML ファイルの更新の必要がなくパスの切り替えが行われます。

以上で UE5 のビルドの自動化が完了となります。

# まとめ

Azure DevOps では Self-hosted で完了を作ってしまえば、あとは YAML スクリプトでターミナルを実行するのと同じような簡単さで自動化をカスタマイズできますので、自動化を検討されている方は Azure DevOps を選択肢に入れて見てはいかがでしょうか？