次の方法で共有



March 2009

Volume 24 Number 03

Team System - Team Build 2008 のカスタマイズ

Brian A. Randell | March 2009

目次

プロパティ
進行中の処理に関する情報を取得する
変更点
カスタム タスク

2008 年 11 月号の Team Foundation Build 2008 に関するコラムでは、Team Build 2008 とは何か、Team Build 2008 の注目点、ビルドの作成方法、新しい API を使用して Team Build サービスのプログラミングを行う方法について説明しました。このコラムでは、Team Build の既定の動作を変更する方法、カスタム タスクでビルドを拡張する方法、Team Build 2008 SP1 で追加された機能の使用方法について説明します。

ビルドのカスタマイズを開始する前に、Team Build は Microsoft .NET Framework 2.0 のコア コンポーネントである Microsoft Build Engine (MSBuild) 上で構築されていることを覚えておいてください。これから、MSBuild でのビルドの実行方法に関する若干の変更点について説明しますが、その内容を理解するには、適切な予備知識が必要です。参考のために、MSBuild に関する MSDN 2006 年 6 月号の記事「Microsoft ビルド エンジンのカスタム タスクを使用した、お好みの方法でのアプリケーションのコンパイル」をご覧ください。

繰り返しますが、Team System のカスタマイズの動作を確認することをお勧めします。確認は、まず、実稼動環境以外の Team Build で行ってください。また、マイクロソフトが提供している評価版の仮想マシンを使用することをお勧めします。2008 年のクリスマス直前にイメージを更新しているので、SP1 をインストールするとイメージが新しくなるだけでなく、その他の点も更新されます。Virtual PC と Hyper-V の両方のイメージが用意されています。リンクおよび詳細については、Pluralsight のブログをご覧ください。

ビルドの実行には、複数の移動パーツが関連しています。図 1 (MSDN の記事「Team Foundation ビルドの概要」より引用) は、これらのパーツを視覚的に表したものです。前回のコラムでは、一般的な処理手順についても説明しました。ここで最も重要な事は、MSBuild がいつ関与するかということです。Team Build サービス (TFSBuildService.exe) は MSBuild プロセスを作成し、TFSBuild.tbrsp ファイルの場所を渡します。このファイルはビルド エージェントの作業ディレクトリの BuildType サブフォルダにあります。

fig01.gif

図 1 ビルド コンポーネントの概要

Team Build 2008 SP1 サービスは TFSBuild.tbrsp を動的に生成します。このファイルは Team Build データベースに保存されたデータ、Team Build で制御されるパラメータ、およびビルドの TFSBuild.rsp ファイルのコンテンツ (存在する場合) で構成されます。図 2 はテスト ビルドの例です。

図 2 テスト ビルドの例

### Begin Team Build Generated Arguments ### /nodeReuse:false /m:1 /nologo /noconsolelogger /dl:BuildLogger,"C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\ PrivateAssemblies\Microsoft.TeamFoundation.Build.Server.Logger.dll"; "BuildUri=vstfs:///Build/Build/45; TFSUrl=http://tfsrtm08:8080/; TFSProjectFile=C:\Builds\ExploreTeamBuild\Sysinfo\BuildType\TFSBuild.proj;ServerUICulture=1033; LogFilePerProject=False; "*BuildForwardingLogger,"C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\ PrivateAssemblies\Microsoft.TeamFoundation.Build.Server.Logger.dll"; "BuildUri=vstfs:///Build/Build/45;TFSUrl=http://tfsrtm08:8080/; TFSProjectFile=C:\Builds\ExploreTeamBuild\Sysinfo\BuildType\TFSBuild.proj;ServerUICulture=1033;" /fl /flp:logfile=BuildLog.txt;encoding=Unicode; /p:BuildDefinition="Sysinfo" /p:BuildDefinitionId="3" /p:DropLocation="\\localhost\Drops" /p:BuildProjectFolderPath="$/ExploreTeamBuild/TeamBuildTypes/Sysinfo" /p:BuildUri="vstfs:///Build/Build/45" /p:TeamFoundationServerUrl="http://tfsrtm08:8080/" /p:TeamProject="ExploreTeamBuild" /p:SourcesSubdirectory="Sources" /p:BinariesSubdirectory="Binaries" /p:TestResultsSubdirectory="TestResults" /p:SourceGetVersion="C244" /p:LastGoodBuildLabel="Sysinfo_20090104.2@$/ExploreTeamBuild" /p:LastBuildNumber="Sysinfo_20090104.2" /p:LastGoodBuildNumber="Sysinfo_20090104.2" /p:NoCICheckInComment="***NO_CI***" /p:IsDesktopBuild="false" /p:TeamBuildRefPath="C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\PrivateAssemblies" /t:EndToEndIteration TFSBuild.proj ### End Team Build Generated Arguments ### ### Begin Checked In TfsBuild.rsp Arguments ### # This is a response file for MSBuild # Add custom MSBuild command line options in this file ### End Checked In TfsBuild.rsp Arguments ###

ビルドを Team Build 2005 で作成した場合、ビルド データの大部分はバージョン管理下で固定した場所にある一連のファイルに保存されます。その中で特に重要なファイルは、MSBuild プロジェクト ファイル スキーマに準拠する XML ファイルである TFSBuild.proj です。Team Foundation Server 2008 でビルドを作成すると、ユーザーが入力した情報の大部分が TFS データベースに保存されます。バージョンが異なってもビルド プロセスのカスタマイズ方法は同じです。TFSBuild.proj ファイルを編集し、必要に応じてカスタム MSBuild タスクを書きます。

Team Build 2008 SP1 で TFSBuild.proj ファイルを表示するには、[チーム エクスプローラ] ウィンドウでビルド定義の名前を右クリックして [View Build Configuration] (ビルド構成を表示する) を選択します。SP1 以前のバージョンの場合は、ソース管理エクスプローラを開き、ビルド定義ウィザードの実行時に場所を指定して、その場所まで手動で移動します。

データベースに保存されたビルド定義には、ビルド対象とビルドのタイミングが定義されています。TFSBuild.proj ファイルは、Team Build でのビルドの実行方法を定義します。前回のコラムで、新しいビルド定義の作成時に新規に TFSBuild.proj ファイルを作成するか、またはバージョン管理されている既存のファイルを参照できると説明しました。MSBuild でこの機能を利用するには、各種の Team Build アセンブリと、ビルド対象、ビルドの順序、追加タスクに関する情報が必要です。図 2 を見ると、Team Build から TFSBuild.proj が MSBuild の処理対象プロジェクト ファイルの名前として渡されていることがわかります。MSBuild ではすべての /p 引数がグローバル プロパティとして扱われます。

単一ソリューション (デバッグ構成とリリース構成の両方) をビルドし、テストを実行しない場合の Team Build 2008 TFSBuild.proj ファイルの内容を確認すると、複数のセクションがあります。この XML ファイルは Visual Basic または C# のプロジェクト ファイルに類似しています。XML ファイルには、ビルド プロパティ、ビルド プロセスの成果物、および実行する処理が定義されています。このファイルはプロパティを <PropertyGroup> 要素にまとめてグループ化し、<ItemGroup> 要素内のソリューションと同様に成果物を追跡します。また、<Target> 要素を使用して実行する一連の処理を指定します。

Target には Name 属性があり、特定の順序でタスクをグループ化します。CLR に依存しないアセンブリにタスクを定義するには、ITask を実装するパブリック クラスまたは抽象基本クラス Task (または ToolTask などの任意の派生型) を継承するパブリック クラスを作成します。ITask、Task、および ToolTask は Microsoft.Build.Utilities.dll アセンブリ内にあります。TFSBuild.proj ファイルの XML 宣言の後に、MSBuild に必要なルート要素 <Project> が記述されています。

<Project DefaultTargets="DesktopBuild" xmlns="https://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">

DefaultTargets 属性は、MSBuild のターゲットとして DesktopBuild を指定しています。ただし、この処理は MSBuild を直接使用してビルドする場合にのみ実行されます。再び図 2 を見ると、Team Build は EndToEndIteration ターゲットをメイン エントリ ポイントとして扱うことを MSBuild に通知しています。そのため、Team Build から起動した場合、MSBuild は DefaultTargets 属性を無視します。

<Project> 要素の後に <Import> 要素があります。<Import> 要素は、処理中のファイル以外に別のプロジェクト ファイルも使用することを MSBuild に通知しています。Team Build は <Import> 要素にバージョン固有の Team Build ターゲット ファイルを指定します。

<!-- Do not edit this --> <Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\TeamBuild\Microsoft.TeamFoundation.Build.targets" />

このターゲット ファイルは Team Build の機能の中核です。このファイルをよく見ると、Team Build のプロセスと MSBuild の動作が詳細にわかります。このターゲット ファイルは編集しないでください。編集すると、特定のビルド エージェントのすべてのビルドに影響します (ただし、影響を受けるのはそのエージェントのみです)。また、マイクロソフトから Team Build に対するサービス パック、修正プログラム、または更新プログラムが提供された場合は、変更が失われることになります。マイクロソフトはこのターゲット ファイルの編集をサポートしていません。このような場合には、組み込みのメカニズムを使用して Team Build の動作を調整する必要があります。その方法についてはこれから説明します。

前処理の一部として、MSBuild は実行するターゲットのツリーを作成します。プロジェクト ファイル内でのターゲットの定義順序は無関係です。ターゲットは、エラーが発生しないことを前提に、エントリ ポイント ターゲットおよび DependsOn 属性に基づいて実行されます。実行されるのは、ターゲットの 1 つの名前付きバージョンのみです。定義されたターゲットの最後のバージョンを使用します。Team Build は、これを利用するために Team Build ターゲット ファイルに複数の空のターゲットを定義します。これらのターゲットの多くは、名前に Before または After というプレフィックスが付いています。<Import> 要素の指定により、Team Build ターゲット ファイルに定義したターゲットが先に処理されます。

開発者がこれらのターゲットをオーバーライドするには、TFSBuild.proj ファイル内の名前と同じ名前でターゲットを作成します。ただし、ターゲットの実行順序に影響するいくつかの項目があります。まず、ルート要素 <Project> は InitialTargets 要素をサポートしています。InitialTargets 要素では、DefaultTargets またはコマンド ラインで指定したターゲットの前に実行する 1 つ以上のターゲットをセミコロンで区切ったリストを指定できます。2 つ目に、DependsOnTargets 属性を使用して、ターゲットに 1 つまたは複数の依存先ターゲットを指定できます。DependsOnTargets 属性に指定したターゲットは宣言された順序で実行されます。Team Build ターゲットの多くはこのように処理されます。3 つ目に、ターゲットには実行条件を指定できます。たとえば、Team Build ターゲットの多くは、ビルドがデスクトップ ビルド以外である場合にのみ実行されます。そのため、Team Build を実行したときに最初に実行される一連のターゲットは、まず CanonicalizePaths、次に CheckSettingsForEndToEndIteration の順になります。

MSBuild が最初に CanonicalizePaths を実行するのは、CanonicalizePaths がターゲット ファイルに InitialTargets の項目として定義されているためです。次は CheckSettingsForEndToEndIteration です。これは、EndToEndIteration (Team Build で MSBuild のコマンド ラインに指定されたターゲット) に対して指定された DependsOnTargets のリストで最初のターゲットだからです。MSBuild は EndToEndIteration からのチェーンに存在するターゲットのみを実行します。

これで、必要事項はすべて説明しました。このコラムの第 1 部で、カスタム ワークスペースを使用して MSDNMag というチーム プロジェクトを作成しました。次の例でも、引き続きこのチーム プロジェクトを使用します。サンプル ソリューションはすべて $MSDNMag/Main/src/TeamSystem/C10/ にチェックインされています。カスタム ワークスペース MSDNMag では、ソリューションおよびビルド ファイルを操作しやすくするため、チーム プロジェクトのトランク $MSDNMag を C:\Work\MSDNMag にマップします。既に説明したように、この作業はすべてマイクロフソフトが提供している仮想マシンの Team System 2008 SP1 バージョンで行いました。

初めて Team Build をカスタマイズする場合には、2 つの注意点があります。1 つは、カスタマイズを作成するために編集するファイルは XML ファイルだということです。もう 1 つは、最近のデバッグでは printf とログ ファイルの解析が主になる傾向があるということです。ビルドをカスタマイズして動作を変更する場合、3 つの一般的な方法があります。1 つは、既知のプロパティの値を変更する方法です。もう 1 つは、定義済みのタスクを起動する方法です。3 つ目は、固有のカスタム タスクを作成する方法です。

MSBuild および Team Build は、ターゲットの実行に影響する条件をユーザーが定義できるようにするための複数のプロパティを公開しています。たとえば、Team Build は特定のターゲットを実行するかどうかの判断に使用する IsDesktopBuild プロパティを公開しています。MSBuild はプラットフォーム、コンパイラ オプション、プロセッサ アーキテクチャなどに関連するプロパティを公開しています。また、Team Build には機能の有効/無効を切り替えるプロパティも用意されています。コード分析は調整が可能な項目の 1 つです。

TFSBuild.proj ファイルを見ると、次のような簡単な XML コードが記述されています。<RunCodeAnalysis> プロパティの値を変更すると、プロジェクトのコード分析設定の MSBuild による評価方法が変更されます。

<!-- CODE ANALYSIS Set this property to enable/disable running code analysis. Valid values for this property are Default, Always and Never. Default—Perform code analysis as per the individual project settings Always —Always perform code analysis irrespective of project settings Never —Never perform code analysis irrespective of project settings --> <RunCodeAnalysis>Never</RunCodeAnalysis>

Team Build はテストの実行を制御するプロパティも使用します。これには複数の XML フラグメントが関連します。まず、<RunTest> プロパティを true に設定します。次に、テスト リストを使用するか、または実行するテストを Team Build でスキャンします。テスト リストを使用する場合、<MetaDataFile> プロパティに 1 つまたは複数の <TestList> 項目を定義する必要があります。次に例を示します。

<!--Set this flag to enable/disable running tests as a post-compilation build step.--> <RunTest>true</RunTest> <MetaDataFile Include= "$(BuildProjectFolderPath)/../../Main/src/SysInfo/SysInfo.vsmdi"> <TestList>All Unit Tests</TestList> </MetaDataFile>

プロパティの動作の例をもう 1 つ示します。通常のビルドの実行時には、Team Build はバージョン管理から取得したすべての成果物にラベルを付けます。この処理をスキップするのに必要な操作は、SkipLabel プロパティを true に設定することだけです。この設定を行うにはいくつかの方法があります。まず、ビルドの特定の実行に対してのみ設定を適用する場合は、MSBuild のコマンド ライン引数に /p:SkipLabel=true を渡します (図 3 を参照)。ただし、SkipLabel を渡しただけでは、Team Build が変更セットのリストを生成して作業項目を更新する際にビルド エラーが発生します。このエラーを回避するには、SkipGetChangesetsAndUpdateWorkItems=true を追加します。ビルド レポートの [概要] セクションにコマンド ライン引数が表示されます。

fig03.gif

図 3 MSBuild にコマンド ライン引数を渡す

コマンド ライン以外に、同じ構文で、ダイアログ ボックスを使用せずに、バージョン管理で TFSBuild.proj ファイルと並んで表示される TFSBuild.rsp ファイルを編集する方法もあります。最後に、プロパティを TFSBuild.proj ファイルに追加します。TFSBuild.proj ファイルをバージョン管理からチェックアウトする方法もあります。ファイルをダブルクリックすると、Visual Studio の XML エディタで表示されます。

XML の開始および終了要素タグを使用し、要素のテキストに true を設定して、各プロパティを既存のプロパティ グループに追加できます。または、固有のプロパティ グループを作成することもできます。次のように、条件パラメータを追加して、コマンド ラインでパラメータのオン/オフを切り替えることも可能です。/p:QuickBuild=True を渡せば、簡易ビルドを実行できます。

<PropertyGroup Condition="$(QuickBuild)=='True'"> <SkipLabel>true</SkipLabel> <SkipGetChangesetsAndUpdateWorkItems>true</SkipGetChangesetsAndUpdateWorkItems> </PropertyGroup>

進行中の処理に関する情報を取得する

ビルド操作を開始し、その動作を確認する際、追加ステータス情報を出力できると便利です。Team Build は既定で詳細ログを生成することをあらかじめ承知しておいてください。このログの詳細度を調整するには、fileLoggerParameters (flp) 引数 (Team Build 2005 では /v 引数) を使用します。Microsoft .NET Framework 3.5 では、既定のログ設定が normal から diagnostic に変更されています。そこで、ログ ファイルのサイズを小さくしたい場合には、TFSBuild.rsp ファイルに /flp:verbosity=normal を追加します。

詳細ログに必要な情報が見つからない場合は、固有のメッセージをログ ファイルに記録できます。メッセージをログに記録するには、ターゲットを定義する必要があります。ターゲット内で、組み込みの Message タスクを使用できます。たとえば、"My Custom Message" という文字列と SkipLabel プロパティの値を記録するには、TFSBuild.proj ファイルの終了 </Project> 要素の直前に次の XML を追加します。

<Target Name="MyMessageLogger"> <Message Text="My Custom Message" /> <Message Text="SkipLabel Status= $(SkipLabel)" /> </Target>

ところが、この XML を追加してビルドを実行しても、何も起こりません。Team Build では EndToEndIteration がエントリ ポイントとして呼び出されることを思い出してください。MSBuild はターゲットの実行チェーン内のターゲットのみを実行します。タスクを実行するには、このチェーンにターゲットをフックする必要があります。この処理を簡単に行うには、ターゲットを Team Build ターゲット ファイルに追加する方法がありますが、これは "やってはいけないこと" として先に警告した操作なので、この方法を採用するわけにはいきません。マイクロソフトがサポートし、積極的に推奨している 2 つの妥当な代替方法があります。その 1 つは、ターゲットの DependsOn プロパティを変更してカスタム ターゲットを依存関係チェーンに挿入する方法です。

前述したように、Team Build のターゲット ファイルには複数の空のターゲットが定義されます。これらのターゲットは明示的に作成されるので、開発者がオーバーライドできます。カスタマイズ可能なターゲットの一覧については、MSDN の記事「カスタマイズ可能な Team Foundation のビルド ターゲット」を参照してください。

チーム ビルド プロセスには、Team Build でカスタム処理を容易に実行できるポイントが 20 か所以上あります。オーバーライド可能な最初のターゲットは BeforeEndToEndIteration です。これは MSBuild が実行する事実上 4 番目のターゲットです。以前の XML フラグメントを実行するには、Name 属性を MyMessageLogger から BeforeEndToEndIteration に変更する必要があります。一歩進んで、メッセージを Team Build レポートに表示するには、Message タスクではなく、Team Build の BuildStep タスクを使用します。次に例を示します。

<Target Name="BeforeEndToEndIteration"> <BuildStep TeamFoundationServerUrl="$(TeamFoundationServerUrl)" BuildUri="$(BuildUri)" Name="MyBuildStep" Message="BeforeEndToEndIteration override is executing." Status="Succeeded" > </BuildStep> </Target>

Team Build の 2005 から 2008 へのアップデートで変更されたすべての点が好評なわけではありません。たとえば、Team Build 2008 では、ビルド プロセスでエラーが発生しなければ、既定でビルド成功のマークを付けますが、この場合、ビルドの部分的成功の概念が無視されます。Team Build では、コンパイルが成功すると、他の処理 (たとえば単体テスト) が失敗してもビルドのステータスを成功状態に設定します。Team Build 2005 では、テストが失敗すればビルドは失敗します。

言うまでもなく、この変更はだれもが望むものではありません。SP1 を適用していない Team Build 2008 でこの動作を回避するには、マイクロソフトの Aaron Hallberg が投稿した方法を使用して、1 つでもテストが失敗した場合にはビルドが失敗するようにします。TFSBuild.proj ファイルに追加する必要がある XML を図 4 に示します。このターゲットは、まず TestSuccess プロパティを取得します。次に、TestSuccess が false の場合には CompilationStatus プロパティを Failed に変更します。マイクロソフトはフィードバックを取り入れました。Team Build 2008 SP1 では、この問題に対処するプロパティが追加されました。これにより、<TreatTestFailureAsBuildFailure> を true に設定するだけで済むようになりました。

図 4 TFSBuild.proj ファイルに追加する必要がある XML

<Target Name="AfterTest"> <!-- Refresh the build properties. --> <GetBuildProperties TeamFoundationServerUrl="$(TeamFoundationServerUrl)" BuildUri="$(BuildUri)" Condition=" '$(IsDesktopBuild)' != 'true' "> <Output TaskParameter="TestSuccess" PropertyName="TestSuccess" /> </GetBuildProperties> <!-- Set CompilationStatus to Failed if TestSuccess is false. --> <SetBuildProperties TeamFoundationServerUrl="$(TeamFoundationServerUrl)" BuildUri="$(BuildUri)" CompilationStatus="Failed" Condition=" '$(IsDesktopBuild)' != 'true' and '$(TestSuccess)' != 'true' "> </Target>

カスタム タスク

ここまでは、TFSBuild.proj の XML を変更することによって MSBuild と Team Build の処理方法を変更してきました。では、ビルドの完了後に IIS に Web プロジェクトを配置する場合はどうしたらよいでしょう。また、バイナリを MSI ファイルにパッケージ化する場合はどうしたらよいでしょう。カスタム タスクを作成するという方法もありますが、インターネット上でダウンロード可能な MSBuild および Team Build のタスク ライブラリが既に充実しており、その多くは完全なソース コードが提供されています。

手始めにお勧めする 2 つのライブラリは CodePlex 上にあります。このサイトには、300 以上のタスクを集めた SDC Tasks があります。また、MSBuild Extension Pack には 250 以上のタスクが揃っています。各ライブラリには多様なタスクが含まれ、ソースも提供されています。これらのライブラリを使用するには、ビルド エージェント コンピュータ上にアセンブリをインストールし、適切な XML フラグメントを TFSBuild.proj ファイルに追加する必要があります。

Team Build 2008 はきわめて柔軟性に優れています。その機能を最大限に活用するには、まず Team Build 2008 のしくみと MSBuild との連携方法を理解する必要があります。これらの知識と多少の XML の編集によって、簡単に動作を変更できます。コミュニティの力を借りて、Team Build をさらに高度に活用し、新しい機能を追加することも可能です。目的に最適なタスクが見つからない場合は、固有のタスクを作成できます。

ご質問やご意見は、Brian (mmvsts@microsoft.com) まで英語でお送りください。

Brian A. Randell は、MCW Technologies, LLC のシニア コンサルタントです。マイクロソフト テクノロジについての講演や執筆を行っています。Microsoft MVP として、Pluralsight 社の Applied Team System コースの作成にも携わりました。mcwtech.com/cs/blogs/brianr にブログを公開しています。