Rebuilding custom Build activities for TFS 2012

At our company Fred I’ve sort of inherited the role of TFS administrator. So as part of this I get to deal with upgrading our TFS server to 2012; and as part of the upgrade we need to ensure that Builds continue to work, So since a 2010 Build machine will NOT work with a 2012 Team Foundation Server, we need to ensure our builds work on a 2012 build machine!

p.s. Jason Prickett has a few hints that help to get started if you’re thinking about going through a TFS upgrade – http://blogs.msdn.com/b/jpricket/archive/2012/10/24/upgrading-your-build-definitions-from-tfs2010-to-tfs2012.aspx

But beyond the regular, I found that one of our solutions had custom build templates as well as custom build assemblies; which is something I had never played with before.  I’ll discuss how I went about getting them to work and the undocumented steps to upgrade them.

Use target framework 4.5 for your template project and activity project

Custom Build Targeting .NET 4.5

Change the target framework for build activities and process projects to compile for the full version of .NET 4.5.

 

BuildActivity attribute

Decorate all Code Activity classes with the BuildActivity(HostEnvironmentOption.All) attribute, i.e.

[BuildActivity(HostEnvironmentOption.All)]
public class ServerConfig : CodeActivity

I was under the impression that this was required for custom activities in 2010, but there were classes that didn’t have it that were working. This seemed to be an issue with 2012…

 

Update TeamFoundation references to 11.0

Update all of the references in your build solution(s) from 10.0 to 11.0, this was mainly painless however there seemed to be some references that were not in the GAC and I had to find them

Custom Build needs version 11 assemblies

Remove the version from the namespace references

Due to a bug in one of the activities in TFS 2010, the Visual Studio Workflow Designer would add versioned namespaces to the XAML file upon saving it. They look something like this:

xmlns:mtbw1=”clr-namespace:Microsoft.TeamFoundation.Build.Workflow; assembly=Microsoft.TeamFoundation.Build.Workflow, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a”

The version number in this string forces Workflow to attempt to load the 10.0.0.0 assemblies. These assemblies contain the same types as the 11.0.0.0 assemblies and cause all kinds of problems.

Here’s a tool that will take out any duplicate namespaces and remove versioning – http://blogs.msdn.com/b/jpricket/archive/2012/07/17/tfs-2012-cleaning-up-workflow-xaml-files-aka-removing-versioned-namespaces.aspx

 

New import statements (From DefaultTemplate.11.xaml)

The ones that were missing for my template were:

  • Microsoft.TeamFoundation.Common
  • System.Linq
  • Microsoft.TeamFoundation.VersionControl.Common

DefaultTemplate.11.xaml

I added these references to my project containing my Build Process Templates and added these to the imports of my workflow.

 

Get the custom activities onto the Build box

  1. From within Source Control Explorer add these new files to a new folder and check the files into TFS. I.e. Create in a new folder under the BuildProcessTemplates called Custom Assemblies.
  2. Open Team Explorer, right-click on Builds and select Manage Build Controllers
  3. Select the controller to configure, and then select Properties
  4. Set the Version control path to custom assemblies to the location just created under version control containing your added assembliesCustom Build Manage Controller

 

Typical error messages we overcame during this process

UPDATE: I found a great summary of typical errors and their fixes: http://reader.feedshow.com/show_items-feed=d1180bf9d191f833eeb8293527793b42

  • Unable to cast object of type ‘Microsoft.TeamFoundation.Build.Workflow.Activities.PlatformConfigurationList’ to type System.Collections.Generic.List’ 1[Microsoft.TeamFoundation.BuiId.Workflow.Activibes.PlatformConfiguration]’.
  • Opening a XAML file in Visual Studio 2012 – System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. —> System.Exception: The component “Microsoft.TeamFoundation.Build.Workflow.Design.InvokeForReasonDesigner’ does not have a resource identified by the URI…
  • Editing a build definition in Visual Studio 2012 – Unable to cast object of type ‘Microsoft.TeamFoundation.Build.Workflow.Activities.TestSpecList’ to type ‘System.Collections.Generic.List`1[Microsoft.TeamFoundation.Build.Workflow.Activities.TestSpecList]’.
  • Editing a build definition in Visual Studio 2012 – [A]Microsoft.TeamFoundation.Build.Workflow.Activities.BuildSettings cannot be cast to [B]Microsoft.TeamFoundation.Build.Workflow.Activities.BuildSettings. Type A originates from ‘Microsoft.TeamFoundation.Build.Workflow, Version=10.0.0.0, …’ in the context ’Default’ at location …. Type B originates from ‘Microsoft.TeamFoundation.Build.Workflow, Version=11.0.0.0, …’ in the context ‘Default’ at location ….
  • Building on a TFS 2012 Build Machine – Validation Error: The private implementation of activity ‘1: DynamicActivity’ has the following validation error: Compiler error(s) encountered processing expression “BuildDetail.BuildNumber”. Type ‘IBuildDetail’ is not defined.
  • The build process failed validation. Details:  Validation Error: The private implementation of activity ’1: DynamicActivity’ has the following validation error: Compiler error(s) encountered processing expression “testAssemblies.Count() > 0”.
  • ‘Count’ is not a member of ‘System.Collections.Generic.IEnumerable(Of String)’.
  • Validation Error: The private implementation of activity ’1: DynamicActivity’ has the following validation error: Compiler error(s) encountered processing expression “WorkspaceName.Length > Microsoft.TeamFoundation.VersionControl.Common.RepositoryConstants.MaxWorkspaceNameSize”.
  • Validation Error: The private implementation of activity ’1: DynamicActivity’ has the following validation error: Compiler error(s) encountered processing expression “WorkspaceName.Substring(0, Microsoft.TeamFoundation.VersionControl.Common.RepositoryConstants.MaxWorkspaceNameSize).TrimEnd()”.
  • ‘Common’ is not a member of ‘VersionControl’.
  • Validation Error: The private implementation of activity ’1: DynamicActivity’ has the following validation error: Compiler error(s) encountered processing expression “String.Format(“The workspace name ‘{0}’ exceeds the maximum allowed limit of ‘{1}’ characters. Truncating it to match the maximum limit.”, WorkspaceName, Microsoft.TeamFoundation.VersionControl.Common.RepositoryConstants.MaxWorkspaceNameSize)”.
  • Validation Error: The private implementation of activity ’1: DynamicActivity’ has the following validation error: Compiler error(s) encountered processing expression “String.Format(“{0}_{1}_{2}”, BuildDetail.BuildDefinition.Id, Microsoft.TeamFoundation.LinkingUtilities.DecodeUri(BuildAgent.Uri.AbsoluteUri).ToolSpecificId, BuildAgent.ServiceHost.Name)”.
  • ‘LinkingUtilities’ is not a member of ‘TeamFoundation’.

Leave a Reply

Your email address will not be published. Required fields are marked *