News for TFS 11 VCS

In this post of Mr. Brian Harry some of the news regarding TFS 11 VCS are unveiled. While there is still no DVCS, there are a lot of improvements with the introduction of “local workspaces”.

Actually TFS Workspaces status is kept on the server, so whenever you issue a GetLatest, the server check the status of the Workspace and send you only new data. This causes sometimes behavior that surprise most developer coming from other VCS like subversion. One of this surprising behavior is “delete a file from the file system, then issue a Get Latest, the file is not downloaded again”. This happens because the server does not know that you deleted the file, he still thinks that the file is there so you need to do a Get Specific version, or issue a tfpt scorch command. Another aspect developers do not like is having Read-only file that needs to be checked out before starting to work with.

In Tfs 11 another type of Workspace is introduced, it is called “local workspace” and it is really different from other ones, because now it is the master so you can do whatever you like with files in the Workspace, delete, edit with notepad++, etc etc, this makes local workspace really similar to subversion local copies. 

In the original post there is also a video that shows some of these news, check-it.

alk.

December update Of TFS and VS 2010

Microsoft releases a Virtual Machine with TFS and VS 2010 with some test data and hands on labs, that are really useful for demo or just to try out the new functionalities.

The machine have a 6 month expiration, and the old version expired today. If you still want to use them you can download the update version here. This new version has already the Feature pack 2 installed and other updates that are listed in the link above, but if you are curious here is all the updates from the older version.

· Visual Studio 2010 Feature Pack 2
· Team Foundation Server 2010 Power Tools (September 2010 Release)
· Visual Studio 2010 Productivity Power Tools (these are disabled in VS so that the screenshots of the hands-on-labs still match; you can quickly enable the Productivity Power Tools via Tools -> Extension Manager from within Visual Studio)
· Test Scribe for Microsoft Test Manager
· Visual Studio Scrum 1.0 Process Template
· All Windows Updates through December 8, 2010
· Lab Management GDR (KB983578)
· Visual Studio 2010 Feature Pack 2 pre-requisite hotfix (KB2403277)
· Microsoft Test Manager hotfix (KB2387011)
· Minor fit-and-finish fixes based on customer feedback
· A new expiration date of June 1, 2011

Grab it and have fun Smile

Alk.

Insert name of the user in assembly file number

Assembly file numbering during a Continuous integration build is one of the most interesting feature in a project, but sometimes we need also to generate numbers even for local build, especially if the user can launch some script to do a local compile and use it to deploy somewhere.

Major and Minor number in an assembly file info are usually updated manually when a new version or milestone is reached, so we are left with two 16 bit number to store useful information. Clearly a number is suitable to store changesetId, or some other integer, but how can you include the name of the user who did the build into the assembly file info number?

The solution is to create some sort of xml file that associate a numerical id to a user, than use that id in the assembly file number, as an example you can have a file like this one.

SNAGHTML898b40

that actually tells me that the user id 1 is associated to WIN.Y4…….. The question is, how I can handle this during a build or during a private build issued by a user? I blogged some time ago on how to grab information on the workspace with few lines of code, and that strategy could be used to solve this problem. First of all I’ve created a XmlUtils class that takes care of xml file handling.

SNAGHTML8c0282

This class is able to manage the numbering, verifying if the string I want to insert already exists in the original file, creates file if it was not already created, and it has a useful property called UpdateRequired that tells me if the string I want to lookup was not originally in the file and I need to call Save().

This is needed because I do not want to take care of the Xml File manually, if a new tfs team member will be added to the team, when he will launch the script I want the script to checkout the file, add the new string, assign the new Id and finally do a checkIn and update the file for all the team.

Thanks to TFS API everything is straightforward.

   1: XmlUtils xmlUtils = new XmlUtils(path);

   2: var ownerId = xmlUtils.GetIdForValue(ws.OwnerName, "Owner");

   3: //use the ownerid in the file assembly numbering

   4: if(xmlUtils.UpdateRequired)

   5: {

   6:    //need to update data file.

   7:    String filename = xmlUtils.GetFileNameForCategory("Owner");

   8:    if (!File.Exists(filename))

   9:    {

  10:        xmlUtils.Save();

  11:        ws.PendAdd(filename);

  12:    } else

  13:    {

  14:        ws.PendEdit(filename);

  15:        xmlUtils.Save();

  16:    }

  17:    var pendingChanges = ws.GetPendingChanges(filename);

  18:    ws.CheckIn(pendingChanges, "***NO_CI***");

  19: }

First of all I simply use the workspace owner name, and in line 2 ask to my XmlHelper class to give me the id assigned to the owner string. Then if an Update is required I get the name of the file and verify if it exists or not. If it does not exists I save it and then add to source control with a call to Workspace.PendAdd() method, if it already exists, I issue a checkout, then save the file. Finally I simply issue a check-in with the ***NO_CI*** comment to avoid triggering again some build if specified.

Now I can use the ownerId numerical value to simply use in the file assembly numbering.

Alk.

How to get TFS server address from a local folder mapped to a workspace

Sometimes you need to operate to a Tfs Version Control System with API starting from a local folder. There are a lot of API to work with workspaces, but the main problem is that you need to pass through a VersionControlServer object, and to obtain such an object you need to know the address of the Tfs server the workspace is mapped to?

The exercise is the following one 🙂 – Write a snippet of code, based on TFS API that, given a local path, retrieve ChangesetId that is currently mapped on the workspace.

The key part is the Workstation class that permits you to obtain a WorkspaceInfo object from a simple Path, thanks to the GetLocalWorkspaceInfo method.

   1: Workstation workstation = Workstation.Current;

   2: WorkspaceInfo info = workstation.GetLocalWorkspaceInfo(path);

Now that you have a workspace info, getting the info you need is really simple, first of all you can know the Team Project Collection address thanks to the ServerUri property of the WorkspaceInfo object, moreover the WorkspaceInfo object can create a valid Workspace object with a simple call to GetWorkspace method, passing a valid TfsTeamProjectCollection object. Here is the code.

   1: TfsTeamProjectCollection collection = new TfsTeamProjectCollection(info.ServerUri);

   2: Workspace ws = info.GetWorkspace(collection);

   3: String servername = ws.GetServerItemForLocalItem(path);

   4: VersionControlServer vcs = collection.GetService<VersionControlServer>();

Now you have both the VersionControlServer object and the Workspace object, and you can use the QueryHistory method to know the information you need.

   1: IEnumerable changesets = null;

   2: VersionSpec spec = VersionSpec.ParseSingleSpec("W", ws.OwnerName);

   3:  

   4: WorkspaceVersionSpec wvs = spec as WorkspaceVersionSpec;

   5: if (null != wvs && null == wvs.Name)

   6: {

   7:     spec = new WorkspaceVersionSpec(ws.Name, ws.OwnerName);

   8: }

   9: changesets = vcs.QueryHistory(servername, VersionSpec.Latest, 0, RecursionType.Full, null,

  10: new ChangesetVersionSpec(1), spec, 1, false, false).OfType<Changeset>().ToList();

  11: int changesetId = changesets.Cast<Changeset>().First().ChangesetId;

And you have the ChangesetId currently mapped to the local folder.

Alk

Executing Test in a test agent during a build

With Tfs Build you have a great flexibility on how to execute your unit tests. First of all you can decide to execute only tests of a certain category, or with a certain priority, but one of the most interesting feature is the ability to execute them in another machine with the helps of a test Agent. First of all you need to install a test controller and configure it in one of the machine:

image

Since this is a test machine I use administrator as the account, but this is not a good security strategy for production :), the important stuff is that the controller should be not associated with a project collection. Once the test controller is installed and configured you can install test agent on some pc and configure them to point at the controller.

image

for this example I installed an agent in the same machine of the test controller; when everything is ok you can simply create a testsetting file to set remote test execution.

image

With this option enabled, tests are executed remotely in an agent  configured with the controller 10.0.0.201. If you run tests you can look at the agent machine to verify that test are actually executed on the remote agent.

image

Now you can simply configure the build to use this new test settings file.

image

The advantage of this approach is that you can execute tests in a remote machine, with an agent that has access to the desktop. You can create a dedicated machine for running unit test during the build, expecially if the test machine has some specific characteristics to be satisfied (Es. it must have Sql Server installed to run database test locally, it should have a RAMDISK to speedup test execution, etc).

Alk.