# Thursday, 06 November 2014

My blog posts are like really terrible buses, you wait 8 weeks for one and now I’ve finally got a little time (3 hours on a train home from the midlands) so 2 or 3 are going to arrive at once.

A process template customisation I do regularly for customers is adding a Team field to scope Work Items to teams in TFS 2012 and TFS 2013.  Microsoft have detailed the process here so it’s not a particularly controversial thing to do and I believe it provides a better experience when you have multiple teams working against a central backlog.

I blogged recently about how to use PowerShell to automate the process of adding a team field.

I performed the customisation for three companies in the last couple of months and bumped into a some issues with Team Web Access in particular.  Even though adding a Team field is very much a valid thing to do, there can be a couple of wrinkles to iron out.

The first issue came as a bit of a shock.  The background to the problem is this - a customer has been happily using TFS 2013 on a pathfinder project with a single team.  Things have gone well and so they wish to roll out the tool to about 5 other teams.

We worked together to create a slightly customised process template which added some further hierarchy to the standard Visual Studio Scrum 2013 process template.  Without thinking, I started work using a Visual Studio Scrum 2013.3 template and when I tried to upload it to the customer’s server we had some errors as Update 3 added all sorts of test related artefacts that weren’t available with the customer’s TFS 2013 RTM version. 

That wasn’t the issue, however and I quickly made the changes to an RTM version of the VS Scrum template and uploaded it successfully.  We then created a central project to house the company’s portfolio backlog (I must add that to my things to blog about!).

We were to resume working on the new project a few days later but before then I received a frantic email from the pathfinder team saying that whenever they tried to edit an existing Work Item using the Team Web Access client they received the following error:

Team Foundation Error

The server operation failed, (Value cannot be null. Parameter name:key).

I quizzed the team on whether they had changed anything on the pathfinder project as templates are like cookie cutters, once you cut out the cookie, it doesn’t matter what you do to the cutter, it doesn’t effect the cookies you produced previously.

I went onsite and pulled down the processconfiguration.xml, categories.xml and the Work Item definitions for the pathfinder project.  Nothing had changed!

Some experimentation confirmed that uploading a new process template configured to use a custom team field had broken Team Web Access for an existing project.  Clearly that shouldn’t happen and although I we could have battled through and fixed it we took the decision to update the TFS 2013 RTM server (without knowing for sure that Update 2/3/4 had fixed the problem).  We took the decision to go with Update 2 as we weren’t quite ready for the new test artefacts and I’d recently been badly burned by an issue with Update 3 massively inflating the collection database (another thing to add to my list of blog posts to write).

The upgrade to Update 2 only caused us a short period of downtime and it was something we were planning on doing soon anyway.  The problem was resolved immediately so it was obviously a known bug which was addressed in the first update for TFS 2013 (there was no update 1 for TFS 2013).

A similar but not identical issue is discussed in the MSDN forum post here.

There are still 90 minutes left of my train journey so I may as well write up the next instalment.

Cheers,

Richard



.

Thursday, 06 November 2014 19:00:00 (GMT Standard Time, UTC+00:00)  #    Comments [0]


# Friday, 12 September 2014

One of the Team Foundation Server Process Template customisations I do frequently is changing a project to make use of a custom team field rather than the default Area Path to scope Work Items to teams.

If you haven’t made use of teams in TFS 2012 or TFS 2013 yet then check out these links

Multiple Teams with Microsoft Team Foundation Server 2012 & Visual Studio Scrum

TFS 2013: Collaborate using team resources

If you don’t know what is involved in customisation then you need to check out this page.

Customize a team project to support team fields

Now, you can, as with any process update, make changes offline and any subsequent projects created using that template will see the changes.  Or, you can update an existing in-flight project with template changes. 

It’s not particularly difficult to change your template to make use of a team field but it is time consuming so I wrote a PowerShell script to do it both to save me time and to play around with using PowerShell to do XML transformations.

My script downloads the required files from a Visual Studio Scrum 2013 project, backs them up, performs an XML Transform on them and uploads them to your project.  If you are using a different process template then you will need to edit the XML transforms and the selected Work Item definitions but the technique is the same.

You can call the script Add-Teams.ps1 from the command line and provide 3 parameters

Add-Teams.ps1 “http://TFS2013:8080/tfs/DefaultCollection” MyProject “C:\TemplateUpdates”

Defaults are specified at the beginning of the script so if you plan to run it using PowerShell ISE for example, then simply change the values.

        #TFS Collection Url
        [string]$CollectionUrl =          "http://TFS2013:8080/tfs/DefaultCollection",
        #Name of the TFS Team Project to transform
        [string]$TeamProjectName =        "MyProject",
        #Working folder to store the XML transforms, downloaded files and backup
        [string]$WorkingFolder =          "C:\TemplateUpdates" 

There is some (hopefully) useful logging throughout the script which uses write-verbose, so if you want to turn it on then  give the script a –verbose flag when you run it.

The script

First we create a function called Transform-XML that takes an XML file and a transform file to apply.  We’ll use it to alter the Work Item definitions, the Process Configuration and add a Global List.


function Transform-XML 
{
     Param (
            [Parameter(Mandatory=$True)][ValidateNotNull()]$Wit,
            [Parameter(Mandatory=$True)][ValidateNotNull()]$Tfm
        )


Next, the necessary Work Item definitions (Product Backlog Item, Task, Bug, Feature & Test Plan) are downloaded from your project using WitAdmin.exe (usually found in C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\Witadmin.exe)


# Export Work Item definitions 
write-Verbose "Exporting PBI definition"
& $WitAdmin exportwitd /collection:$CollectionUrl /p:$TeamProjectName /f:$PBIDefinition /n:"Product Backlog Item"
write-Verbose "Exporting Task definition"
& $WitAdmin exportwitd /collection:$CollectionUrl /p:$TeamProjectName /f:$TaskDefinition /n:"Task"
write-Verbose "Exporting Bug definition"
& $WitAdmin exportwitd /collection:$CollectionUrl /p:$TeamProjectName /f:$BugDefinition /n:"Bug"
write-Verbose "Exporting Feature definition"
& $WitAdmin exportwitd /collection:$CollectionUrl /p:$TeamProjectName /f:$FeatureDefinition /n:"Feature"
# Required if using TFS 2013 Update 3 or later 
write-Verbose "Exporting Test Plan definition"
& $WitAdmin exportwitd /collection:$CollectionUrl /p:$TeamProjectName /f:$TestPlanDefinition /n:"Test Plan"

# Export Process Configuration
write-Verbose "Exporting Process Configuration"
& $WitAdmin exportprocessconfig /collection:$CollectionUrl /p:$TeamProjectName /f:$PCDefinition 

# Export Global List 
write-Verbose "Exporting Global List"
& $witadmin exportgloballist /collection:$CollectionUrl /f:$GLDefinition 

The we copy all the downloaded files into a backup directory.  If your Team project was called MyProject then all the files would be downloaded to C:\TemplateUpdates\MyProject and a backup would be copied to C:\TemplateUpdates\MyProjectBackup\110914.161115 where the date is 11\09\2014 and the time is 16:11 and 15 seconds.  This way, if anything goes wrong, you have your original files to upload.


# Create backup of process files 
write-Verbose "Backing up process files"
$timestamp = Get-Date -UFormat "%d%m%y.%T" | foreach {$_ -replace ":", ""}

Copy-Item -Path $ProjectFolder -Container -Destination "$($ProjectFolder)Backup\$timestamp" -Recurse -force

After that we call the Transform-XML function against the required files

try
{
    #Try transforming the required files and exit the script if there are any problems
    
    # Add Global List 
    write-Verbose "Adding Team Global List"
    Transform-XML $GLDefinition $GLTransform

    # Update Work Item Definitions to add new Team field and include on form 
    write-Verbose "Updating PBI Definition"
    Transform-XML $PBIDefinition $WITTransform
    write-Verbose "Updating Task Definition"
    Transform-XML $TaskDefinition $WITTransform
    write-Verbose "Updating Bug Definition"
    Transform-XML $BugDefinition $WITTransform
    write-Verbose "Updating Feature Definition"
    Transform-XML $FeatureDefinition $WITTransform
    # Required if using TFS 2013 Update 3 or later
    write-Verbose "Updating Test Plan Definition"
    Transform-XML $TestPlanDefinition $WITTransform

    # Update Process Template to make use of new Team field instead of AreaPath 
    write-Verbose "Updating Process Configuration"
    Transform-XML $PCDefinition $PCTransform
}

The XML transform for a Work Item looks like this for example


<?xml version="1.0"?>
<witd:WITD xmlns:witd="http://schemas.microsoft.com/VisualStudio/2008/workitemtracking/typedef" xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <WORKITEMTYPE name="Bug">
    <FIELDS>
    <!-- If the team field has already been added then remove it first-->
    <FIELD name="Team" xdt:Transform="Remove"  xdt:Locator="Match(name)" />
      <FIELD name="Team" refname="RippleRock.Scrum.Team" type="String" reportable="dimension" xdt:Transform="Insert">
        <HELPTEXT>Name of the team that will do the work.</HELPTEXT>
        <ALLOWEXISTINGVALUE />
        <ALLOWEDVALUES >
          <GLOBALLIST name="Teams" />
        </ALLOWEDVALUES >
        <DEFAULT from="value" value="Unassigned" />
      </FIELD>
    </FIELDS>
    <FORM>
      <Layout>
      <Group>
      <Column>
        <Group Label="Status">
          <Column PercentWidth="100">
          <!-- If the team field has already been added then remove it first-->
            <Control FieldName="RippleRock.Scrum.Team" xdt:Transform="Remove"  xdt:Locator="Match(FieldName)" />
            <Control FieldName="RippleRock.Scrum.Team" Type="FieldControl" Label="Team" LabelPosition="Left" EmptyText="&lt;None&gt;" xdt:Transform="Insert" />
          </Column>
        </Group>
        </Column>
        </Group>
      </Layout>
    </FORM>
  </WORKITEMTYPE>
</witd:WITD>


This adds a field called RippleRock.Scrum.Team to the Work Item and then adds a Field Control at the end of the Status group on the Work Item form.  I added an additional Remove transform for both elements so that if you run the script against an item that already has a Team field then it will be replaced.

Finally, we import all our definitions and we should be good to go.


# Import Global List 
write-Verbose "Importing Global List"
& $witadmin importgloballist /collection:$CollectionUrl /f:"$ProjectFolder\GlobalList.xml"

# Import Work Item definitions 
write-Verbose "Importing PBI definition"
& $WitAdmin importwitd /collection:$CollectionUrl /p:$TeamProjectName /f:"$ProjectFolder\WorkItem Tracking\TypeDefinitions\ProductBacklogItem.xml" 
write-Verbose "Importing Task definition"
& $WitAdmin importwitd /collection:$CollectionUrl /p:$TeamProjectName /f:"$ProjectFolder\WorkItem Tracking\TypeDefinitions\Task.xml" 
write-Verbose "Importing Bug definition"
& $WitAdmin importwitd /collection:$CollectionUrl /p:$TeamProjectName /f:"$ProjectFolder\WorkItem Tracking\TypeDefinitions\Bug.xml" 
write-Verbose "Importing Feature definition"
& $WitAdmin importwitd /collection:$CollectionUrl /p:$TeamProjectName /f:"$ProjectFolder\WorkItem Tracking\TypeDefinitions\Feature.xml" 
# Required if using TFS 2013 Update 3 or later
write-Verbose "Importing Test Plan definition"
& $WitAdmin importwitd /collection:$CollectionUrl /p:$TeamProjectName /f:"$ProjectFolder\WorkItem Tracking\TypeDefinitions\TestPlan.xml"

# Import Process Configuration 
write-Verbose "Importing Process Configuration"
& $WitAdmin importprocessconfig /collection:$CollectionUrl /p:$TeamProjectName /f:"$ProjectFolder\WorkItem Tracking\Process\ProcessConfiguration.xml"


Remember to follow the steps in the “Configure Team Settings” section of the Customize a team project to support team fields to alter how Work Items show up on the team backlogs.

image

Download the script and the transforms here.

I hope it saves you some time.

Cheers,

Richard



.

Friday, 12 September 2014 07:00:00 (GMT Daylight Time, UTC+01:00)  #    Comments [0]