Best Practices for Workspaces

One Team System concept that a number of VSS users struggle with is workspaces because there doesn’t appear to be a comparable concept under VSS.

This isn’t entirely true because by setting working folders in VSS you are effectively establishing a “default” workspace and you can create multiple workspaces by performing gets into alternate directories. However, unlike Team System these workspaces aren’t named or managed.

So how can you get the most value out of Team System workspaces?

Read the Workspaces section of High-level Best Practices in Software Configuration Management by Laura Wingerd & Christopher Seiwald from Perforce Software. In this SCM tool agnostic article Laura and Christopher outline five course-grained best practices for workspaces:

  1. Don’t share workspaces. A workspace should have a single purpose, … for a single developer. Each developer owns their own workspaces and they should not be stored in a shared location where other developers can access (or worse modify it).
  2. Don’t work outside of managed workspaces. Your SCM system can only track work in progress when it takes place within managed workspaces. Under Team System this really means that all changes should be performed using Team System (either through Source Control Explorer, the tf command-line, or custom applications that use the TFS API) rather than using Windows Explorer or other file system commands.
  3. Don’t use jello views. A file in your workspace should not change unless you explicitly cause the change. Although Windows supports symbolic links (of a sort) they aren’t often used so this is less of an issue, but conceptually it is still important that developers are in control of and understand the current state of their workspace.
  4. Stay in sync with the codeline. As a developer, the quality of your work depends on how well it meshes with other peoples’ work. Staying in sync with the codeline can be a trade-off between productivity and “correctness”. What’s important is that the developer is aware of how often the codeline that their workspace maps to is changing and the risk of including those changes in their workspace and schedules their synchronisations accordingly. The ideal time to synchronise is when the codeline is in a known good state and so is the developer’s workspace and it would be advisable not to go more than a week without synchronising except in exceptional circumstances. Developers should always synchronise their workspace with the codeline before checking their changes in, this allows them to resolve any conflicts in their workspace without compromising the codeline.
  5. Check in often. Integrating your development with other peoples’ work also requires you to check in your changes as soon as they are ready. As a rule as soon as a developer has completed a task and it has passed any quality gates defined by the codeline’s policies their changes should be checked-in to the codeline so that other developers have access to the change and integrate their changes with it.

The next question is should you have one workspace or multiple and what should the granularity of each workspace be? I take the following factors into account whenever I create a workspace:

  • Each workspace should have the simplest set of working folders possible. Overly complicated working folder mappings (such as large numbers of working folders or mixtures of active and cloaked working folders) can be confusing and cumbersome to manage.
  • Each workspace has an overhead (e.g. staying in sync with the codeline). You need to evaluate the cost-benefit balance for each workspace you create. For example, creating a separate workspace for each task would probably not be worth the overhead it adds.
  • Each workspace should have a single defined purpose (e.g. development, QA, release management, or testing). For example, don’t do development and QA using the same workspace or don’t do QA and release management using the same workspace. These purposes have different codeline synchronisation, backup, and integration requirements, keeping them separate allows you to manage these activities more easily.
  • Each workspace should contain a single product or a related set of products. This will reduce the scope of any activities you perform which will both improve performance as well as avoid you having to deal with synchronisation or integration conflicts that aren’t relevant to your current context.
  • Each task you perform should start with an empty list of pending changes. Your contents of your pending changes tool window should always reflect your current task because managing pending changes that are related to a multitude of different tasks is cumbersome and prone to error.

Here are some examples on how these can be applied:

Joe is a developer for the WidgetManager product and performs QA when required. To do this Joe would create two workspaces, one called “WidgetManager Development” and one called “WidgetManager QA”.

Joe would use the “WidgetManager Development” workspace to fix bugs and implement enhancements to the product. Because of the development nature of this workspace he would ensure that it is synchronised with the codeline when both the codeline and the workspace are in known good states. Once he has completed his work and met all of the quality gates the changes in the workspace would be checked-in. If Joe had to switch development tasks he would shelve the pending changes (without preserving the local copy) and work on the other development task.

Halfway through the development cycle Joe is asked to perform some QA on work integrated into the codeline by one of his colleagues. He switches to the “WidgetManager QA” workspace and synchronises it with the codeline and then performs QA on the necessary files.

The advantage of having a separate workspace is that Joe doesn’t need to worry about shelving his pending development changes (or even worse losing them) when switching contexts. He also doesn’t need to worry about his in progress development contaminating the files being QA’d.

Let’s look at another example:

Niles is a build engineer on two separate products and is responsible for building and packaging the products for distribution. The products don’t have any dependencies and ship on entirely separate schedules. To do this Niles would create two workspaces, one called “WidgetManager Release” and one called “FooPlus Release”.

Each workspace would map the folders for the development and maintenance branches as well as any tools or scripts needed to build and release the software. Niles can synchronise each workspace separately which improves performance and reduces the scope of any conflicts.

Hopefully this has given you some ideas on how you can better use workspaces in your development process.

Visual Studio Hotfixes

Brian Harry has blogged about the MSDN Code Gallery web site which not only contains numerous code samples and add-ins but is also used to publish the Visual Studio hotfixes.

Filtering Build Completion Emails

Firstly, I know I’ve been quiet for a while, I’ve been working on a few things, enhancements to our build system, a presentation on the Migration and Synchronisation toolkit (will be posted shortly) and I have started work on a book about Team Build.

After receiving a large number of build completion emails that I wasn’t interested in I decided to filter these emails. The following command (which requires BisSubscribe.exe from the Visual Studio SDK) will restrict the build completion emails to all completion emails for builds you started but only build failures or stopped builds for other people’s builds.

BisSubscribe.exe /eventType BuildCompletionEvent /address <EmailAddress> /deliveryType EmailHtml
/server <TeamFoundationServer> /filter “RequestedBy=’<Domain>\<Username>’ OR CompletionStatus=’Failed’ OR CompletionStatus=’Stopped’”

Jason Pricket has a good post explaining the filters available for the BuildCompletionEvent.

Extending Team Foundation Server UI

I’ve been doing some work today on extending the Team Foundation Server UI, for example integrating with Team Explorer and the Pending Changes windows. I came across a number of resources explaining how to achieve this:

How to get the active Team Foundation Server and Project from an Add-In

Extending Team Foundation Server Version Control for Team Build Types Visual Studio integration

How to Write a Team Foundation Version Control Add-in for Visual Studio

Extending VSTS Work Item Tracking UI: Accessing work item UI elements and responding to events

Work Item Tracking v1 Client Extensibility in Visual Studio Team System

How to delete folders from your local workspace

A question I’ve had a few times is how can you delete folders from your local workspace without deleting them from the server. This question usually comes up when someone has done a get of a large area and wants to free up some local disk space.

Just deleting the folder using Windows Explorer works but it has a problem, Team Foundation Server still thinks you have that folder, so if you try to get the folder (or one of its children) from source-control in the future then Team Foundation Server won’t download it unless you use Get Specific Version and choose the Force get of file versions already in workspace option.

The solution is to cloak the folder, perform a get on the folder and then remove the cloak. When you do a get of a cloaked folder Team Foundation Server removes the local version from your workspace, thus freeing up your much needed disk space.

To cloak a folder simply edit the appropriate workspace and add an additional folder mapping with a status of Cloaked.

Modifying build emails to include Build Type

The emails sent by Team Build to notify that a build has completed don’t include the build type that spawned the build. This isn’t normally an issue because the default build numbers used include the build type. However, if you’ve overriden the build number generation you may want to include the build type within the email.

  1. On the Team Foundation Server navigate to %ProgramFiles%\Microsoft Visual Studio 2005 Team Foundation Server\Web Services\Services\v1.0\Transforms. This is where all of the email templates are stored.
  2. Back up the files BuildCompletionEvent.plaintextXsl and BuildCompletionEvent.xsl. These are the files we’ll be modifying.
  3. Edit the BuildCompletionEvent.plaintextXsl file.
  4. Immediately below the line Team Project: <xsl:value-of select=”BuildCompletionEvent/TeamProject”/> add the line Build Type: <xsl:value-of select=”BuildCompletionEvent/Configuration”/>.
  5. Save the file.
  6. Edit the BuildCompletionEvent.xsl file.
  7. Immediately below the section:

    <tr>
        <td>Team project: </td>
        <td class=”PropValue”><xsl:value-of select=”TeamProject”/></td>
    </tr>

    Add the section:

    <tr>
           <td>Build type: </td>
           <td class=”PropValue”><xsl:value-of select=”Configuration”/></td>
    </tr>

  8. Save the file.
  9. Back up the two files you modified. You should do this because when applying a Team Foundation Server service pack these files may be reverted to the original versions.
  10. Finally, restart IIS on the Team Foundation Server. You need to do this because these *.xsl files are cached the first time they are read and restarting IIS will refresh this cache.

That’s all there is to it. I haven’t tested this under Team Foundation Server 2008 (yet) but I expect the process will be the same. The more advanced reader will be wondering how I knew that the element that had to be selected was called Configuration, there are two parts to my answer:

  1. For each of the events there is an *.xsd file in that directory that specifies all of the elements that are available when that event fires. In this case it is the BuildCompletionEvent.xsd file that we’re interested in.
  2. When looking at that file the first element I chose was the one called Type (this seemed logical), however, in my testing this was always blank. After a bit of research I came across a post by Jason Prickett stating the Configuration is the correct element to use.

How to specify a custom compare/merge tool

Compare/merge tools are very much a developer preference so it’s useful that Visual Studio Team System allows you to specify your own compare/merge tool.  What’s even better is that you can have different tools for different extensions, so if you’d like to use a different tool to compare/merge *.xml files then you can do this.

Here’s how:

  1. From the Tools menu click Options….
  2. Expand Source Control.
  3. Click Visual Studio Team Foundation Server.
  4. Click Configure User Tools….
  5. Click Add.
  6. Enter the extension (including the leading full-stop). If you’d like to use the tool for all files then enter “.*”.
  7. Select Compare or Merge. If you want to use the tool for both then you must add two entries.
  8. Browse for the tool.
  9. Enter the arguments to be passed to the tool. To see a list of the available placeholders click the black triangle button.
  10. Click OK.

For Araxis Merge you can use the arguments:

  • Compare: /title1:%6 /title2:%7 /max %1 %2
  • Merge: /title1:%6 /title2:%8 /title3:%7 /max /wait /3 %1 %3 %2 %4

Feel free to leave comments with configurations for other tools.

Unattended Installation of Team Foundation Server Power Tools

If rolling the Team Foundation Server Power Tools out to a number of users (which you will need to do if you want to use the check-in policies) you will probably want to run the installation unattended.

There are two tricks:

  1. You will need to uninstall the previous version. To do this run:
    msiexec.exe /x /qn {C802488F-CB5F-48BE-BBD2-0C0F9E290E63}
    /x specifies that we are doing an uninstall
    /qn specifies that we want no user interface
    {C802488F-CB5F-48BE-BBD2-0C0F9E290E63} is the Product Code for the Team Foundation Server Power Tools
  2. Then you need to install the latest version. To do this run:
    msiexec.exe /i /qb tfpt.msi ADDLOCAL=CLI,VSIP,CHECKINPOLICIES
    /i specifies that we are doing an install
    /qb specifies that we want a basic user interface (just a progress bar)
    tfpt.msi is the path to the tfpt.msi to be installed
    ADDLOCAL=CLI,VSIP,CHECKINPOLICIES specifies that we only want to install tfpt.exe, the Visual Studio add-in, and the check-in policies (we leave out the Best Practices Analyzer [BPA] and the Process Editor [PROCESSEDITOR] because most users don’t need these and they have dependencies on PowerShell and the DSL Runtime respectively)

I used dark.exe from the WiX Toolkit to determine the ProductCode and thanks must go to Hua Chen from Microsoft for helping out with how to exclude the Best Practices Analyzer and the Process Editor.

Schemas for Work Item Type Definitions

I’m doing a lot of work with Work Item Type Definitions and for those that don’t know the Visual Studio SDK includes schemas for these that can be used in Visual Studio (and other XML editors) to provide Intellisense capabilities.

Rob Caron blogs about this here. For those that don’t want to download the whole SDK he also provides a direct download of just the schemas.

Upgraded to TFS Service Pack 1

I decided that I’d put off the upgrade to TFS Service Pack 1 for long enough and did the upgrade on our production server yesterday.

The good news is that it went very smoothly and the only hiccup I encountered was actually related to installing SQL Server Service Pack 2 (which we chose to do at the same time). The problem was simply that there wasn’t enough space available on the system drive to complete the installation.

For those of you that are interested the process I followed is:

  1. Take a snapshot of the virtual machine.
  2. Stop IIS (iisreset /stop).
  3. Perform a full backup of all of the SQL Server databases.
  4. Start IIS (iisreset /start)
  5. Install Windows Powershell (required by the TFS Best Practice Analyzer).
  6. Run the TFS Best Practices Analyzer.
  7. Install the Quiescing GDR on the TFS server and the TFS proxy.
  8. Install TFS Service Pack 1 on the TFS server.
  9. Install TFS Service Pack 1 on each of the build machines.
  10. Install TFS Service Pack 1 on the TFS proxy.
  11. Test.

I also performed a couple of extra steps:

  1. Install SQL Server Service Pack 2.
  2. Install Team System Web Access.
  3. Modified the Work Item Changed XSL to link to Team System Web Access.
  4. Install hotfixes for the 2 issues we’ve come across.
  1. FIX: Error message when you perform a merge operation in Visual Studio 2005 Team Foundation Server: “TF14087: Cannot undelete because not all of the deletion is being undeleted”.
  2. FIX: When the Microsoft.TeamFoundation.VersionControl.Adapter adapter processes a changeset, the adapter may fail in Visual Studio 2005 Team Foundation Server.
  • Restricted SQL Server to 1 Gb memory.
    1. Because we’re using a single server configuration we’re testing whether there will be a performance improvement by restricting SQL Server’s memory to ensure that there is memory left for the application “tier” and the OS.