TFSカスタムアクティビティの展開:セットアッププロジェクトの作成

作成したアクティビティを使うためには、
 ・VS/TFSが参照するフォルダにdllが格納されていること
 ・グローバルアセンブリキャッシュ(GAC)に登録されていること
が条件になります。(詳細については「Customize Team Build 2010 – Part 7: How is the custom assembly found?」)

参考にさせて頂いた「C#.NETでいく? TFS2010ビルド テンプレートのカスタマイズ(3)」とか「Ewald Hofman Customize Team Build 2010 – Part 7: How is the custom assembly found?」では、ビルドコントローラーに対してカスタムアセンブリを参照させる方法で解決していますが、複数のカスタムアセンブリを使いたくなった時にややこしくなるのが嫌だったので、ここではセットアップを作成して登録する方法をとります。

ソリューションに対して、セットアッププロジェクトを追加します。

Act022


Act023

自動的にエディタが起動されますので、「対象コンピュータのファイルシステム」を右クリックし、「特別なフォルダーの追加」-「グローバルアセンブリキャッシュフォルダ」を選択します。

Act024

GACに登録するファイルとして、プロジェクトでビルドされたファイルを指定します。

Act025


Act026

次は、セットアップ時の動作を少しだけ変更します。
通常、セットアップ実行時に「このユーザーのみ」と「すべてのユーザー」という選択肢が表示されますが、アクティビティはユーザ単位で使う/使わないというコントロールはしない(はず)ので、必ず「すべてのユーザー」でインストールするように変更します。
セットアッププロジェクトを右クリックし、「表示」-「ユーザーインターフェイス」を選択します。ユーザーインターフェイスのエディタ画面で、「インストール」-「開始」-「インストールフォルダー」のプロパティにある「InstallAllUsersVisible」をTrueに変更します。

Act034


Act035

ここで、セットアッププロジェクトをビルドすると、こんなエラーになってしまいました。

Act028

すっかり忘れていましたが、GACに登録するアセンブリは、厳密名を持っていないと登録できない仕組みになっています。(いわゆる「DLL Hell」の解決)

これはちゃんと対応しないといけないので、厳密名をアセンブリに付与します。

TFSカスタムアクティビティの展開:厳密名の付与

カスタムアクティビティのプロジェクトのプロパティを開き、「署名」タブを選択します。

Act029

「アセンブリの署名」をONにし、キーファイルの選択から「<新規作成…>」を選択します。

Act030

作成画面で「キーファイル」にファイル名を指定します。ここでは「キーファイルをパスワードで保護する」をOFFにしておきます。(他にも展開するのであれば、ちゃんとパスワード指定した方がよいかと思います)

Act031

この状態で、カスタムアクティビティのプロジェクトを一旦ビルドし、次にセットアッププロジェクトのビルドを行うとセットアッププログラムが正常に作成できます。

このセットアッププログラムを使って、ビルドワークフローを編集する端末とビルドサーバにアクティビティをインストールします。
なお、インストール後にビルドサービスの再起動を行わないとちゃんと認識してくれません。

次は、インストールしたアクティビティをVS IDEに登録します。

TFS2010のBuildProcessTemplate編集 その2

さて、WriteBuildMessageでビルド実行結果にメッセージを出力してみます。ツールボックスから、WriteBuildMessageをメッセージ出力したい場所にドラッグします。
今回は、「エージェントで実行」の中の、ビルド実行後に入れてみます。

Act006_4

プロパティで、「Message」に出力したいメッセージを"ダブルクォーテーション付き"で指定します。変更したら、保存→チェックインします。
チェックインまで完了したら、ビルドを実行してみます。
実行結果を確認してみると・・・・・・メッセージが出力されていません><



Act008_2

いろいろネットを検索してみると、メッセージの重要度(Importance)を変更しないと出力されないようですので、設定内容を変更します。

Act009

初期値は「Microsoft.TeamFoundation.Build.Client.BuildMessageImportance.Normal」なのですが、これを「Normal」から「High」に変更します。
(ここでもインテリセンスがきくのは流石です)

Act010

保存・チェックインしたあと、再度ビルドを実行して、結果を確認してみます。

Act011

ちゃんと出力されました。

単純なメッセージはこれで出力できるのですが、当初の目的であったリンク形式でのメッセージ出力はこれではできません。(他のアクティビティでもリンク先のURLを指定する項目はありません)

さて、どうしたものかと悩みましたが、ネットでいろいろ検索してみると、リンク形式でのメッセージ出力ができるカスタムアクティビティを作成している人がいました。
それをそのまま使わせていただこうかと思いましたが、せっかくなのでカスタムアクティビティの作成も行ってみようかと思います。

TFS2010のBuildProcessTemplate編集 その1

FindBugsの実行結果をビルド実行結果から参照するためには、ビルド結果メッセージを出力しないといけないはずです。

となると、「ビルドが終わったら」とか「FindBugsが終わったら」といったタイミングで出力することになりそうですが、どこでどうやったら可能なんでしょうか??

TFSの場合、いろんな処理のフロー(ビルドプロセス)については、ビルド定義で指定されているビルドプロセステンプレートに定義します。
個別に処理を変更した場合には、テンプレートファイルを編集します。
編集例はMSDNのチュートリアル: カスタム ワークフローの定義と Team Foundation ビルドからのデータベースの配置にあります。

TFSのビルドプロセスは、ビルド定義にある「プロセス」で指定されています。

Act001

実体は、Windows Workflow Foundation(WF)用のXAMLファイルになっています。
XAMLファイルなので、テキストエディタでペシペシ編集すると想像してしまいますが、
なんと、WF用のエディタ画面があります!
ビルド定義画面で「バージョンコントロールパス」をクリックし、ソース管理エクスプローラーから、ビルドプロセスファイルに指定されているファイル(今回はUpgradeTemplate.xaml)をダブルクリックします。

Act003

なんということでしょう、ワークフローエディタ画面になるではありませんか。
ツールボックスにもたくさん入っています。

Act004

ビルド結果にメッセージを出力するための部品(アクティビティ)としては、
 ・WriteBuildError
 ・WriteBuildInformation<T>
 ・WriteBuildMessage
 ・WriteBuildWarning
の4つになります。

Act005

次は、ためしにWriteBuildMessageで単純なメッセージを出力してみます。

TFSでのJavaビルド環境作成:JDKとAntのインストール

ほぼ1ヶ月ごとの更新になってます^ ^;

さて、今までクライアント側(Eclipse)のことは何回か書きましたが、これからはサーバ側のことについて書いてみたいと思います。
(ほんとは.NETで全部開発したいのに...)
※あくまで1例です

今回、こんな環境を前提で作業を行います。
Buildjava01

TFSのアプリケーションサーバ(tfs02)とビルドサーバ(build2008r2)を分けてみました。
プロジェクト管理は1サーバで集中管理するけど、ビルドは言語別で環境を分離するかなという想定です。

まずは、ビルドサーバにJDKとAntをインストールします。JDKは16.u18、Antは1.8.1を使ってみました。
インストールそのものに注意点はありません。JDKはインストーラーの言うことに従い、Antはただ解凍するだけです。

インストール終了後、JDKとAntのインストールフォルダをシステム環境変数に追加します。
今回は、JDKは「JAVA_HOME」、Antは「ANT_HOME」で追加します。

TFSでのJavaビルド環境作成:Ant用Build.xml作成

続いて、TFSのビルド定義からAntを起動できるようにします。

まずは、VSからTFSプロジェクトを作成します。その後、Eclipseから作成したTFSプロジェクトに接続します。
Buildjava03

そして、EclipseでJavaプロジェクトを作成し、TFSプロジェクトに登録します。

Buildjava04_2

「保留中の変更」にいろいろでてくるので、とりあえず「チェックイン」してしまいます。
その後、Team Foundation Server チームエクスプローラーから「ソース管理」をダブルクリックし、ソース管理エクスプローラーからJavaプロジェクトフォルダの下にある「.settings」のフォルダをクローク(ファイル同期対象外にする)します
(Team Foundation Server チームエクスプローラーはパースペクティブから開けます)

Buildjava05_2

Javaソースファイルを作成し、TFSにチェックインします。
次に、Ant用のBuild.xmlファイルを作成し、TFSにチェックインします。
最初はビルドでエラーがでても嫌なので、メッセージだけ出力することにします。
Buildjava06

次は、TFSのビルド定義の作成です。

TFSでのJavaビルド環境作成:EclipseからTFSビルド定義作成

前回作成したBuild.xmlを使うTFSのビルド定義を作成します。
チームエクスプローラーから「ビルド」を右クリックし、「新しいビルド定義」を選択します。
Buildjava07_2

VisualStudio IDEから作成するのとほぼ同じですが、一部異なります。
ビルド定義名は「JavaBuild」で作成してみます。
Buildjava08

トリガーは「手動」のままです。
Buildjava09

ワークスペースはデフォルトのままにします。
Buildjava10_2

ビルドの規定値で、「ビルドコントローラー」にはビルドサーバで稼働しているビルドコントローラーの名称(デフォルトのままで作成した場合、「既定のコントローラー – [ビルドサーバ名])を選択します。また、ビルド結果(結果ログ、作成したバイナリファイルなど)を保存/公開するための共有フォルダ名を入力します。
Buildjava11

次項目がVisualStudio IDEとは完全に異なります。VisualStudio IDEから作成したときは「プロセス」となっていて、MSBuildとかWF(Windows Workflow Foundation)エンジンへのパラメータを設定するのですが、TEE(Team Explorer Everywhere)からビルド定義を作成(編集)したときには、MSBuild用のファイルを指定する内容になります。
ビルド定義を作成したときには、MSBuildプロジェクトファイルは作成されていませんので、「作成」ボタンが表示されます。
Buildjava12

ビルド構成のウィザードが起動されます。今回はAntを使用するので、「既存のAnt BuildfileによるMSBuild構成」を選択し、「次へ」を押します。
Buildjava13

TFSビルド定義で使用するAntビルドファイルとして、先ほど作成したBuild.xmlを指定します。
Buildjava14

「完了」を押すと、MSBuildプロジェクトファイルが作成され、元のTFSビルド定義編集画面に戻りますので、「OK」を押して定義作成を終了します。
Buildjava15

これで、TFSビルドからAnt用Build.xmlが実行できるようになったので、おためしで実行してみます。
Buildjava16
Buildjava17

ビルドが完了したら、実行結果を確認してみます。
Buildjava18

結果一覧から最新ビルド結果レコードをダブルクリック
Buildjava19

概要のところに「ログファイルの表示」がありますので、これをクリックすると、Ant用Build.xmlのログファイルが表示されます。
Buildjava21

「BUILD SUCCESSFUL」と出力されてるので、Antそのものは起動されているのですが、、Build.xmlで記載したメッセージが出力されていません。
どうするかはこの次で。

TFSでのJavaビルド環境作成:AntのTarget指定方法

前回、Ant用Build.xmlが実行できたのにメッセージが出力されなかったのは、Ant実行時のTarget名を指定していなかったためです。
Antでは(Antじゃなくてもそうだと思いますが)、一連のまとまった処理をTargetとして定義し、実行時にTarget名を指定することでいろいろ動作を切り替えます。
今回作成したBuild.xmlは、
Buildjava06_2
という内容で作成しました。<project default="">と指定しているので、実行時にTarget名を指定しないと何も実行されません。

しかし、AntのTarget名を指定するところはどこにもありませんでした。
VisualStudio IDEからビルド定義を開いても、AntのTarget名を指定する項目はありません。
Buildjava22

多少力技かと思いますが、MSBuildプロジェクトファイルを修正して、MSBuildの引数でAntのTarget名を指定できるようにします。
ここからはVisualStudio IDEでの作業になります。
まずは、TFSプロジェクトのフォルダとローカルフォルダのマッピングをしておきます。
チームエクスプローラーから「ソース管理」をダブルクリックし、ソース管理エクスプローラーを開きます。
Buildjava23

ローカルパスのところに「マップされていません」とあるので、クリックします。
Buildjava24

マッピングするフォルダを指定し、「マップ」を押すとソース管理エクスプローラーに戻ります。
MSBuild用のプロジェクトファイルは「TeamBuildTypes」-「[ビルド定義名(ここではJavaBuild)]」-「TFSBuild.proj」になります。
まずは編集のために、最新ファイルを取得します。
「TFSBuild.proj」を右クリックし、「最新バージョンの取得」を選択します。
Buildjava28

取得が終わったら、ダブルクリックしてファイルを開きます。
ファイルの最後のほうにAnt関連のパラメータを指定する記述があります。(AntBuildFile要素)

Buildjava29

Target要素に指定した名称がAnt実行時のTarget名として使われますが、何も指定はありません。ここに、MSBuildの引数を当てはめることにします。
Target要素の内容として「$(AntTarget)」を追加し、保存→チェックインします。
Buildjava30

Buildjava31

次に、TFSのビルド定義を変更します。
チームエクスプローラーから「JavaBuild」を右クリックし、「ビルド定義の編集」を選択します。
Buildjava32

「詳細」の中にある「MSBuild引数」のところに「Property:AntTarget=test」を追加し、保存します。
Buildjava33

Eclipseから再度ビルドを実行し、結果を確認します。
Buildjava34

ちゃんとAntの"test"Targetが実行され、メッセージが表示されました。

次は、Antのjavacタスクで指定するソースファイル/クラスファイルの場所指定についてです。

TFSでのJavaビルド環境作成:javacタスクで使用するフォルダの指定

今回は、Antのjavacタスクで使用するソースファイル/クラスファイルのフォルダ指定についてです。
TFSでビルドを実行すると、指定された状態(通常は最新バージョン)のファイルを自動的に取得します。取得先は、ビルドエージェント作成時に作業ディレクトリに指定したフォルダになります。
Buildjava35

Buildjava36

クラスファイルなどのビルド生成ファイルの出力先についてはいろいろ考えがあると思いますが、今回はTFSのビルド結果出力フォルダに出力したいと思います。

javacタスクでは、ソースファイルのフォルダは「srcdir」属性、クラスファイルの出力先フォルダは「destdir」属性で指定できますが、この内容をTFSで使用するフォルダと連動させます。
実は、MSBuildからAntを実行する際に、TFSBuild.projでTFSで使用する情報の一部がプロパティとしてセットされています。
Buildjava37

デフォルトでセットされているのは以下の情報です。
 BinariesRoot
 BuildDefinitionName
 BuildDefinitionUri
 BuildDirectory
 BuildNumber
 DropLocation
 LogLocation
 SourceGetVersion
 TestResultsRoot
 TeamProject
 WorkspaceName
 WorkspaceOwner
各項目の内容については、MSDNのTeam Foundation ビルド アクティビティ、またはIBuildDetail Propertiesに記載されています。
但し、「LogLocation」はなぜかセットされていません。(今回、これが結構痛いです)

この情報を組み合わせてソースファイル/クラスファイルのフォルダ指定を行いたいのですが、Javaプロジェクト名はTFS側では管理されていないので、MSBuildの引数に追加し、Antに渡すプロパティ情報にも追加します。
以下の内容で「JavaProjectName」というプロパティ指定をTFSBuild.projに追加し、修正内容をチェックインします。
Buildjava38

TFSビルド定義の方は、MSBuildの引数に「JavaProjectName」を追加し、保存します。
Buildjava39

次に、EclipseからBuild.xmlを以下のように変更し、チェックインします。
Buildjava40
変更内容は
 ・javacタスクのsrcdir属性に指定するソースフォルダをsrcbaseプロパティとして組み立てる。
 ・javacタスクのdestdir属性に指定するクラスファイル出力フォルダdestbaseプロパティとして組み立てる。
 ・destbaseプロパティにセットしたフォルダをjavacタスク実行前に作成する
になっています。
※クラスファイルの出力先がTFSのビルド結果出力フォルダになっていませんが、TFSのビルドが完了したときに、「${BuildDirectory}/binaries」配下の内容がTFSのビルド結果出力フォルダにコピーされます。

これで、Eclipseからビルドを実行すると、.classファイルがTFSのビルド結果出力フォルダに出力されます。
Buildjava41

Buildjava42

Buildjava43

Buildjava44

次は、ソースファイルの静的解析ツールであるFindBugsをビルド時に実行してみます。

TFSでのJavaビルド環境作成:FindBugsの実行

まずは、ビルドサーバにFindBugsをインストールします。
JDK/Antと同様、インストール先フォルダをシステム環境変数「FINDBUGS_HOME」に登録するのと、Antと連動させますので「findbugs-ant.jar」をAntのLibフォルダにコピーしておいてください。

次に、Ant用Build.xmlにfindbugs属性を追加し、チェックインします。
Buildjava45_2

追加したのは
 ・FindBugs実行用のtaskdef/property追加
  findbugs.home指定のため、OS環境変数のFINDBUGS_HOMEを参照しています。
  (${env.FINDBUGS_HOME})
 
 ・findbugs要素の追加
です。
※「${LogLocation}」がちゃんと設定されていれば、チェック結果の出力先(outputFile)が、「${DropLocation}/${BuildNumber}/findbugs-result.html」というややこしい指定にならないのではと思います。ちょっと調べてみると、前からずっとこの仕様(?)のようなのですが、M$さん、なんとかしてください<(_ _)>

ビルドを実行すると、FindBugsのチェック結果が出力されます。

Buildjava46

Buildjava47

ちゃんとFindBugsが実行されています。
とりあえず、共有フォルダを開けば実行結果も確認できます。

ただ、わざわざ共有フォルダを参照するのではなくて、ビルド実行結果から直接参照するのがスマートだと思いますので、次はビルド実行結果からFindBugsの出力ファイルをリンク参照できるようにします。