Saturday, November 10, 2012

TFS Extensibility

In this post I hope to outline all the extensibility points in TFS 2012 and come up with a reason I might use it for the company I work for.  I would define this as both a major strength and weakness in TFS, there's a lot of powerful stuff exposed to developers but there's not a lot of documentation and a fair bit of it seems half complete which all results in very little adoption.  The community around customizing TFS seems fairly small in my opinion, but could be a major win for Microsoft.

Tfs Client API - .NET
A set of .NET classes to interact with the various webservices exposed by TFS, this is the main interaction point from which Visual studio and all components that don't need to be installed on the TFS server directly, for this reason it is extremely powerful.

We mainly use it to build a custom TFS web frontend for our clients for logging bugs which is a bit more cut down than the TFS web access. The need for this has reduced drastically with the release of TFS 2012 however it does mean we can integrate other systems giving our clients a one stop site for all their needs (rather than requiring them to login to 3-4 different systems).  We are careful that users can only see any work items that they create so that they don't require a special TFS CAL. The built in boards and backlog in TFS 2012 require a higher level CAL, but you can build your own backlog/board that works under the limited CAL.

We also make use of the API in a few ways to help manage the TFS Server. For example automatically granting permissions to TFS teams for any areas/iterations they're associated with, that way I can just assign people to project teams and they'll have the permissions they need.  Another example is a set of sanity checks which do things like making sure every solution in source control has an associated build.

Tarun AroraNeno Loje, and Shai Raiten all blog extensively on this subject.

TFS Build Templates - XAML, .NET
TFS Builds in 2010 and higher are controlled by .NET Workflows, this includes a lot of the Lab management functionality.  There are lots of builtin activities you can add to your templates and you can write your own activities in Visual studio and include you (or use one of the many activities that are part of the community tfs build extensions).

I'm not a fan of the editor and using custom assemblies causes all kinds of pain just to get the custom activities into Visual Studio so you can add them.  You can't easily just grab a component off someones blog, add it to your template, test it and deploy it.  This gets even more complex when you've already customized your template so can't just replace the entire template and have to add their changes manually.

For the above reasons I typically try keep template customizations to a minimum.  I believe the only customization I have currently is to set the default build quality of a successful build so that I can make use of TFS Deployer to deploy the same binaries in turn to each environment for testing.  TFS Deployer then makes use of powershell scripts, which I find much easier to customise and test.

TFS Soap Subscriptions - SOAP
The tfs api (mentioned above) allows you to subscribe to a number of events via soap webservices, this allows your app to get notified when any of the following events occurs in TFS.
  • Work item changes
  • Check ins
  • Build completes
  • Build quality changes (this is what TFS Deployer uses)
  • Project is created or deleted
  • Branch moved
  • Security Acl changes
  • Iteration/Area changes
Note: The last 4 may be client events only, meaning only the client that triggers the event gets notified.

Back in 2005/2008 we used to use this notification service to send out emails when a workitem was assigned (instead of getting every developer to create a subscription themselves), in 2010 we migrated this to use the server events instead and finally replaced it with a single out of the box team subscription in tfs 2012.

These days I don't make use of any of these events myself (except obviously build quality change). I can imagine subscribing to area/iteration changes to automatically create folders in SharePoint, much like the proposed TFS Automation Platform from Martin Hishelwood, sadly this project never seemed to get off the ground.

TFS Server-side Event Handlers - .NET
Location: %Program Files%\Microsoft Team Foundation Server 11.0\Application Tier\Web Services\bin\Plugins

TFS 2010 introduced the ability to create server side event subscribers by implementing the ISubscriber interface and dropping the resulting assembly into the plugin directory and access the same events as the soap subscriptions.

These seemed a lot more reliable than the soap subscriptions, but had to process fairly quickly as it blocked TFS from finishing what it was doing. As mentioned earlier we used this to send email alerts for assigned work items, if you ever did a bulk update (100 work items) TFS would lock up and not respond for up to a minute.  The solution was either to spin up a background thread (which I believe had a chance to be killed) or queue a custom TFS Job.

Because TFS waits for you to process it means you can use events as Decision Points to allow or deny certain actions from occurring.  This means you can add extra custom validation to workitems and checkins, there are better ways to do both but sometimes you need access to code to do more advanced checks.

Apart from emailing notifications, I've seen a plugin that can associate workitems to checkins based on the comments (and heard of someone doing the reverse - setting comments based on the associated workitems).

Update: I created a few sample server side event plugins that automatically creates builds for new solution files, automatically creates workitem queries for new areas

MTM/TestCase server notifications are also available in 2012.

Check In Policies - .NET
Location: Developer machines

Code that can ensure particular requirements are met before a checkin can occur, examples:
  • Project Compiles
  • Tests pass
  • Comments added
  • WorkItem associated
  • Passes StyleCop checks
  • WorkItems associated are in particular areas/queries
  • Regex patterns on filenames/contents
New policies can be created by extending the PolicyBase class, and deploying them to your development machines.

These are annoying to deploy as they get installed on each developers machine, not the TFS server. They became easier in VS2010 with the ability to install using a vsix, in Visual Studio 2012 it became possible to create private extension galleries to help deploy extensions within your enterprise.  However as far as I'm aware there is still no automated way to deploy one of these when your developers connect to a TFS server.

I try not discourage my developers from checking in so I keep the policies fairly light.  We currently require a comment, but encourage other practices just by word of mouth.  I think it would be possible to prompt the user if they want to create a code review request in 2012 on checkin, which may be a good way to introduce users to code review, however it would likely be annoying fast and probably still harder than just informing developers manually.

TFS Job Agent - .NET
Location: %ProgramFiles%\Microsoft Team Foundation Server 11.0\Application Tier\TFSJobAgent\plugins\

TFS runs a number of jobs in the background using its job agent and service (Processing the cube, email subscriptions, AD sync).  You can either write your own custom tasks by implementing the  ITeamFoundationJobExtension interface, or fire off existing tasks when you feel like it.

Custom Jobs are a good choice when you need to do a lot of work in the background, the problem I mentioned earlier when TFS hanging when trying to update 100+ workitems due to the email plugin could be solved by writing an event handler that queues a custom job.
Update: I created a sample server side job plugin that automatically creates workitem queries for new areas

Warehouse/Cube Customization - .NET
Location: %ProgramFiles%\Microsoft Team Foundation Server 11.0\Application Tier\TFSJobAgent\plugins\

TFS builds its own data warehouse from scratch, this is likely because work item fields can be configured to push information through to the warehouse/cube as either a dimension or measure.  TFS supports the interface IWarehouseAdapter which allows the various parts of TFS to add fields to the warehouse as it is getting built.  Developers can also take advantage of this interface and write their own custom data warehouse adapter.

The above example is regarding TFS 2008 which I have heard does not work in 2010, unfortunately there seems to be no real documentation from Microsoft and very few people trying to build a custom adapter.  I would suggest that maybe a tool like ILSpy and looking at the built in adapters would be the way to go.

In 2010 it looks like the warehouse processing was merged into the job service, and any IWarehouseAdapter have been converted to extend the abstract class WarehouseAdapter.  There's also a notion of WebhouseJobExtension which are the ITeamFoundationJobExtension jobs that presumably kick off the schema and data updates int the adapters.

Microsoft.TeamFoundation.WorkItemTracking.Adapter.WorkItemTrackingWarehouseAdapter looks to be a good example of a warehouse adapter.

Deployment Services - REST, .NET
TFS 2012 update 1 adds in a new build definition and services that allow you to deploy websites to azure. The code behind this actually looks a lot more powerful and gives me the impression that they're going to open it up for others to start publishing not only deployment methods but other services that can interact with TFS using OAuth.

Using WCF Storm I discovered the following webservices.


  • CreateConnectedService
  • QueryConnectedServices
  • GetConnectedService


  • CreateDeploymentEnvironment
  • GetDeploymentEnvironments


  • GetDrawerContents
  • GetString

Once you register a deployment service (eg Azure, or a custom built one) you can add environments to it with a custom set of properties (any keyvalue pair). You can then query all enviroments for a given service and pull properties out of its strong box drawer.

I haven't looked at the workflow activities at all to see if they would support calling a custom service.

Custom WorkItem Controls - .NET, Javascript
It's fairly well known that you can customize the fields for any workitem, however you can also write your own custom controls to display on workitems.

With the totally new Web Acess in TFS 2012 there's a new way to write custom controls.

There's a codeplex project that contains many work item tracking custom controls along with their source, and look like they may be updated for TFS 2012 (the visual studio integration side anyway).

Web Access Extensibility - Javascript
The Web access allows you to upload new javascript based plugins, apparently the team were not happy with the state of this at the time of release and are currently reworking them before they make many details public.

It also appears that the different sections of Web Access are built using the above plugins, two controllers (one for the view, one for json) and an AreaRegistration to register them. It may be possible to create new sections just by creating a new AreaRegistration and dropping it in the bin directory.

Update - below are some extensibility points I was either unaware of at the time of writing, or didn't think worth mentioning (visual studio extensions) as everyone already knows about them.

Test Controller Plugins
I've never seen anyone else use one of these, but they appear to exist and work well. I've written one to help filter available test agents by their machine tags for the current test config.

Diagnostic Data Adapters
Custom Adapter – Part 1

MTM Extensions
Example Extension TestScribe for MTM

Visual Studio Extensions
Developing Visual Studio Extensions

There's lots of extensibility points in TFS but a number of them seem half finished, or not documented.  It could be that most of them are only designed for internal Microsoft use, but it wouldn't take too much to make them very useful for other developers.