kkamegawa's weblog

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

C# 7.0のプロジェクトをVSTSで継続的インテグレーションする

前振り

という話があったので、ちょっと書いてみます。

C# 7.0プロジェクトを作る

f:id:kkamegawa:20170411062240p:plain

こんな風にC# 7.0の新機能であるタプルを書いてみます。

引用:ufcpp.net

もちろん素のVS2017ではエラーになるので、NuGetでValueTupleを追加します。

f:id:kkamegawa:20170411062239p:plain

ビルド定義作成

VSTSにプッシュしたら、VSTSのビルド定義を作ります。注意点は二つ。

  • Hosted AgentにVS2017を選ぶ
  • Visual Studio 2017を選択する。

f:id:kkamegawa:20170411062236p:plain

Visual Studio 2017を選びます。

f:id:kkamegawa:20170411062233p:plain

OptionsにあるエージェントからHosted VS2017を選びます。

ビルドしてみる

f:id:kkamegawa:20170411062231p:plain

Hosted VS 2017では成功します。

f:id:kkamegawa:20170411062254p:plain

普通のHosted Agentを選択すると失敗します。ちょっと前までVS2017というHosted Agentがなかったのですが、Side by Sideで動かすより、VS2017はしばしば更新されるから別にしたんでしょうかね。

Visual Studio Team Servicesに接続して開発する(6日目)

ようやく今日からVisual Studioをつないで開発を行います。

Gitリポジトリ

まず、VSTSにGitリポジトリを作成してからVisual Studioで接続します。

初期化

f:id:kkamegawa:20161205204215p:plain

最初はこのような画面が表示されます。既存のローカルリポジトリがあればそれをpushしてもいいですが、最初にVSTSで作ってからクライアントにcloneすれば.gitignoreの手間が省けます。

一番下にあるor initialize with a README or gitignoreにあるinitializeをクリックすれば指定したgitignore形式で作ります。

f:id:kkamegawa:20161205204214p:plain

注意点として、C#やVB.NETという設定はなく、Visual Studioになっています。

f:id:kkamegawa:20161205204212p:plain

cloneするためのツールも多く対応しています。.NET開発以外にもPhpStormやRubyMineとかにも対応しています。

f:id:kkamegawa:20161205204213p:plain

(あまりないかもしれませんが)GitHubなどの外部リポジトリから引っ越すこともできます。Requires authorizationにチェックすると、非公開な認証が必要なリポジトリもインポートできます。

f:id:kkamegawa:20161205204211p:plain

VSTS側で初期化した直後の状態です。.gitigonoreなどがあるので、このままクローンしてください。

f:id:kkamegawa:20161205204216p:plain

リポジトリのメニューを開いて、リポジトリ名のそばにある☆をクリックすると、該当リポジトリがお気に入りとして扱われ、アクセスしやすくなります。ほかの人が作ったリポジトリに素早くアクセスする場合に使ってください。

f:id:kkamegawa:20161205204217p:plain

一つのチームプロジェクトには複数(上限は非公表)のGitリポジトリを作ることができます。ビルドツールチェインはリポジトリ単位になるので、ある程度は分割したほうが便利でしょう。この辺はほかのGitサービスと考え方は変わらないはずです。

Gitセキュリティ設定

f:id:kkamegawa:20161205204218p:plain

歯車アイコンから、Securityハブを使用して、チームプロジェクトにアクセスできるユーザーもしくはグループを設定します。コードの編集権を付けるにはContributorsグループに追加します。

f:id:kkamegawa:20161205204208p:plain

チームプロジェクト内のリポジトリごとに設定することもできます。

f:id:kkamegawa:20161205204220p:plain

特定のブランチ(通常masterやリリース用のブランチ)にむやみやたらにpushされて、ビルドが通らなくなるというのはよくあることです。

そのような事故を防ぐためにブランチ単位でブランチポリシーという機能を使って、レビューやCIおよび、テストが通っていないコミットを拒否することができます。

まだビルドがないので、上記の画面ではビルドの指定ができていません(^^;。Require a new build if older than xx hoursというのは、Gitでは細かい単位でコミットを行うこともあります。

単なるtypoやCSSの色修正でビルドやテストを全部やっていたら時間がいくらあっても足りません。そこで、直近xx時間以内のビルドは許容する、という指定です。開発が活発になって、しょっちゅうコミットするような状態になったら検討したほうがいいでしょう。

f:id:kkamegawa:20161205204221p:plain

ブランチポリシーでレビュワーの指定ができます。この人(たち)がレビューしないとマージが行われません。

f:id:kkamegawa:20161205204219p:plain

ブランチの…をクリックすると、既定ブランチにするか、ブランチを誤って削除できないようにします。devとかpull request作った後も残っていてほしいブランチは指定するといいでしょう。

ブランチと作業項目を関連付ける

f:id:kkamegawa:20161204170815p:plain

ブランチはfeature,Backlog, Taskのいずれでも作成できます。機能レベルであれば、Backlogあたりで作るのがいいかもしれません。この辺りはいろいろ試行錯誤してルールを作ってみてください。タスクやissue単位でブランチを作るのもいいでしょう。

ブランチ名は / で区切ると階層になります。ここでは「チーム/backlog/id」というルールで切ってみました。こうするとブランチ名が何に関連づいているかわかりやすいでしょう。

f:id:kkamegawa:20161205204222p:plain

タスクに着手したので、タスクをIn Progressに変更します。

Visual StudioからVSTSへ接続する

f:id:kkamegawa:20161205204159p:plain

チームエクスプローラーから「接続の管理」を使用して「チームプロジェクトへ接続」をクリックします。なお、VSTSがサポートするVisual StudioはVS 2008 SP1 GDR1を適用したもの以降だそうです。

www.visualstudio.com

とはいえ、CIツールとして使う場合、Visual Studio 2013以降じゃないと、新しいビルドツールがサポートしていないとかいろいろ困ると思います。さらに、チームプロジェクトのリポジトリをGitで作った場合、サポートされるのはVisual Studio 2015 Update 1以降となっていますので、本当に使おうと思った場合、Visual Studio 2015 Update3を検討してください。

f:id:kkamegawa:20161205204201p:plain

さて、接続しましょう。ここもTeam Foundation Serverと書いていますが、気にせず「追加」をクリックします。なお、Visual Studio 2017ではこのUIがまた少し変わっています。

f:id:kkamegawa:20161205204200p:plain

接続するサーバーを追加するので「サーバー」をクリックします。

f:id:kkamegawa:20161205204202p:plain

VSTSにつなぐ場合、アカウント名.visualstudio.comを指定して、OKをクリックします。

f:id:kkamegawa:20161205204203p:plain

接続に使うアカウント名を選択します。

f:id:kkamegawa:20161205204204p:plain

追加されましたので、「閉じる」をクリックします。

f:id:kkamegawa:20161205204205p:plain

接続するチームプロジェクトを選択します。ちなみにVisual Studio 2017ではここでGitとTFVCの選択がやりやすくなっていますが、VS2015ではTFVCが優先されるようなUIです。

f:id:kkamegawa:20161205204206p:plain

接続すると、複製(git clone)します。基本的に作成したリポジトリのクローンを先に行ってください。

f:id:kkamegawa:20161205204207p:plain

複製先のフォルダを指定します。既定値はDocumentsフォルダのRepsの下に作成となっていますが、昨今のJavaScriptライブラリをcloneすると、ファイル名が簡単に260バイト超えてしまいます。

こんな風にc:\とかに短いフォルダを作成して、その下にcloneしましょう。

Gitの設定

f:id:kkamegawa:20161205204210p:plain

チームプロジェクト内にある、Gitの設定を行っておきましょう。グローバル設定(全Gitリポジトリに共通)と、リポジトリの設定(リポジトリ毎)の二種類があります。リポジトリの設定はVSTSでリポジトリを初期化するとVisual Studioに最適化されたGit設定(.gitignore)がダウンロードされているので、設定する必要はありません。

Gitのグローバル設定ではメールアドレスと、氏名だけは必ず設定しておきましょう。何も設定しないとWindowsのログオンアカウントが使用されてしまいます。

プロジェクトを作成する

git clone後、いよいよVisual Studioで作成します。

f:id:kkamegawa:20161205204224p:plain

.NET のWebアプリケーションを作ります。

f:id:kkamegawa:20161205204225p:plain

.NET Coreでやってみます。

f:id:kkamegawa:20161205204223p:plain

Application Insightsも構成してみます。

f:id:kkamegawa:20161205204226p:plain

App Serviceを設定して、完成。

まとめ

ようやく開発らしいところになりました。ここから先、ようやく開発関係の機能紹介を行います。

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