Mapping Team Foundation Server Process Templates, example Agile 4.3 to Agile 5.0

We recently discussed the changes that have been happening in the Team Foundation Server Team Project process templates from 2005 to 2008 and more recently to 2010, not to mention upcoming changes in future versions.

Would it not be great to have a quick reference poster to illustrate the changes? It would definitely help anyone who is considering to use the TFS Integration Tools (Platform) to migrate from one process template to another and would need to define a field map for the Work Item Tracking types. Looking at TFS Integration Tools and scrolling down until you find the section Process Templates, you will notice that the community has been busy creating maps for a number of possible process templates.

Unfortunately someone’s map is not everyone’s treasure map, because interpretation and business rules vary from environment to environment. In addition we have not resolved out initial “ask” for a quick reference map and therefore need a way to define the differences and possible mappings. What we have decided, however, is to defer the creation of the difference definition and visualization thereof and raise it as an Epic in one of the upcoming projects we are going to discuss on this blog shortly.

In this blog we will discuss the process of creating a potential mapping and eventually a visualization.

The basic steps for our investigation and planning for a TFS Integration Tools (Platform) migration are:

  • Analyse source (understand the differences)
  • Analyse target (understand the differences)
  • Create a mapping from source to target

If we are looking at a bi-directional synchronization A<->B, instead of one-way migration A->B, we would need to create a second map for the B->A direction. In this post we are assuming a A->B migration  only.

Understand the differences

Using the Process Editor from the Team Foundation Server Power Tools, we investigate the process templates and define a potential map for the various work item types. Other useful tools include WinDiff and other file comparison tools.

I created an Excel workbook and started creating a mapping for various work item types. The following extract shows a comparison of the Agile 4.3 (2008) and Agile 5.0 (2010) “Bug” work item type and one of the many potential mappings. In my case I decided to map all fields that occur in both process template on a 1:1 basis, aggregate the description and issue fields from the Agile 4.3 template to the shared steps field ion the Agile 5.0 template, and ignore a number of fields, such as the test name. The possible variations are vast and beyond the scope of this post Smile


Create a Field Map from Process Template to Process Template

Once we have an understanding of the differences and the mappings, based on business rules, we can start pondering over how we migrate from the one to the other. If we opt for the TFS Integration Tools (Platform) we have to define a session configuration that defines the field mapping and field values. Related blog posts include Mapping Work Item Fields and Values, @@MISSINGFIELD@@, Aggregated Fields, Why are my field mappings only working one way, and more. You should also peruse the configuration guide that ships with the TFS Integration Tools (Platform).

A great tool, evolving on Codeplex, is the TFS Integration Field Mapping Tool. It allows you to create a mapping file by connecting to team projects or work item files and selecting an Auto Map or by manually selecting the relevant fields and associated mapping.


The result is a FieldMaps definition which you can Copy+Paste to a session configuration file in the TFS Integration Tools (Platform).

    1: <!--Replace the WorkItemTypes node and FieldMaps node in the TFS Integration Platform mapping file with the content of this file-->
    2: <WorkItemTypes>
    3:   <WorkItemType LeftWorkItemTypeName="Bug" RightWorkItemTypeName="Bug" fieldMap="BugToBugFieldMap" />
    4: </WorkItemTypes>
    5: <FieldMaps>
    6:   <FieldMap name="BugToBugFieldMap">
    7:     <MappedFields>
    8:       <MappedField MapFromSide="Left" LeftName="Microsoft.VSTS.Common.ActivatedBy" RightName="Microsoft.VSTS.Common.ActivatedBy" />
    9:       <MappedField MapFromSide="Left" LeftName="Microsoft.VSTS.Common.ActivatedDate" RightName="Microsoft.VSTS.Common.ActivatedDate" />
   10:       <MappedField MapFromSide="Left" LeftName="System.AreaPath" RightName="System.AreaPath" />
   11:       <MappedField MapFromSide="Left" LeftName="System.AssignedTo" RightName="System.AssignedTo" />
   12:       <MappedField MapFromSide="Left" LeftName="System.ChangedBy" RightName="System.ChangedBy" />
   13:       <MappedField MapFromSide="Left" LeftName="System.ChangedDate" RightName="System.ChangedDate" />
   14:       <MappedField MapFromSide="Left" LeftName="Microsoft.VSTS.Common.ClosedBy" RightName="Microsoft.VSTS.Common.ClosedBy" />
   15:       <MappedField MapFromSide="Left" LeftName="Microsoft.VSTS.Common.ClosedDate" RightName="Microsoft.VSTS.Common.ClosedDate" />
   16:       <MappedField MapFromSide="Left" LeftName="System.CreatedBy" RightName="System.CreatedBy" />
   17:       <MappedField MapFromSide="Left" LeftName="System.CreatedDate" RightName="System.CreatedDate" />
   18:       <MappedField MapFromSide="Left" LeftName="Microsoft.VSTS.Build.FoundIn" RightName="Microsoft.VSTS.Build.FoundIn" />
   19:       <MappedField MapFromSide="Left" LeftName="System.History" RightName="System.History" />
   20:       <MappedField MapFromSide="Left" LeftName="System.Id" RightName="System.Id" />
   21:       <MappedField MapFromSide="Left" LeftName="Microsoft.VSTS.Build.IntegrationBuild" RightName="Microsoft.VSTS.Build.IntegrationBuild" />
   22:       <MappedField MapFromSide="Left" LeftName="System.IterationPath" RightName="System.IterationPath" />
   23:       <MappedField MapFromSide="Left" LeftName="Microsoft.VSTS.Common.Priority" RightName="Microsoft.VSTS.Common.Priority" />
   24:       <MappedField MapFromSide="Left" LeftName="System.Reason" RightName="System.Reason" />
   25:       <MappedField MapFromSide="Left" LeftName="Microsoft.VSTS.Common.ResolvedBy" RightName="Microsoft.VSTS.Common.ResolvedBy" />
   26:       <MappedField MapFromSide="Left" LeftName="Microsoft.VSTS.Common.ResolvedDate" RightName="Microsoft.VSTS.Common.ResolvedDate" />
   27:       <MappedField MapFromSide="Left" LeftName="Microsoft.VSTS.Common.ResolvedReason" RightName="Microsoft.VSTS.Common.ResolvedReason" />
   28:       <MappedField MapFromSide="Left" LeftName="System.State" RightName="System.State" />
   29:       <MappedField MapFromSide="Left" LeftName="Microsoft.VSTS.Common.StateChangeDate" RightName="Microsoft.VSTS.Common.StateChangeDate" />
   30:       <MappedField MapFromSide="Left" LeftName="System.Title" RightName="System.Title" />
   31:     </MappedFields>
   32:   </FieldMap>
   33: </FieldMaps>

The tool does not yet support the field aggregation feature … at least the version I downloaded recently … and we have to manually edit the configuration. The field aggregation, as per the proposed mapping in our workbook extract above, is defined in lines 11-16 in the code extract below. In addition the example replaces the explicit field mappings created by the TFS Integration Field Mapping Tool, with a *->* mapping in line 9. In essence we are saying that the migration should map all fields from the left (source) to the right (target) and aggregate the description and issue fields.

    1: ... snip ... configuration file extract
    2:     <WITSessionCustomSetting>
    3:       <WorkItemTypes>
    4:         <WorkItemType LeftWorkItemTypeName="Bug" RightWorkItemTypeName="Bug" fieldMap="Bug2BugFieldMap" />
    5:       </WorkItemTypes>
    6:       <FieldMaps>
    7:         <FieldMap name="Bug2BugFieldMap">
    8:           <MappedFields>
    9:             <MappedField LeftName="*" RightName="*" MapFromSide="Left" valueMap=""/>
   10:           </MappedFields>
   11:           <AggregatedFields>
   12:             <FieldsAggregationGroup MapFromSide="Left" TargetFieldName="Microsoft.VSTS.TCM.ReproSteps" Format="[Description: '{0}'] {Issue: '{1}'}">
   13:               <SourceField Index="0" SourceFieldName="System.Description" valueMap=""/>
   14:               <SourceField Index="1" SourceFieldName="Microsoft.VSTS.Commin.Issue" valueMap=""/>
   15:             </FieldsAggregationGroup>
   16:           </AggregatedFields>
   17:         </FieldMap>
   18:       </FieldMaps>
   19:     </WITSessionCustomSetting>
   20: ... snip ... configuration file extract

You can further refine the configuration by adding the following mapped fields definitions for the fields that only exist on the left (source) and that hypothetically we are not interested in:

    1: <MappedField LeftName="Microsoft.VSTS.Common.Triage" RightName="" MapFromSide="Left"/>
    2: <MappedField LeftName="Microsoft.VSTS.Common.Rank" RightName="" MapFromSide="Left" />
    3: <MappedField LeftName="Microsoft.VSTS.Test.TestName" RightName="" MapFromSide="Left" />
    4: <MappedField LeftName="Microsoft.VSTS.Test.TestId" RightName="" MapFromSide="Left" />
    5: <MappedField LeftName="Microsoft.VSTS.Test.TestPath" RightName="" MapFromSide="Left" />

Perhaps you know of an easier and more effective way? Your candid comments and feedback will be most appreciated.