How to enforce a rule on Area/Iteration Path

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.

Leave a Reply