Archive for the ‘Work Item Tracking’ Category

How to enforce a rule on Area/Iteration Path

Tuesday, February 17th, 2009

Another pitfall I encountered while setting up our new team project was how to make sure people didn’t cop out and leave them at the default (root, aka useless) value.  With Areas I may have been able to set up some weird non-inheriting permission scheme, but I needed to solve this problem for Iterations anyway, so I turned to the web. 

Unfortunately, the standard answer from the product team didn’t work for me. 

<FIELD type="Integer" name="AreaID" refname="System.AreaId"> <HELPTEXT>AreaID</HELPTEXT> </FIELD> <FIELD type="Integer" name="IterationID" refname="System.IterationId"> <HELPTEXT>IterationID</HELPTEXT> </FIELD> <FIELD type="String" name="Product Area - Validation" refname="Coatue.ProductAreaValidation"> <HELPTEXT>Hidden field used to validate Product Area</HELPTEXT> <WHEN field="System.AreaId" value="84"> <COPY from="value" value="Restricted" /> </WHEN> <PROHIBITEDVALUES> <LISTITEM value="Restricted" /> </PROHIBITEDVALUES> </FIELD> <FIELD type="String" name="Sprint or Release - Validation" refname="Coatue.SprintPathValidation"> <HELPTEXT>Hidden field used to validate Sprint or Release</HELPTEXT> <WHEN field="System.IterationId" value="84"> <COPY from="value" value="Restricted" /> </WHEN> <PROHIBITEDVALUES> <LISTITEM value="Restricted" /> </PROHIBITEDVALUES> </FIELD>

It successfully blocked work items that had Area/Iteration paths I didn’t want, but I’d continue to get validation errors after I changed the paths in the form to something else.

At this point I started to wonder whether the AreaId and AreaPath fields were as intricately tied as I thought they were.  After all, I didn’t have any rules saying to update one when the other changed.  (The documentation kinda implies this but doesn’t spell out the mechanism.)  So I decided to test at the object model level: Get-TfsServer OM wrapper to the rescue!

PS C:\Users\rberg> $tfs = get-tfsserver njtfs –all
PS C:\Users\rberg> $bug = $tfs.wit.GetWorkItem(1333)
PS C:\Users\rberg> $bug.AreaId; $bug.IterationId
84
84  

 

PS C:\workspaces\ws1> $bug.AreaPath; $bug.IterationPath
Test-ConchangoV2\test
Test-ConchangoV2\Release 1\Sprint 4

PS C:\Users\rberg> $bug.fields | where { $_.name.contains("Validation") } | select value
Value
-----
Restricted Restricted                                                                                                                       

PS C:\Users\rberg> $bug.AreaId = 104; $bug.IterationId = 91
PS C:\workspaces\ws1> $bug.AreaPath; $bug.IterationPath
Test-ConchangoV2\test
Test-ConchangoV2\Release 1\Sprint 4 

PS C:\Users\rberg> $bug.fields | where { $_.name.contains("Validation") } | select value
Value
-----
Restricted
Restricted

Nope, not a synchronization issue between path on the form <–> underlying ID.  Looks like I really do need to tweak Gregg’s advice.  All you need is a corresponding WHENNOT rule to cancel out each WHEN rule as it’s no longer needed.  Here’s what the hidden validator for Area looks like now:

<FIELD type="String" name="Product Area - Validation" refname="Coatue.ProductAreaValidation"> <HELPTEXT>Hidden field used to validate Product Area</HELPTEXT> <WHEN field="System.AreaId" value="84"> <COPY from="value" value="Restricted" /> </WHEN> <WHENNOT field="System.AreaId" value="84"> <COPY from="value" value="Ok" /> </WHENNOT> <PROHIBITEDVALUES> <LISTITEM value="Restricted" /> </PROHIBITEDVALUES> </FIELD>

Make the same change for Iteration and you’re golden.

How to prevent people from opening new bugs

Tuesday, February 17th, 2009

We’re in the middle of transitioning to a new team project.  On the source control side, Microsoft has made a huge investment to support arbitrary renames throughout the tree.  No reason to mess with TFS->TFS migration when I can move the native items!  On the other hand, migrating work items across team projects is notoriously tricky.  I decided it would be easiest to steadily phase out the work items remaining in the old project while forcing people to open new issues in the new project.

Being relatively new to WIT customization, the answer wasn’t immediately obvious.  TFS doesn’t let you stick an ALLOWEDVALUES rule on fields like System.CreatedDate that the system populates on creation.  And anything you stick on a user-editable field will inevitably block users from navigating an existing work item through the rest of its legitimate workflow.  The path I took was modifying the initial transition from “”.  XML excerpt:

<TRANSITION from="" to="Active"> <REASONS> <REASON value="Build Failure" /> <DEFAULTREASON value="New" /> </REASONS> <FIELDS> <FIELD refname="Microsoft.VSTS.Common.ActivatedBy"> <COPY from="currentuser" /> <VALIDUSER /> <REQUIRED /> </FIELD> <FIELD refname="Microsoft.VSTS.Common.ActivatedDate"> <SERVERDEFAULT from="clock" /> </FIELD> <FIELD refname="System.AssignedTo"> <DEFAULT from="currentuser" /> </FIELD> <FIELD refname="System.Title"> <ALLOWEDVALUES> <LISTITEM value="Before 2009-02-12" /> </ALLOWEDVALUES> </FIELD> </FIELDS> </TRANSITION>

Most of this comes from the stock MSF Agile v4.2 template; the System.Title field with the strange rule toward the end is my addition.  Doesn’t really matter what you put in the value, so long as you don’t tell your users what it is :)