kkamegawa's weblog

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

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

Linuxビルドエージェントを構成する

.NET - Powerful Open Source Development

Linuxのディストリビューションごとに手順が違うので、注意してください。私はUbuntu Server 16.04 LTSでやっています。

ビルド定義を作る

Windows版と同じ感じで作ります。

f:id:kkamegawa:20160919120826p:plain

違うのはZipパッケージの作成と、リリース用PowerShellスクリプトの代わりにシェルスクリプトが用意されていることですね。タスクはほとんどUtilityにある、Shell Scriptを使用します。

シェルスクリプトとタスクの単位

dotnet restore/buildのように連続するタスクは一つのシェルスクリプトで実施してもかまわないのでしょうが、個人的にはビルドタスク単位で別にしたほうがわかりやすいかと思います。

作成したシェルスクリプトはSolutionフォルダ内に適当なシェル用のフォルダを作って入れておくといいでしょう。

NuGetパッケージのリストア

NuGetパッケージのリストアに必要なシェルはこのようになります。

#!/bin/sh  
/usr/bin/dotnet restore  

パッケージリストア用のシェルスクリプトはテストプロジェクトでも使用できるので、使いまわしてください。

プロジェクトのビルド

ビルドに必要な最低限のシェルはこのようになります。

#!/bin/sh
/usr/bin/dotnet build -c $BUILDCONFIGURATION

$BUILDCONFIGURATIONはVariablesに定義された値です。Variablesでは大文字小文字があるように見えますが、bashではこの定義済みの値は全て大文字として定義されています。

f:id:kkamegawa:20160919141406p:plain

テストプロジェクトの実行

テストプロジェクトにあるテストを実行するにはこのようなスクリプトを実行します。テストプロジェクトを実行する前に必ずNuGetパッケージのリストアタスクをテストプロジェクトのフォルダで実行してください。

#!/bin/sh
/usr/bin/dotnet test -xml Test-Result1.xml

Windowsのビルド定義のところでも書きましたが、-xmlオプションでXMLファイルにテスト結果を出力します。複数のテストプロジェクトの結果をマージする場合、この引数はシェルスクリプトの引数として外出できるようにしてください。

パッケージを出力する

特定のプロジェクトをWebサーバーへデプロイするための最低限のスクリプトはこのようになります。

#!/bin/sh
/usr/bin/dotnet publish src/{プロジェクト名} --configuration $BUILDCONFIGURATION --output $PUBLISHOUTPUT  --framework $NETCOREVERSION

$PUBLISHOUTPUTは出力先フォルダを定義した値です。これもWindows版と同様に、システムに.NET Coreがインストールされているという前提のパッケージです。

Windows版にも書きましたが、必ず--configurationでreleaseと指定して、Release版をデプロイしてください。

場合によってはここで一気にデプロイまでやってもいいのですが、別にしています。

まとめ

Windows版と同様ですが、タスクごとにシェルスクリプト作らないといけないのが少し面倒かもしれませんね。外部にビルドサーバーが必要になるし、どうしてもLinuxでなくてはならないビルドを行う以外はHostedエージェントを使ったほうがいいように思います。
次はリリースについて紹介します。

.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で共有フォルダにコピーする場合、独自のビルドエージェントからになるでしょうね。

プログラマ的にWindows 10 Anniversary Updateのうれしいところ

10個あるかな、と思ったのですが、今のところ思いついたものをあげてみました。うーん、まだあるはずなんですが。とりあえず、つらつらと書いてみます。Inkとかは純粋にプログラマ向けとしてどうかなーと思って、あえて入れていません(ぉ)。

他にもお気に入りの機能があれば紹介してください。

Docker互換のコンテナ

言わずと知れたこれですね。Docker for Windowsを使えば現在でも使えます。

docs.docker.com

ただ、こちらはHyper-VでLinux仮想マシン(初期で2GB )が動くので、少しメモリがきつい。なによりもWindowsで動くコンテナであればWindowsネイティブの機能を使うことになります。

msdn.microsoft.com

コマンドはdockerコマンドで共通のようです。PowerShellコマンドレットも用意されるようですが、基本はdockerコマンドで、詳細な情報を見たいときはPowerShellという住み分けになるようです。

MAX_PATHが260バイトの制限から解き放たれる

実は今までもファイル名のprefixに\\?\とつけて、UnicodeでコンパイルしたWin32アプリケーションであれば、64KBまでのパスを使えることができました。しかし、ExplorerがWindows 95時代からのANSIモードで動いていたり、世の中MAX_PATHが260バイトという決め打ちで動いていたり、.NET FrameworkもWindows 95とかを引きずっていた都合上、最大パスは260バイトまで、となっていました。

Anniversary Update以降、グループポリシーでEnable NTFS long pathsを有効に設定すれば、Win32アプリケーションでも有効になります。もちろん、MAX_PATHが260と決め打ちしているような大多数(99.9999%くらい?)のアプリケーションに長いパスを与えると即死、もしくはバッファオーバーフロー起こすので、十分評価してからにしましょう。

betanews.com

Desktop ConverterでWin32/.NETアプリケーションの簡単展開

既存の.NETアプリケーションやWin32アプリケーションにUWPのガワだけかぶせて、ストアでより簡単に配信ができるようになるというDesktop Converterです。間違えないで欲しいのは、あくまでも「ストアに公開できるようになる」というだけで、「UWP化される(mobileやXBoxで動くようになる)わけではありません

ただし、何でもかんでもコンバートできるわけではなく、制限があります。特にVisual C++ランタイムと.NET Frameworkが限られるので、古いVCランタイムを使っているアプリケーションの場合、一度移行してから、ということもあるので、注意してください。

Convert your desktop application to a Universal Windows Platform (UWP) app

UACで特権昇格が必要なアプリや、他のアプリと連携する(AppDataに書き込む)ようなアプリがダメ、というのはややきついものの、大多数のアプリケーションでは問題無いでしょう。ただし、その前にインストーラーでインストールされるようなアプリケーションでなくてはなりませんが。

インストーラーがないようなアプリの場合、コンテナ使うしかないですかね。

ネットワークが高速化

ネットワークは門外漢ですが、Linuxなどではすでに対応している新しいRFCもしくはドラフトの規格に対応しているそうです。TFOとかは素人目に見ても頻繁にopen/closeするようなサーバにアクセスする場合の高速化が見込まれると思われます。

blogs.technet.microsoft.com

PowerShell (WMF 5.1)

WMF 5.1 リリース ノート (プレビュー)

Bashに持って行かれた感がありますが、Windows における自動化、スクリプトでの運用管理を行いたい場合はWMF(PowerShell)なのは変わりません。いろいろ聞かれましたが、Bashは(今のところ)Windows 10を開発者モードに変更しないと使用できません。つまり、Bashは管理者がシステム管理のために使うのではなく、あくまでも開発者向けのツールセットの一部となっています。

PowerShellはWindowsクライアントおよびサーバの管理、自動化のためのものです。

PowerShell 5.0 にあったバグや、高速化、PowerShell DSCをはじめとした機能強化が盛りだくさんです。

.NET Framework 4.6.2

先ほどWin32アプリケーション向けの長いファイル名を扱うようにする設定を紹介しましたが、.NETの場合はapplication manifestに指定することにより、プロセス単位で制御することが可能です。

<?xml version="1.0" encoding="utf-8" ?>  
 <configuration>
  <runtime>
    <AppContextSwitchOverrides value="Switch.System.IO.UseLegacyPathHandling=false;Switch.System.IO.BlockLongPaths=false" />
  </runtime>
</configuration>

.NET Coreおよび、.NET Framework 4.6.2がインストールされたWindows 10 Anniversary Update(1607)で有効だそうです。

blogs.msdn.microsoft.com

長いファイル名の他にもモニタごとのDPIを認識するようになったとか、新しい暗号化に対応したとか、着実な強化が行われています。

blogs.msdn.microsoft.com

Bash on Ubuntu on WindowsでツールセットがLinux共通に

//Build 2016での話題は間違いなくこれだったでしょうね。cygwinとかもまぁいいのですが、なんとなくもどかしさを感じていました。PowerShellのすべてがオブジェクトになるというのは.NETなどの相互運用で大変便利です。

しかし、他のプラットフォームの方に使ってもらおうとする場合、そのへんが足かせにもなっていました。移行のためにコマンドレットにエイリアスを登録されているものもある(lsやwgetとか)のですが、結局オプションが違うから使わないんですよね。

あと、長いファイル名の扱いも、UnicodeアプリであったとしてもWindowsだから260バイト固定とかになっているものも少なからずあり、困っていました。node.jsもしばらく困ったなぁ…。

しかしそんな時代もさようなら。パスさえ少し考慮すればUbuntuで動いているものがまぁ大体動くようです。もちろんまだ実装されていないシステムコールや実装されないであろうシステムコールもありますが、コマンドラインの開発用ツールセットは割りと動くようですね。

blogs.msdn.microsoft.com

詳細な仕組みなどは上記のブログで。もしも困る場合はGitHubにissueをたててみればいいようです。

github.com

UWPアプリのバックグラウンド実行サポート

通知ではなく、バックグラウンドで実行したいような場合よさそう?

blogs.windows.com

VSTSの新ビルドで単体テスト結果を確認する

ASP.NET MVC(.NET Framework 4.6)のプロジェクトをVisual Studio Team Servicesでビルドしたいとします。作成したデフォルトのビルド定義には単体テストを実行するタスクがあり、有効にしています。

f:id:kkamegawa:20160316220108p:plain

しかし、ビルドしても、このようにテスト結果が表示されません。もちろんローカルでは表示されます。これはどういうことでしょうか?

f:id:kkamegawa:20160316220110p:plain

原因はvstestに指定するターゲットフレームワークの指定がFramework4(.NET 4)になっているからじゃないかな、と思います。ビルドタスク内のTestのAdvanced Execution OptionsのOther Console Optionsに"/UseVsixExtensions:false /Framework:framework45"と指定してください。

f:id:kkamegawa:20160316220109p:plain

こんな感じ。/UseVsixExtensionsはVSIXの拡張機能を使用しない、という指定です。コンソールで実行するテストのときあっても意味がないので無効化しています。

f:id:kkamegawa:20160316220111p:plain

ビルド後、単体テスト結果やカバレッジ結果が正しく表示されるようになりました。この指定はRun Settings Fileに指定したテスト構成ファイルでもできるはずなのですが、リポジトリに追加するのも面倒なので、実行時引数に指定しています。

VSTest.Console.exe のコマンド ライン オプション