kkamegawa's weblog

Visual Studio,TFS,ALM,VSTS,DevOps関係のことについていろいろと書いていきます。Google Analyticsで解析を行っています

.NET CoreアプリをVSTSで継続的インテグレーションする(Windows版)

はじめに

昨日dotnetConf関西で行ったセッション資料ではCI/CDの細かいやり方はのせていませんでしたので、ブログで詳細の解説を行います。 CIそのものはメニューのBuild & Releaseから構築します。この記事では新しいUIで説明していますが、以前のUIでもあまり関係ありません。
長くなったので、Linux版は別にします。

VSTSとビルドエージェント

VSTSには内蔵のビルドエージェント(Hosted Agent)があります。Hostedは今のところWindowsのエージェントのみになっているので、LinuxやMac環境でビルドする場合、独自のビルドサーバーを用意する必要があります。
ビルドエージェントは一台までであれば無料で接続できます。httpsのoutboundだけ通信できていればいいので、Firewallがある環境でも大体大丈夫です。

有料($15/月)支払って、一つのプールに二台以上のビルドエージェントを運用すると、並列でビルドができるようになります。並列可能ということ以外にも、エージェントを占有するので、占有しているエージェントではリポジトリのクローンが頻発しなくなるはずです。
原則1台1エージェントですが、登録するときにエージェントの名前を変えれば、一台のサーバーに複数のエージェントが登録できます。例えば、TFSとVSTSそれぞれ登録するとかもできます。サーバーの性能次第ですが、複数のVSTS/TFSを使っているときは試してみてください。

エージェントの対応OS

  • .NET CoreがサポートするWindows
  • Ubuntu 14.04/16.04(サービスとして動かす場合は16.04必須)
  • Red Hat Enterprise Linux 7.x
  • OS X 10.10/10.11

TFS 2015に接続する場合、WindowsではTFSに付属しているエージェントを使ってください。TFS "15"ではPAT(Personal Access Token)をサポートするので、.NET Core版のエージェントが使用可能になります。
VSTSのエージェントはソースも公開されています。

github.com

Windows(Hosted)で.NET Coreアプリをビルドする

では、実際にビルド定義を作ってみましょう。ASP.NET Core MVCアプリケーションを作ってコミットしておきます。
Visual Studioのテンプレートを使ってもいいですが、大部分を削除することになります。

NuGetの復元タスクを追加

f:id:kkamegawa:20160919120827p:plain

Add build stepからUtilityにあるCommand Lineを追加します。

NuGetパッケージを復元する
Tool: "c:\Program Files\dotnet\dotnet.exe"
Arguments : restore Working Folder : Project.jsonのあるフォルダ

ビルドタスク

ビルド用のCommand LineをAdd build stepで追加します。

Tool: "c:\Program Files\dotnet\dotnet.exe"
Arguments : build -c $(BuildConfiguration) Working Folder : Project.jsonのあるフォルダ

※:BuildConfigrationはVariablesでreleaseと作っておいてください(Visual Studioのテンプレートから作った場合は作られています)

f:id:kkamegawa:20160919141406p:plain

テストプロジェクトのNuGetパッケージを復元する

テストプロジェクトのNuGetパッケージ復元のCommand LineをAdd build stepで追加します。

Tool: "c:\Program Files\dotnet\dotnet.exe"
Arguments : restore Working Folder : テストプロジェクトのProject.jsonがあるフォルダ

テストの実行

テスト実行用のCommand LineをAdd build stepで追加します。

Tool: "c:\Program Files\dotnet\dotnet.exe"
Arguments : test -xml TestResult.xml Working Folder : テストプロジェクトのProject.jsonがあるフォルダ

Visual Studioでビルドする場合と異なり、プロジェクト単位でdotnet restoreを実行する必要があるので気を付けてください。

-xml にはテスト結果を出力するxmlファイルを指定します。テストプロジェクトごとに異なる名前にしてください。後で集計することができなくなります。

dotnetコマンドはフルパスで指定しなくても実行できますが、ビルド時に警告が出るので、フルパスを指定するほうが無難です。

テスト結果をVSTSにアップロード

f:id:kkamegawa:20160919120828p:plain

Add build stepで"Publish Tests Results"タスクを追加して、ビルド結果をVSTSにアップロードします。VSTEST以外にもXUnit,NUnit,JUnit(Javaなので.NET Coreには関係ないですが)などに対応しています。

f:id:kkamegawa:20160919142327p:plain

テスト結果をVSTSにアップロードすると、このようにテスト結果の品質を追跡することができます。

LnuxもしくはOS/Xでビルドする場合、出力するXMLファイル名の大文字小文字に気を付けてください。

コードカバレッジも取れるはず…Visual Studioでは取れていますが、VSTSでは集計されていません。これは少し調査します。

パッケージの出力

パッケージ出力用のCommand LineをAdd build stepで追加します。

f:id:kkamegawa:20160919120829p:plain

出力パッケージを作ります。具体的にはproject.jsonで定義されているpublishの動作が実行されます。

docs.microsoft.com

Tool: "c:\Program Files\dotnet\dotnet.exe"
Arguments : publish src/{プロジェクト名} --configuration $(BuildConfiguration) --output $(PublishOutput) --framework $(NETCoreVersion)

注意点として、publishコマンドはデフォルトでデバッグ版を出力しています。--configurationで明示的にrelease版(ここではvariablesで指定しています)を指定してください。Azureではデバッグ版実行できない(エラーになる)はずなのですが、なぜかデバッグ版をデプロイしてもApp Serviceで動いてしまってます。長い間気づきませんでした。

Framework Runtimeは組み込むか、システムインストールを使用するかはご自由に。今回はシステム組み込みのランタイムを使用する前提でやっています。

f:id:kkamegawa:20160919142328p:plain

bin\$(BuildConfiguration)\ にあるアプリケーションの実体をコピーするタスクです。このタスクは非.NET CoreのASP.NET前提のタスクのようで、フォルダ構成をそのままコピーしてくれません。

IIS(Azure App Service)にデプロイする場合、これで問題ないのですが、Linuxにデプロイするとこのタスクでは実行時に「\bin\$(BuildConfiguration)\netcoreapp1.0\モジュール名」が存在しないというエラーになります。

特別にタスクを作るか、project.jsonのpublishOptionsにbin/releaseを含めるしかないように思います。今回はproject.jsonに入れています。あと、各種jsonファイルも入っていない場合、Linux(たぶんOS/Xも)実行失敗するので、jsonファイルを忘れないようにpublishOptionsに入れましょう。

  "publishOptions": {
    "include": [
      "wwwroot",
      "Views",
      "Areas/**/Views",
      "appsettings.json",
      "project.json",
      "bin/release",
      "web.config"
    ]
  }

リリース作業用PowerShellスクリプト追加

f:id:kkamegawa:20160919120830p:plain

ここはApp ServiceにリリースするためのPowerShellスクリプトをリリース成果物としてコピーするタスクですビルド時にデプロイするなら不要です。

WebDeploy用zipファイル作成

f:id:kkamegawa:20160919120831p:plain

IIS(Azure App Service)にwebdeployでデプロイする場合、zipパッケージを作っておく必要があります。webdeployを使わない場合は不要です。

VSTSにリリース成果物を登録

f:id:kkamegawa:20160919120832p:plain

最後に成果物をVSTSにコピーします。特定のファイル共有にコピーするか、VSTSに保存します。ファイル共有はUNCでVSTSもしくはビルドエージェントからアクセスできる必要があります。

UNCで共有フォルダにコピーする場合、独自のビルドエージェントからになるでしょうね。

PowerShell Users Groupのセッション資料公開

4/9のPowerShellユーザーグループでPowerShell DSCやAzureを使ってどうやってテスト環境を維持しましょうか、ということについてお話してきました。DSCそのものはあまり触れておりません(すいません)。テスト環境をクラウド上に置く、ということは考えるかと思いますがそれをどういう使い分けしようかみたいな話です。

これやるためにDevTest Labsを改めて使ってみたんですが、ちょっとまだまだこなれていないところがあるものの、初めてクラウド上に作るテスト環境としては、結構便利なものになる可能性を秘めていると感じました。

Azure DevTest Labsでテスト用仮想マシンを作るべき理由

Azure DevTest Labs | Microsoft Azure

まだプレビューですが、Azure DevTest Labsというサービスがあります。これはテスト用の仮想マシンの作成と管理に特化したサービスです。Azure 仮想マシンほど細かくいろいろ設定することはできないのですが、その分かなりお手軽になっており、ARMで作る仮想マシンと比べて以下のような利点があります。

テンプレートが異様に短い

最低限の仮想マシンでも大体これくらいです。診断の拡張機能や初期設定をしようとPowerShell DSCの拡張機能を入れるともっと長くなります。

azure-quickstart-templates/azuredeploy.json at master · Azure/azure-quickstart-templates · GitHub

対して、DevTest Labsで作る仮想マシンテンプレートはこんな感じ。実はこれでGitとAzure PowerShellが入ります。

Azure DevTest Labs Deploy sample script

PowerShell DSCを使わなくてもいろいろ入る

PowerShell DSCでリソース使えばもちろんいろいろ入るのですが、Azureで試行錯誤するのは結構大変です。DevTest Labsではデプロイ時についでにいくつかのソフトを追加できます。Chocolatyを指定できるので、パッケージを入れることや、Gitのリポジトリクローン、PowerShellスクリプトの実行、VSTSのdropフォルダのコピーとか便利ですね。

f:id:kkamegawa:20160405052244p:plain

JSONだとこの辺。

https://gist.github.com/kkamegawa/bfb437684d56f05bfa99308a6ca4f9ad#file-windowsvirtualmachine-json-L60

自動運転が最初から入っている

azure.microsoft.com

Azure Automationを使えば自動運転を設定することができますが、DevTest Labsでは最初から設定することができます。

f:id:kkamegawa:20160405052245p:plain

停止し忘れてクラウド破産とか(あるていど)防げそうです。通常は日中の自動運転でしょうが、例えば夜間に自動テストしたい、というような場合は夜間にのみ動くLabを作ればいいでしょう。

コスト上限の設定

仮想マシンを無制限に立てられると同じくクラウド破産になりそうですが、あらかじめユーザごとにいろんな上限を設定することができます。

  • 仮想マシン数
  • 仮想マシンのサイズ
  • DevTest Labs単位での仮想マシン数上限

まだ残念なところ1 - Visual Studioからの配置ができない

そのうち直るんでしょうが、残念ながらAzureのQuickStartから仮想マシンのテンプレートを流用して作った場合、配置ができません。Visual Studioの配置でStorageアカウントを指定するところがあるのですが、こんなのいらないので、削除したら配置ができなくなりました(てへっ)。

PowerShellから実行すればいいので、そんなに困りません。CIも大丈夫のはずです。

まだ残念なところ2 - Visual Studioのテンプレートがない

uservoiceに上がってるし、事実上New-AzureRmResourceGroupDeploymentひとつ発行するだけでいいので楽なんですが、やっぱり作ってほしいですねぇ。あと、テンプレートはDevTest Labsから仮想マシンを作ってView Templateでみればわかると思います。

まとめ

いくつかちょっと難しいとところもあるけど、ARMのテンプレートが圧倒的に小さく、追加インストールするソフトがある場合は助かります。テスト用の仮想マシンだとそんなに難しいものはいらないので、今後はこのDevTest Labsに仮想マシンを作っていこうと思います。

Apache JMeterで世界規模のデータセンターから負荷をかける

Visual StudioとVisual Studio Team Servicesを使えば、任意の(残念ながら日本はまだありません)Azureデータセンターから特定のWebサイトに負荷をかけることができます。

クラウドベースのロードテスト | Visual Studio Online

www.atmarkit.co.jp

負荷をかけるサイトはASP.NETに限らないのですが、Visual Studioを使わなければなりませんでした。ところが、先日のバージョンアップでApache JMeterにも対応しました。

blogs.msdn.microsoft.com

実際にやってみましょう。まず、簡単なJMeterの負荷シナリオを作っておきます。必ず最新版(2.13)を使ってください。

f:id:kkamegawa:20160319074557p:plain

Visual Studio Team ServicesのLoad TestからApache JMeter testを選びます。

f:id:kkamegawa:20160319074558p:plain

Target Scriptに作成したjmxファイルを指定します。

f:id:kkamegawa:20160319074559p:plain

Supporting Filesには負荷テストで使用するパラメータなどを格納したcsvファイルを指定します。今回は使ってないので指定しません。

あとはAgentの数、負荷の時間、どのデータセンターから実施するか、ということを選ぶだけです。Run Testを実行すればかまいません。しかし、実行するとこんなエラーが出ることがあります。

f:id:kkamegawa:20160319074600p:plain

VSTS Load Testでjmxが実行できない場合、この辺が理由になります。

  • jmxファイルの中身(テスト計画名など)に日本語を使わない
  • 「結果を表で表示」などのインタラクティブな出力を伴うリスナーを追加しない

JMeterを日本語UIで使うと自動的日本語が入ってしまうので、英語モードで使うことをお勧めします。

f:id:kkamegawa:20160319074603p:plain

負荷がかかり始めるまで結構待ちますが、終了するとこんな感じで結果が出ます。

f:id:kkamegawa:20160319074602p:plain

あとから参照することもできます。

f:id:kkamegawa:20160319074601p:plain

エラーはこんな風に見ることができます。ほんとはチャートを見せたかったのですが、JMeterのリスナーにファイル作成系のリスナーを追加しないといけないようです…すいません。

f:id:kkamegawa:20160319075659p:plain

Application Insightsを設定していたので、Application Insights側でも負荷結果を見ると、ちゃんとアクセスされていたことがわかります。

まとめ

VSTSの負荷テストは今までVisual Studioがないとできないものでしたが、よく使われているJMeterに対応したことで、パブリックなWebサイトに対して負荷をかけるときに使いやすくなったかと思います。月当たり20000ユーザまでは無料で使えるので、便利ですよ。