7/12/14

TFS Build Web.config Transformation

With Visual Studio, we are able to create different build configurations with the Configuration Manager. This allows us to create different web.config files for a particular build target like Stage, Prod. The idea behind this is that each target configuration contains the correct application settings for that target environment.

When we build our projects on Visual Studio, we notice that the web.config file is transformed to contain the changes that are needed for the build target. When we use TFS Team Build, this does not happen by default.  An approach that we can take to address this is as follows:

Add a target directive only on the web project definition

For this step, we need to edit the .csproj file and add the following XML entries:

<UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.Tasks.dll" />
<Target Name="AfterBuild" Condition="'$(IsTFSBuild)' != ''"
<Message Text="'Message After Build: TFSBuild Status $(IsTFSBuild) - $(OutDir)\_PublishedWebsites\$(TargetName) '" />
  <TransformXml Condition="Exists('$(OutDir)\_PublishedWebsites\$(TargetName)')"
       Source="Web.config"
       Transform="Web.$(Configuration).config"
       Destination="$(OutDir)\_PublishedWebsites\$(TargetName)\Web.config"
/>

Element Name
Description
UsingTask
This element allows the MSBuild process to know in what assembly to find the TrasnformXml task. We need to note that the path is the one on the Build Server not a personal work station.

Target
The target is the action that runs the transformation process. We want this to be done AfterBuild has completed, and we only want this done when the IsTFSBuild argument is not empty. We add this argument to the TFS build definition.

Message
The message element helps us make a log entry, so that we can validate if this action is getting executed.

TransformXml
With this directive, we are executing a transformation task and merging the web.config file with another config file that is associated to the build target. For example for a release build, the $(Configuration) is set to “Release”. The result is merged and copied on the _publishedWebsites folder

*Note this can also be done as part of the build definition, but web.config is only applicable to web projects.

Save your file and unit test the change using the MSBuild application from the Visual Studio command shell. The command should look like this:

msbuild webproject.csproj /p:Configuration=Release /p:IsTFSBuild=True > out.log

On our desktop the OutDir is set to the Bin folder, so we can change the folder paths to read like this:

<TransformXml Condition="Exists('$(OutDir')"
       Source="Web.config"
       Transform Web.$(Configuration).config "
       Destination="$(OutDir)\Web.config"
/>

A merged web.config file should be copied to the Bin folder. Make sure to not include two target elements with the same name (AfterBuild). The last element always override the one that was declared before it.

Add a MSBuild Argument to the build definition

Now that the project file has been checked-in, we can test this on Team Build. First we need to add the IsTFSBuild argument to the build definition. This is done on Visual Studio. Add the parameter in the MSBuild Argument textbox as shown below:


Now, we can queue a build and take a look at the _PublishedWebSites folder. The web.config file should be merged with the configuration from the build target.  In case this did not happen, we can look at the build log file. We can look for the AfterBuild tag and find the message that was added to the project file. If this is not visible in the log file, we need to make sure that there are no typos on the changes and arguments that we are using.

Key Benefits

This process is a key component for the delivery a build and deployment automation process.

Management of configuration files for multiple environments.

0 comments :

Post a Comment