[NAgile]Team BuildとWeb Deployment Projectsを利用したデプロイ

デプロイ時に本番環境とステージング環境で Web.config の内容を書き換えたいというニーズは多い。これは Visual Studio 2008 Web Deployment Projects を利用することで簡単に実現できる。
ただし、Team Foundaion Server 2008 の Team Build でデフォルトの設定のまま Web Deployment Projects を使用してビルドを行うと、エラーが発生してしまう。

ここでは、Web Deployment Projects を利用して、ステージング環境と本番環境で構成を切り替える方法および Team Build でビルドを成功させるための手順を簡単に説明しておく。

まず、簡単な Hello World アプリケーションを作成する。ボタンクリック時には、Web.config セクションから文字列を取得してラベルに表示するようなものだ。このプロジェクト名は Hello.Web とする。

using System;
using System.Configuration;

namespace Hello.Web
{
    public partial class _Default : System.Web.UI.Page
    {
        ...

        protected void messageButton_Click(object sender, EventArgs e)
        {
            string message = ConfigurationManager.AppSettings["HelloString"];
            messageLabel.Text = string.Format("Hello {0}!!!", message);
        }
    }
}

Web.config は以下のようになっている。

...
	<appSettings>
		<add key="HelloString" value="Development"/>
	</appSettings>

ビルドの成功を確認したら、VSの構成マネージャで Staging (ステージング用) のソリューション構成を新規に作成する。

同様に Deploy (本番用)のソリューション構成も作成する。

次に、Web Deployment Projects でデプロイ用のプロジェクト(中身は MSBuild のビルドファイル)を作成する。プロジェクト名は Hello.Web.Deploy にしよう。
作成された Hello.Web.Deploy.wdproj をメモ帳で開き、以下のように編集する。SourceWebPhysicalPath セクションを Team Build 用に書き換えるのがポイントだ。この設定を行っておかないと、Team Build ではうまくビルドできない。
あと、Web アプリケーション プロジェクトは aspnet_merge.exe 用の設定に意味がないので、UseMerge の値を false にしておくとよい。

<!-- 
  Microsoft Visual Studio 2008 Web Deployment Project 
  http://go.microsoft.com/fwlink/?LinkID=104956

-->
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    ...
    /* 元のSourceWebPhysicalPathセクションを書き換える */
    <SourceWebPhysicalPath Condition=" '$(TeamBuildConstants)'=='' ">..\Hello.Web</SourceWebPhysicalPath>
    <SourceWebPhysicalPath Condition=" '$(TeamBuildConstants)'!='' ">$(OutDir)_PublishedWebsites\Hello.Web</SourceWebPhysicalPath>
    ...
  </PropertyGroup>
  ...
  
  /* ステージング用の設定を追加する */
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Staging|AnyCPU' ">
    <DebugSymbols>false</DebugSymbols>
    <OutputPath>.\Staging</OutputPath>
    <EnableUpdateable>true</EnableUpdateable>
    <UseMerge>false</UseMerge>
    <SingleAssemblyName>Hello.Web.Deploy</SingleAssemblyName>
    <UseWebConfigReplacement>true</UseWebConfigReplacement>
  </PropertyGroup>

  /* 本番用の設定を追加する */
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Deploy|AnyCPU' ">
    <DebugSymbols>false</DebugSymbols>
    <OutputPath>.\Deploy</OutputPath>
    <EnableUpdateable>true</EnableUpdateable>
    <UseMerge>false</UseMerge>
    <SingleAssemblyName>Hello.Web.Deploy</SingleAssemblyName>
    <UseWebConfigReplacement>true</UseWebConfigReplacement>
    <ValidateWebConfigReplacement>true</ValidateWebConfigReplacement>
  </PropertyGroup>
  ...
</Project>

Hello.Web.Deploy.wdproj を上書き保存し、VSで Hello.Web.Deployプロジェクトのプロパティを表示する。まずは、ステージング用に Web.config の内容を書き換えるための設定を行う。

アセンブリの出力ペインで、「すべての出力を単一のアセンブリにマージする」オプションを選択する。

配置ペインで「Web.config ファイルのセクションの置換を有効にする」にチェックを入れて、以下のように、置換するセクションの内容が書かれてる config ファイルを指定する。

appSettings=StagingAppSettings.config

この config ファイルの中身は以下のようなものだ。このファイルをWebアプリケーションのプロジェクトに追加する。

<?xml version="1.0" encoding="utf-8" ?>
<appSettings>
  <add key="HelloString" value="Staging"/>
</appSettings>

同様に、本番用にWeb.config の内容を書き換えるための設定も行う。

ここで、再度VSの構成マネージャを開き、すべての構成の設定を行う。以下に示すように、Debug / Release では、デプロイプロジェクトのビルドは行わず、Staging / Deploy では Web アプリケーションプロジェクトとデプロイプロジェクトの両方がビルドされるようにする(デプロイのプロジェクトだけだとビルド時にエラーになる)。


ここまで出来たら、ステージング用と本番用のソリューション構成でローカルビルドが成功することを確認し、ソリューションをチェックインしよう。

次はビルド定義を作成する。ステージング用のビルド定義を HelloStagingBuild、本番用のビルド定義を HelloDeployBuild としよう。
ここでは、Team Build のビルド定義の作成方法は割愛するが、ポイントだけを説明しておこう。

ビルド定義を作成途中に、TFSBuild.proj を作成するためのウィザードが表示されるので、ステージング用 / 本番用のそれぞれの構成を選択するのを忘れないようにすればいいだけだ。

ビルド定義が作成できたら、キューに入れてビルドを実行してみよう。サーバーの共有フォルダにそれぞれ、Web.config のセクションが書き換えられた デプロイ用のビルドが出力されているはずだ。

#ビルド結果をビルドサーバーの仮想ディレクトリに配置してWebテストを実行するシナリオについては、以下を参考にされたい。

TN_1601: TechNote 1601 チーム ビルドと Web Deployment プロジェクト

ビルドコンピュータをTeam Fondation Serverにするのであれば、既定のWeb サイトが停止されているはずなので (Team Foundtion は 規定のWeb サイトをポート80 で使用)、この既定のWeb サイトのポートを変更 (8089など)して開始してやれば、デプロイの完全自動化が可能だ。もちろん、Webテストもここでぶん回せる。上記のサイトに記述されているように、ビルドサービスのユーザーが管理者権限を持っていることを確認するのと、ビルドのパブリッシュフォルダに一般ユーザーの読み取り権限をつけてやるのをお忘れなく。

#あとで書いた

もっと柔軟にconfig ファイルの要素を書き換えたいような場合は、NAnduさんの以下の記事を参考にされたい

XmlMassUpdateタスクを使用したデプロイ