Welcome to Manicprogrammer Sign in | Join | Help

Easily Getting Builds Out Of The Global Build List in TFS

Inside TFS global lists are created to store the names of completed builds that are then used to populate the SuggestedValues of such fields as Fixed in Build or Integrated in Build. Lots of folks don't want every build type they run to show up in this list, for example a CI build or failed build. I'm one of those folks. There is not, as one might expect, a property name that can be set in the build script to indicate that this specific build should not be added to the global lists.

I have heard a few different approaches to go about modifying the global list to remove the entries. None are perfect. Jason Prickett wrote up the following

http://blogs.msdn.com/jpricket/archive/2006/09/05/how-to-filter-the-build-completion-event.aspx

http://blogs.msdn.com/jpricket/archive/2006/09/05/useful-buildcompletionevent-filters.aspx

I, like a few other people are not too keen on replacing an out of the box subscription with our own and personally I just don't want to have to maintain the service and keep a config list for it to read of what builds it should and should not send on to the global lists. I don't know why. I guess its just not important enough to me.

And Ben Day promotes the manual edit approach here:

http://blog.benday.com/archive/2007/10/23/23165.aspx

I personally use a custom build task. Like the approaches listed prior this is far from perfect. First off since the the build doesn't get into the list until the web service is called it's not there when the custom build task runs. So what does my build task do then? It removes any preexisting entries for that build type thus I really will have no more than one entry for that build type in the global list -which will be the one for the build that is running and will be added after the build complete. Basically I empty out the global list for entries of that build type on each run so that only the latest will be present. This does nothing for you in terms of not placing into the list the Failed builds. But it did what I needed in not having a boat load of CI builds showing up in the list.

I just threw this together as a hack one night and also used it to play with some LINQ syntax so don't pound me on the style. It's an example of a quick hack thrown together all the time saying 'Let me try this. And I'll come back later and refactor into something real' But... 9 months later it's still in this form and running on my build servers.

In short- I take some needed parameters from the build and then concoct up a string to use in an XLINQ query to blow away the list entries I don't want then push the list back up to the server.

 

   1: using System;
   2: using System.Collections.Generic;
   3: using System.Text;
   4: using Microsoft.TeamFoundation.WorkItemTracking.Client;
   5: using Microsoft.TeamFoundation.Client;
   6: using System.Linq;
   7: using System.Xml.Linq;
   8: using System.Xml;
   9: using Microsoft.Build.Utilities;
  10: using Microsoft.Build.Framework;
  11:  
  12:  
  13: namespace ModifyGlobalList
  14: {
  15:     public class ClearBuildTypeFromGlobalList : Microsoft.Build.Utilities.Task 
  16:     {
  17:         private string _teamFoundationServerURL;        
  18:         private string _buildDefinitionName;
  19:         private string _teamProject;
  20:  
  21:         private const string GLOBAL_LIST_ELEMENT_NAME = "GLOBALLIST";
  22:         private const string GLOBAL_LIST_MEMBER_ELEMENT_NAME = "LISTITEM";
  23:         private const string GLOBAL_LIST_ELEMENT_NAME_VALUE = "Builds - ";
  24:  
  25:  
  26:         [Required]
  27:         public string TeamFoundationServerURL
  28:         {
  29:             get
  30:             {
  31:                 return _teamFoundationServerURL;
  32:             }
  33:             set
  34:             {
  35:                 _teamFoundationServerURL = value;
  36:             }
  37:  
  38:         }
  39:    
  40:         [Required]
  41:         public string BuildDefinitionName 
  42:         { 
  43:             get
  44:             {
  45:                  return _buildDefinitionName;
  46:             }
  47:  
  48:             set
  49:             {
  50:                  _buildDefinitionName = value;
  51:             }
  52:          }
  53:         [Required]
  54:         public string TeamProject
  55:         {
  56:             get
  57:             {
  58:                 return _teamProject;
  59:             }
  60:  
  61:             set
  62:             {
  63:                 _teamProject = value;
  64:             }
  65:         }
  66:  
  67:         public ClearBuildTypeFromGlobalList()
  68:         {
  69:  
  70:         }
  71:  
  72:         public override bool Execute()
  73:         {
  74:             bool isOk = true;
  75:  
  76:             string globalListToPrune = GLOBAL_LIST_ELEMENT_NAME_VALUE + TeamProject;
  77:  
  78:  
  79:             
  80:  
  81:             TeamFoundationServer tfs = TeamFoundationServerFactory.GetServer(_teamFoundationServerURL);
  82:             WorkItemStore _wiStore = (WorkItemStore)tfs.GetService(typeof(WorkItemStore));
  83:  
  84:          
  85:             XmlDocument globalLists = _wiStore.ExportGlobalLists();
  86:             XElement xGlobalLists = XElement.Load(new XmlNodeReader(globalLists));
  87:             IEnumerable<XElement> listItemsToDelete = (from listItems in 
  88:                                                            (
  89:                                                              (from gl in xGlobalLists.Elements(GLOBAL_LIST_ELEMENT_NAME)
  90:                                                               where ((string)gl.Attribute("name")).ToUpper() == globalListToPrune.ToUpper()
  91:                                                               select gl
  92:                                                              ).First<XElement>()
  93:                                                            ).Elements(GLOBAL_LIST_MEMBER_ELEMENT_NAME)
  94:                                                        where ((string)listItems.Attribute("value")).ToUpper().StartsWith(_buildDefinitionName.ToUpper())
  95:                                                        select listItems
  96:                                                       );           
  97:  
  98:  
  99:  
 100:             listItemsToDelete.DescendantsAndSelf().Remove<XElement>();
 101:  
 102:             _wiStore.ImportGlobalLists(xGlobalLists.ToString());
 103:  
 104:             return isOk;
 105:             
 106:         }
 107:  
 108:     }
 109: }
 110:  
 111:  
 112:  
 113:  
 114:  
Published Friday, August 01, 2008 8:24 AM by michaelruminer
Filed under , ,

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

Thursday, August 07, 2008 10:04 AM by Team System News

# VSTS Links - 08/07/2008

Hakteng on Creating and Customizing TFS Reports Michael Ruminer on Easily Getting Builds Out Of The...

Tuesday, August 26, 2008 6:00 PM by Websites tagged "builds" on Postsaver

# Websites tagged "builds" on Postsaver


Enter the text you see in the image:

Leave a Comment

(required) 
required 
(required)