しばやん雑記

Azure とメイドさんが大好きなフリーランスのプログラマーのブログ

GitHub Actions / Azure Pipelines の Windows Runner で Azurite と Cosmos DB Emulator を利用する

以前に Azurite と Cosmos DB Emulator を使って GitHub Actions / Azure Pipelines でテストを実行する方法を書きましたが、Ubuntu Runner と Service Containers を利用した方法だったので Windows Runner では実質的には使えない方法でした。

理由としては Azurite の Windows 向け Docker Image が公開されていないのと、Cosmos DB Emulator を Windows Containers で動かすのは Linux の数倍時間がかかるためです。

今回は Windows Runner 上で Azurite と Cosmos DB Emulator を利用する方法を確認したのでまとめます。

Azurite を利用する

Azurite 自体はクロスプラットフォームなので Windows Runner でも問題なく動作しますが、前述したように Windows 向けのイメージが公開されていないので、npm を使ってインストールする形になります。

Azure Pipelines で Azurite を使う方法はドキュメントで紹介されていますが、Ubuntu 上で動かす前提となっているので Windows Runner にそのまま持っていくことは出来ません。具体的にはプロセスをバックグラウンドで動かす部分ではまります。

実行時に利用するシェルとして bash を選べば動く気はしますが、今回は古典的な start コマンドを利用する方法でバックグラウンド実行を行います。

npm install -g azurite
mkdir azurite
start azurite --silent --location azurite --debug azurite\debug.log

これで Azurite は別の cmd 上で実行されるので、後続の処理を実行できるようになります。

Cosmos DB Emulator を利用する

Ubuntu Runner では Cosmos DB Emulator の Docker Image を利用して実行しましたが、Windows Runner では Cosmos DB Emulator がインストールされているので、それを利用するのが手っ取り早いです。

ただし単純にインストールされているだけなので、Cosmos DB Emulator の起動は手動で行う必要があります。今回は以下のドキュメントにある管理用のコマンドレットを利用しました。

コマンドレットなので PowerShell 上で動かす必要がありますが、`Import-Module` 後に `Start-CosmosDbEmulator` を実行するだけなので非常に簡単です。

Import-Module "$env:ProgramFiles\Azure Cosmos DB Emulator\PSModules\Microsoft.Azure.CosmosDB.Emulator"
Start-CosmosDbEmulator

Cosmos DB Emulator 自体の起動にそこそこ時間がかかるので、その点だけは注意が必要です。起動に 240 秒以上かかるとタイムアウトで失敗になるので、若干の不安は残ります。

Azurite と Cosmos DB Emulator を Docker 使わずに利用する方法は確認出来たので、後は GitHub Actions と Azure Pipelines 上に持っていくだけですが、それぞれで少しはまりポイントがありました。

GitHub Actions を使う例

早速 Workflow 定義を載せてしまいますが、注意するポイントとしては GitHub Actions の Windows Runner ではデフォルトのシェルが PowerShell になっていることです。mkdirstart コマンドは PowerShell のコマンドレットのエイリアス扱いになっているので、cmd とは挙動が異なります。

name: Emulator

on:
  push:
    branches:
      - master

  workflow_dispatch:

jobs:
  build:
    runs-on: windows-latest
    steps:
    - uses: actions/checkout@v3

    - run: |
        npm install -g azurite
        mkdir azurite
        cmd /c "start azurite --silent --location azurite --debug azurite\debug.log"
      name: Install and Start Azurite

    - run: |
        Import-Module "$env:ProgramFiles\Azure Cosmos DB Emulator\PSModules\Microsoft.Azure.CosmosDB.Emulator"
        Start-CosmosDbEmulator
      name: Start Cosmos DB Emulator

    - run: dotnet test
      name: Run dotnet test

Azurite の起動には start コマンドを使っていますが、PowerShell の場合は実行するファイル名とパラメータを別で指定する必要があるので、元のままだとエラーになります。

この辺りの対応をするのは面倒なので、明示的に cmd を使って実行させるようにしています。デフォルトが PowerShell なので Cosmos DB Emulator の起動に関してはそのまま書けます。

この Workflow でテストコードを実行させると、問題なく通っていることが確認出来ます。

手元で何回か実行させてみたところ、Cosmos DB Emulator に関しては 240 秒の制限に引っかかってしまい、エラーとなるケースがありました。パラメータの調整で改善できる可能性はありますが、可能な限り Ubuntu Runner を使いたいところです。

Azure Pipelines を使う例

今度は Azure Pipelines になりますが、Runner のイメージは GitHub Actions と共通なのでほぼ同じ定義になります。こちらはデフォルトのシェルが cmd なので start コマンドはそのまま使えますが、複数行コマンドを書いた場合の挙動が GitHub Actions とは異なっていました。

具体的には start コマンドで起動したはずの Azurite が実際には起動されていないという現象が発生しました。Azure Pipelines では複数行の場合はバッチファイルが生成されてから実行されるので、その処理の関係で挙動が変わっていそうです。

trigger:
- master

pool:
  vmImage: windows-latest

steps:
- script: |
    npm install -g azurite
    mkdir azurite
  displayName: Install Azurite

- script: start azurite --silent --location azurite --debug azurite\debug.log
  displayName: Start Azurite

- powershell: |
    Import-Module "$env:ProgramFiles\Azure Cosmos DB Emulator\PSModules\Microsoft.Azure.CosmosDB.Emulator"
    Start-CosmosDbEmulator
  displayName: Start Cosmos DB Emulator

- script: dotnet test
  displayName: Run dotnet test

その問題に対応するために、Azurite の起動だけを独立した script として定義しました。これで GitHub Actions の時のように Azurite がバックグラウンドで起動するようになりました。

Cosmos DB Emulator の起動には例によって PowerShell が必要なので、組み込みの powershell 定義を使ってコマンドレットの呼び出しを書いています。

この Pipeline 定義を使ってテストコードを実行すると、時間はかかりますが問題なく通るので、Azurite / Cosmos DB Emulator の起動に成功していることが分かります。

面白い結果として今回試した範囲では、Azure Pipelines の方が Cosmos DB Emulator の起動が高速でした。

VM のスペックは変わらないはずなので、このような差が生まれている理由がいまいち分かりませんが、Cosmos DB Emulator を Windows Runner で使う時には Azure Pipelines の方が有利かも知れません。