Thursday, May 26, 2011

TFS–Automated Project Creation

May 26, 2011 Posted by Jason , No comments
I posted a while back about the…difficulties…migrating from VSS to TFS in terms of mass project creation and re-creation. Specifically, the process to create a team project in TFS is somewhat manual and it has been extremely frustrating re-initializing our TFS sandbox prior to every iteration of testing…until today…

Part 1

Today I stumbled across a useful nugget of information – there is a client-side Team Explorer command called File.BatchNewTeamProject located in the Microsoft.VisualStudio.TeamFoundation.TeamExplorer DLL located in C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\PrivateAssemblies. This command is used by Team Explorer in Visual Studio to create a new team project. A little extra investigation led me to a Codeplex project ( by Brad Kaenel named Team Foundation Project Provisioner with the express purpose to
“1) Produce a .Net assembly that encapsulated all the fiddly code necessary to generate the required XML file and invoke BatchNewTeamProject; 
2) To write a shop-specific provisioning tool that not only created Team Projects, but also did the necessary post-creation tasks that I needed.”
This code does everything I need and more (right now I don’t need to pull in AD groups etc.) solving part 1 of my problem.

Part 2

Building on this I decided to parse our existing conversion.xml files, used by VSSConverter to migrate VSS projects to TFS. The file looks a little like this trivial example:

<?xml version="1.0" encoding="utf-8"?>
    <Source name="VSS">
      <VSSDatabase name="C:\TFSMigration\vss_database"></VSSDatabase>
      <UserMap name="c:\UserMap.xml"></UserMap>
      <Project Source="$/BillingProject/BillingProject/Client" Destination="$/BillingProject/Client"></Project>
      <Project Source="$/BillingProject/BillingProject/Server" Destination="$/BillingProject/Server"></Project>
      <Project Source="$/FinancialProject/FinancialProject/Client" Destination="$/FinancialProject/Client"></Project>
      <Project Source="$/FinancialProject/FinancialProject/Server" Destination="$/FinancialProject/Server"></Project>
	  <Project Source="$/FinancialProject/FinancialProject/Common" Destination="$/FinancialProject/Common"></Project>
      <Project Source="$/StaffingProject/StaffingProject/Client" Destination="$/StaffingProject/Client"></Project>
      <Project Source="$/StaffingProject/StaffingProject/Server" Destination="$/StaffingProject/Server"></Project>
    <TeamFoundationServer name="" port="8080" protocol="http" collection="tfs/MyProjectCollection">

Obviously this file contains all of the requisite information to identify needed TFS (destination) projects and pulling this information out couldn’t be simpler:

static void Main()
	var uri = new Uri("");
	const string processTemplateName = "MSF for Agile Software Development v5.0";
	var projectProvisioner = new ProjectProvisioner();

	var loaded = XDocument.Load(@"C:\conversion.xml");
	var listOfProjectPaths = loaded.Descendants("Project").Select(x => ((string)x.Attribute("Destination")).Replace(@"$/", string.Empty));
	var listOfDistinctProjectNames = listOfProjectPaths.Select(x => x.Substring(0, x.IndexOf("/"))).Distinct();

	projectProvisioner.ProvisionProgress += MyProvisionerProvisionProgress;
	projectProvisioner.ProvisionException += MyProvisionerProvisionException;

	foreach (var project in listOfDistinctProjectNames)
		projectProvisioner.Create(uri, project, processTemplateName, null, null);

I created a simple console app, referencing the TFSProjectTools assembly from tfsprojprovisioner. Loading the conversion.xml file from my C:\ drive I was then able to loop through each project element and performed some simple string manipulation essentially turning this:

into this:

and returning the distinct root projects. I looped through these projects and used the Create method in TFSProjectTools to create the required projects. That is all VSSConverter needs to be set up and I finally have a repeatable solution in place to create the requisite projects for our VSS migration.