Rules To Better TFS Customization

​Since 1990, SSW has supported the developer community by publishing all our best practices and rules for everyone to see. 

If you still need help, visit Application Lifecycle Management and book in a consultant.

Hold on a second! How would you like to view this content?
Just the title! A brief blurb! Gimme everything!
  1. Do you start from a built-in process template?

    ​TFS 2012 includes 3 built-in process templates:
    BuiltInTemplates.png
    Figure: built-in process templates in TFS 2​012Instead of starting from scratch, you should always choose one of these built-in templates to do your own customization. It will depend on the target process for you to choose which one, for small and simple process, Scrum and Agile templates are recommended; for formal and complex process, choose the CMMI template.​
    ​Using an existing process template will save you a lot of time because
    •  It has the structure setup already, all you need to do is to make modifications and upload the template back to the server again.   
    • All the built-in reports could be used as a template for your customization, this will save you a lot of time from creating a new report​.
     
  2. Do you Check-in your process template into source control?

    ​Customized process template is very important asset for your team, you should use Source Control to store the work-in-progress template so you can track the changes and avoid mistakes. 
    CheckInTemplateIntoSourceControl.png
    Figure: customized process template in source control​

    ​You should also keep a version history log in ProcessTemplate.xml so you can track the deployed version easily.
    Figure: ProcessTemplate.xml with version history log 
  3. Do you use Global List?

    ​​Global list could be referenced in multiple work item types, if you are using the same list in different places and want to keep the drop down items con​sistent, global list is the best practise. 

    ​​​​​<FIELD name="Discipline" refname="Microsoft.VSTS.Common.Discipline" type="String">
      <HELPTEXT>The discipline to which the task belongs</HELPTEXT>
      <ALLOWEDVALUES expanditems="true">
        <LISTITEM value="Development" />
        <LISTITEM value="Test" />
        <LISTITEM value="Project Management" />
        <LISTITEM value="Requirements" />
        <LISTITEM value="Architecture" />
        <LISTITEM value="Release Management" />
      </ALLOWEDVALUES>
    </FIELD>

    ​​Figure: Bad Example – embed the list items in work item type definition

    <?xml version="1.0" encoding="utf-8"?>
    <gl:GLOBALLISTS  xmlns:gl="http://schemas.microsoft.com/VisualStudio/2005/workitemtracking/globallists">
      <GLOBALLIST name="Disciplines">
        <LISTITEM value="Architecture" />
        <LISTITEM value="Requirements" />
        <LISTITEM value="Development" />
        <LISTITEM value="Release Management" />
        <LISTITEM value="Project Management" />
        <LISTITEM value="Test" />
      </GLOBALLIST>
    </gl:GLOBALLISTS>​

    Figure: Good Example - Save above as GlobalList.xml file​ 

    <FIELD name="Discipline" refname="Microsoft.VSTS.Common.Discipline" type="String">
      <HELPTEXT>The discipline to which the task belongs</HELPTEXT>
      <ALLOWEDVALUES>
        <GLOBALLIST name="Disciplines" />
      </ALLOWEDVALUES>
    </FIELD>​​

    Figure: Good Example - Reference a global list in work item type definition​​Note: Global list is defined at the Team Project Collection level and it needs to be uploaded before the process template could be uploaded. ​ ​​​​​​​​
    Read more about Do you use Global List?
  4. Do you have a WitAdmin script to import work item definitions?

    ​You will need to update your work item types very frequently once the customization process is started, make sure you have a script like below in your solution, this will help you to upload your process template quickly with one click, which make your development more efficient.
    ​ECHO OFF
    ECHO ***********Importing new definitions*******************************
    ECHO ON
    witadmin importwitd /collection:http://%1:8080/tfs/%2 /p:%3 /f:"..\CN.SAC.TfsProcessTemplate\WorkItem ​Tracking\TypeDefinitions\Requirement.xml"
    witadmin importwitd /collection:http://%1:8080/tfs/%2 /p:%3 /f:"..\CN.SAC.TfsProcessTemplate\WorkItem Tracking\TypeDefinitions\Task.xml"
    witadmin importwitd /collection:http://%1:8080/tfs/%2 /p:%3 /f:"..\CN.SAC.TfsProcessTemplate\WorkItem Tracking\TypeDefinitions\Issue.xml"

    ​ECHO OFF​
    ECHO ***********Importing new definitions*******************************
    ECHO ON
    witadmin importwitd /collection:http://%1:8080/tfs/%2 /p:%3 /f:"..\CN.SAC.TfsProcessTemplate\WorkItem Tracking\TypeDefinitions\Requirement.xml"
    witadmin importwitd /collection:http://%1:8080/tfs/%2 /p:%3 /f:"..\CN.SAC.TfsProcessTemplate\WorkItem Tracking\TypeDefinitions\Task.xml"
    witadmin importwitd /collection:http://%1:8080/tfs/%2 /p:%3 /f:"..\CN.SAC.TfsProcessTemplate\WorkItem Tracking\TypeDefinitions\Issue.xml"​​ ​
    Figure: quick deployment script for process template – Upd​ateProcessTemplate.bat With above script, you can execute the command like below UpdateProcessTemplate.bat <serverAddress> <collectionName> <projectName> ​​​So, just one command, all of your customized work item types will be updated on the server.

  5. Do you use PowerShell script to create duplicated work item types?

    ​Sometime you will need to create duplicate work item types, e.g. a task work item may be clones as PlatformDepTask, SystemDepTask; both of these task work items are sharing the same fields, workflow or layouts, but they are configured to be accessible by different department or there is some other minor differences.

    You should create a WIT template and use a place holder for the difference, e.g. <WORKITEMTYPE name="xxxxDepNamexxxxTask">

      …

    </WORKITEMTYPE>
    Figure: WIT template with place holder  ​

    Then use the following PowerShell script to automatically clone the work item and replace the placeholder with actual text.

    ​$original_file = '..\WorkItem Tracking\TypeDefinitions\Task_Template_DONOTInstall.xml'

    $destination_file =  '..\WorkItem Tracking\TypeDefinitions\Task_ PlatformDep.xml'
    (Get-Content $original_file) | Foreach-Object {
        $_ -replace "xxxxDepNamexxxx", "PlatformDep"
        } | Set-Content $destination_file -Encoding UTF8

    $destination_file =  '..\WorkItem Tracking\TypeDefinitions\Task_SystemDep.xml'
    (Get-Content $original_file) | Foreach-Object {
       $_ -replace "xxxxDepNamexxxx", "SystemDep"
       } | Set-Content $destination_file -Encoding UTF8
    Figure: PowerShell script to create duplicate WITs and replace the place holder with actual data​Note: if you are using non-English characters in your template, make sure you add –Encoding UTF8 otherwise you will have some encoding problems. ​​​
  6. Do you control the drop down list value for Assigned To field?

    ​The default WIT doesn’t control the valid drop down items in Assigned To filed, this will introduce unnecessary items to be shown in the list which will make your users confused, e.g. TFSBUILD, tfsBuildService should never be used to assign a job.
    UnnecessaryValue.png
    Figure: Bad Example – shown unnecessary values
    You can add the following XML in the Assigned To filed definition to control the valid values​:​​​​​​​​​​
    <FIE​LD name="Assigned To" refname="System.AssignedTo" type="String" reportable="dimension" syncnamechanges="true">
      ​<ALLOWEXISTINGVALUE />
      ​<REQUIRED />
      <ALLOWEXISTINGVALUE />
      <VALIDUSER />
      <ALLOWEDVALUES expanditems="true" filteritems="excludegroups">
            <LISTITEM value="Active" />
            <LISTITEM value="[project]\xxxxDepNamexxxxGroup" />
      </ALLOWEDVALUES>
    </FIELD>​ ​   
    Figure: Use ALLOWEDVALUES to control the values in Assigned to field

    ShowNecessaryUser.png
    Figure: Good Example – shown necessary values
  7. Do you remove the need to type “/tfs” ?

    Many clients that complain when they type: tfs.northwind.com
    ...and then see ‘Server Error 403 – Forbidden: Access is denied’​

    It is not a nice experience that in 2015 the out-of-the-box requirement is still to type "/tfs".

    tfs-url-1.jpg
    Figure: Bad example - A horrible first experience... did I get the URL wrong? Is the server down?​

    Note: The better out-of-the-box experience for Exchange OWA is to type https://mail.ssw.com.au/
    ...and it redirects to
    https://mail.ssw.com.au/owa/auth/logon.aspx?replaceCurrent=1&url=https%3a%2f%2fmail.ssw.com.au%2fowa%2f.

    So fix the nasty out-of-the-box experience.​

    tfs-url-2.png
    Figure: Option 1 – This is one way. Include some text to tell devs that they can remove the need for /tfs - on the Application Tier page specify port 80 and an empty Virtual Directory
    tfs-url-2.png
    Figure: Option 2 – This is another way. In IIS add the redirect to remove the need to type “/tfs” (recommended)​​