Tuesday, June 24, 2008

Automate workspace creation with MSBuild

And now as promised I shall script workspace creation. I will use MSBuild for this exercise (since it is way better looking and more convenient than batch files, and more standard than PowerShell); if you shied away from MSBuild previously may be it is time to get better acquainted :)

The task at hand is pretty simple: create new workspace and define set of mappings as specified per script; the user will pass workspace name and root folder for the mappings as an arguments to the script.

I will use tf command-line client with workspace and workfold commands for the purpose [while there are CreateWorkspace MSBuild tasks shipped as part of VSTS 2005/2008, they are not suitable for the purpose as the mappings cannot be specified as parameters to the task; 2005 version uses XML file and 2008 version uses Team Build database].

One thing to note before going into further details – when you use tf workspace /new to create a workspace, the default mapping is created (yes, no one asked for that, but tf does so nevertheless). That necessitates removal of that default root mapping as a first step after workspace creation.

So here goes the script (it is a longish one, but it is pretty self-descriptive):

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="CreateWorkspace"
  xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <!-- Default values for the properties the script  uses -->
  <PropertyGroup>
    <RootPath></RootPath>
    <WorkspaceName></WorkspaceName>
    <Tf>tf</Tf>
  </PropertyGroup>
  <!-- Workspace mappings to create -->
  <!-- Customize at will -->
  <ItemGroup>
    <WorkspaceMapping Include="$/Project1/Source">
      <LocalPath>$(RootPath)Source</LocalPath>
    </WorkspaceMapping>
    <WorkspaceMapping Include="$/Infra/Bin">
      <LocalPath>$(RootPath)Common</LocalPath>
    </WorkspaceMapping>
  </ItemGroup>
  <!-- Main target -->
  <Target Name="CreateWorkspace">
    <!-- Checking input parameters -->
    <Error Condition="$(WorkspaceName) == ''" 
          Text="Please specify WorkspaceName property"/>
    <Error Condition="$(RootPath) == ''" 
          Text="Please specify RootPath property"/>
    <Error Condition="!HasTrailingSlash('$(RootPath)')" 
          Text="Please make sure RootPath is slash terminated"/>
    <!-- Create new workspace-->
    <Exec Command="$(Tf) workspace /new /noprompt 
                    &quot;$(WorkspaceName)&quot;" />
    <!-- Remove default mapping -->
    <Exec Command="$(Tf) workfold /unmap 
                  /workspace:&quot;$(WorkspaceName)&quot; $/"/>
    <!-- Create new mappings (uses MSBuild batching) -->
    <Exec Command="$(Tf) workfold 
                /map &quot;%(WorkspaceMapping.Identity)&quot; 
                    &quot;%(WorkspaceMapping.LocalPath)&quot; 
                /workspace:&quot;$(WorkspaceName)&quot;"/>
    <!-- Great success! -->
    <Message Text="Workspace '$(WorkspaceName)' created sucessfully"/>
    <!-- List created mappings -->
    <Exec Command="$(Tf) workfold 
                /workspace:&quot;$(WorkspaceName)&quot;"/>
  </Target>
</Project>

To execute the script, fire up “VS 200x Command Prompt” and type the following:



msbuild CreateWorkspace.proj /p:WorkspaceName=VistaDevt /p:RootPath=c:\Vista\


Only caveat is that the folder the script located in cannot be mapped anywhere (as I noted above, tf workspace /new will try to map it and will fail).

If you are convinced that using script to create workspace is better than typing in the mappings, CreateWorkspace.proj is available for download here.

For completeness sake, it is worth mentioning /template argument of tf workspace command. If you want to copy somebody else’s workspace it is pretty attractive choice (or if you do not want to remember that somebody’s workspace name and AD user name, you can use Workspace Sidekick UI for the same purpose)

If you want to have “single-click” build, you may want to add to this script a) getting everything once workspace is created and b) building everything once get latest is finished. MSBuild makes both tasks very easy to achieve.

No comments: