Jan 032012
 

TFS has a great (but not perfect) events and alerts system – you can be sent emails about work item changes, source control check-ins and build completion. TFS Power Tools adds Alerts Explorer to Visual Studio, which is a must-have for configuring alerts as the built-in Project Alerts is very basic.

Alerts Explorer allows very sophisticated filters to be set up, but that power can be confusing. I have found that in a development team lead role just two special alerts provided the oversight I needed. Here’s how to set them up.

Alert 1: Check-in Policy Override

Check-in policies (along with folder security) are invaluable for source control management – they can enforce check-in comments and linked work items, and prohibit specific file types being checked-in. However, users can simply override the check-in policy! In one way this is helpful, because it allows work to continue past an overly-restrictive policy, but in every other way it’s madness – people can ignore your carefully constructed policies whenever they like.

Fortunately there is a good compromise – you set up an alert telling you when the check-in policy has been overridden. That way, the user can override the policy if they think they really must, but you get to review what happened and take action if necessary. I found that simply telling people that you get an alert when the policy is overridden was a sufficient deterrent 99% of the time.

This alert is a slight modification of a template that comes with the TFS Power Tools. Note that all source control users must have the power tools installed if you are using any of the check-in policies that come with the power tools, or you will receive an alert every time they check-in (which is quite useful, as you can then tell them to install the power tools!)

Alert 2: Build Failure

The Build Notifications tool that comes with Visual Studio is OK, as it generates system tray alerts that are near-synchronous with build completion. But it’s not much help if a build failed an hour ago or overnight. An email alert can cover this instead.

Note that I have not simply chosen StatusCode = Failed as I also want to be alerted on builds that are “partially successful” i.e. that have test failures. I’ll give users the benefit of the doubt on Stopped builds and assume that builds are only stopped for valid reasons. You may decide differently for your team.

Nov 132011
 

What should you do if you see the error “TF42097: A work item could not be created due to a field error” under the Other Errors and Warnings section of a failed build? The error may seem mysterious initially, because it’s a build complaining about a work item and the connection is not obvious.

The explanation is quite straightforward: the build uses the Default Template (or a derivative) and has the Create Work Item on Failure option turned on, however the Bug work item has been modified in a way that means the build is unable to create it – which could be as simple as making a field mandatory. When I saw this error it was due to putting a work around in place to force users to choose an Area, but the build template left the Area as the default – which was prohibited.

How you fix this depends on how the Bug work item has been restricted. Work item fields that have been made mandatory should have a value specified in the build process template, and if that value should vary depending on the build definition you will need to expose it as an argument in the definition. Here is a step-by-step guide:

  1. Open the build process template you are using (if using the Default Template it is recommended that you make a copy and point your build definitions to it before modifying it).
  2. Click the Arguments tab at the bottom
  3. Create a new argument for each mandatory field in the Bug work item that should have a different value depending on the build definition. Then edit the Metadata argument to make the new argument(s) user friendly in the build definition (optional!)
  4. Find the place in the build definition where the work item is created. This is hidden very well but you can find it here in the Default Template: Sequence –> Run on Agent –> Try Compile, Test, and Associate Changesets and Work Items –> Sequence –> Compile, Test, and Associate Changesets and Work Items –> Try Compile and Test –> Compile and Test –> For Each Configuration in BuildSettings.PlatformConfigurations –> Compile and Test for Configuration –> If BuildSettings.HasProjectsToBuild –> For Each Project in BuildSettings.ProjectsToBuild –> Try to Compile the Project –> Exception –> Handle Exception –> If CreateWorkItem –> Create Work Item for non-Shelveset Builds –> Create Work Item
  5. Open the Properties for the Create Work Item activity and expand the Custom Fields property. Thankfully this is just a Dictionary of key-value pairs and quite easy to edit. Before the final closing brace just add additional pairs of work item field reference names and the value they should have. If you need to pass through the value of an argument you may find this a little tricky – all the braces and escaping in the underlying XML make it difficult to pass in arguments normally so you may need to wrap them in a String.Format(“{0}”, MyArgument) statement.

My final OpenWorkItem activity looked like:


<mtbwa:OpenWorkItem AssignedTo="[BuildDetail.RequestedFor]"
Comment="[&quot;This work item was created by TFS Build on a build failure.&quot;]"
CustomFields="[New Dictionary(Of String, String) From { {&quot;System.Reason&quot;, &quot;Build Failure&quot;},
{&quot;Microsoft.VSTS.TCM.ReproSteps&quot;, &quot;Start the build using TFS Build&quot;},
{&quot;Microsoft.VSTS.CMMI.Symptom&quot;, &quot;Build Failure&quot;}, {&quot;Priority&quot;, &quot;1&quot;},
{&quot;Severity&quot;, &quot;1 - Critical&quot;}, {&quot;Microsoft.VSTS.CMMI.FoundInEnvironment&quot;, &quot;n/a&quot;},
{&quot;System.AreaPath&quot;, String.Format(&quot;{0}&quot;, WorkItemArea) }, {&quot;MyCo.Client&quot;, &quot;n/a&quot;},
{&quot;MyCo.Project&quot;, &quot;BAU&quot;} }]"
DisplayName="Create Work Item" Title="[String.Format(&quot;Build Failure in Build: {0}&quot;, BuildDetail.BuildNumber)]"
Type="[&quot;Bug&quot;]" />
<pre>

There’s a lot of escaping to make it valid XML so it’s best to edit in the designer!

Oct 172011
 

Web.config Transformations

A great feature in Web Deploy (Microsoft’s latest website publishing technology) is the ability to transform your default web.config to a customised version, driven by the configuration being built. So you can have different configurations for Test, Staging and Production etc. with transformation rules that change only the settings that differ in each of those environments.

To add web.config transformations in Visual Studio, simply right-click your web.config and select Add Config Transforms. If the option is disabled, you probably need to add a new configuration to the solution using the Configuration Manager. The transformation language is XML Document Transform (XDT) which has been covered very well by Scott Hanselman and the syntax is fully documented.

You may be surprised to learn that TFS build does not automatically apply your web.config transformations when it generates the _PublishedWebsites folder containing your compiled web application. This is an inconvenience if you aren’t using the Web Deployment Tool to deploy the application, and just want a package of files customised to the right environment. The fix for this is fairly straightforward: to get TFS build to run the transformations you need to pass some additional arguments to MSBuild telling it to use the new Web Publishing Pipeline. This can be done using the build definition’s MSBuild Arguments parameter (if you are using the default build template or a custom template derived from it). Simply add /p:UseWPP_CopyWebApplication=true /p:PipelineDependsOnBuild=false as shown below.

* * * * *

App.config Transformations

Web.config transformations are great, but you can also transform app.config files. You need to make some changes to the MSBuild project file to associate the configs and import a transformation MSBuild script, but that’s all. Here’s how to do it using the neat solution by Sayed Ibrahim Hashimi:

First, if your project doesn’t have an app.config file, add one using the provided template (under the General category when you choose to add a new item to a project). Next, add further app.*.config files using the same template – one for each configuration in the project except Debug.

Add transforms to the configuration-specific files. For testing, you could use something simple like:


<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<appSettings>
<add key="MyNewKey" value="MyNewValue" xdt:Transform="Insert"/>
</appSettings>
</configuration>

Next, associate the config files by editing the project file (.csproj or .vbproj) either in a text editor or in Visual Studio (but you will need to unload the project first). Locate each app.*.config reference like…


<None Include="app.Release.config" />

…and change it to…


<None Include="app.Release.config">
<DependentUpon>App.config</DependentUpon>
</None>

Next, add the following just above the final Project closing tag:


<Import Project="AppConfig.Transformation.targets" />

Finally, download the script from Sayed Ibrahim Hashimi’s blog and save it as AppConfig.Transformation.targets to the same location as your project file. Build the project and you should see the transformed app.config in the output folder.

We use this file in several projects so deploy it to C:\Program Files\MSBuild on each development and build machine and reference that folder using $(MSBuildExtensionsPath32), instead of adding it to every project.