Showing posts with label Team Build. Show all posts
Showing posts with label Team Build. Show all posts

Tuesday, November 30, 2010

Keep Assembly version same as build number

I have been struggling all afernoon with Team Foundation Server 2010 Custom Activities to keep the BuildNumber and the AssemblyVersions in Sync.
Apperantly System.Version is not serializable so the value gets lost when going into the Run On Agent Sequence.
As a startiong point I used the code of Ewald Hoffman. Original Article: http://www.ewaldhofman.nl/post/2010/04/20/Customize-Team-Build-2010-e28093-Part-1-Introduction.aspx
Step 1: Create the Version Generator (+ offcource the necessary unit tests Smile)…
   1:  using System;
   2:  using System.Collections.Generic;
   3:  using System.Linq;
   4:  using System.Text;
   5:   
   6:  namespace SharpSolutions.Tfs.Build.BuildTasks
   7:  {
   8:      public sealed class AssemblyVersionGenerator: IAssemblyVersionGenerator
   9:      {
  10:          /// <summary>
  11:          /// Generatas a new Assembly version
  12:          /// int the following format: Major.Minor.Build.Revision
  13:          /// Major: same as current version
  14:          /// Minor: same as current version
  15:          /// Build: 2 digit year since 2000* 1000 + day of year eg 10001 = Build run on 1 jan 2010
  16:          /// Revision: seconds since midnight
  17:          /// </summary>
  18:          /// <param name="currentVersion">used to retrieve current major and minor version</param>
  19:          /// <returns>A new Assembly version</returns>
  20:          public Version Generate(Version currentVersion)
  21:          {
  22:              //If we did not force now use the real now
  23:              //O_o get it?
  24:              DateTime now = ((IAssemblyVersionGenerator)this).Now == default(DateTime)? DateTime.Now: ((IAssemblyVersionGenerator)this).Now;
  25:              int major = currentVersion.Major;
  26:              int minor = currentVersion.Minor;
  27:              int build = (now.Year % 2000) * 1000 + now.DayOfYear;
  28:              int revision = (int)(now - new DateTime(now.Year, now.Month, now.Day, 0, 0, 0)).TotalSeconds / 10;
  29:   
  30:              return new Version(major, minor, build, revision);
  31:          }
  32:   
  33:          DateTime IAssemblyVersionGenerator.Now { get; set; }
  34:      }
  35:  }



2. Create a new Code Activity. Offcourse you can easily implement your own version of IAssemblyVersionGenerator



   1:  using System;
   2:  using System.Activities;
   3:  using Microsoft.TeamFoundation.Build.Client;
   4:  using Microsoft.TeamFoundation.Build.Workflow.Activities;
   5:   
   6:  namespace SharpSolutions.Tfs.Build.BuildTasks.Activities
   7:  {
   8:      [BuildActivity(HostEnvironmentOption.Controller)]
   9:      public sealed class GenerateAssemblyNumber : CodeActivity<string>
  10:      {
  11:          private IAssemblyVersionGenerator versionGenerator = new AssemblyVersionGenerator();
  12:          
  13:          [RequiredArgument]
  14:          public InArgument<string> AssemblyInfoFileMask { get; set; }
  15:   
  16:          [RequiredArgument]
  17:          public InArgument<string> Version { get; set; }
  18:   
  19:          [RequiredArgument]
  20:          public InArgument<IBuildDetail> BuildDetail { get; set; }
  21:          
  22:          protected override string Execute(CodeActivityContext context)
  23:          {
  24:              string assemblyInfoFileMask = context.GetValue(this.AssemblyInfoFileMask);
  25:              string version = context.GetValue(this.Version);
  26:   
  27:              Version currentVersion = new Version(version);
  28:              Version newVersion = versionGenerator.Generate(currentVersion);
  29:              context.TrackBuildMessage(string.Format("New Version is {0}", newVersion.ToString()));
  30:  
  31:              return newVersion.ToString();
  32:          }
  33:      }
  34:  }



Step 3: Update the version number in the AssemblyInfo.cs



   1:  using System;
   2:  using System.Collections.Generic;
   3:  using System.Linq;
   4:  using System.Text;
   5:  using System.Activities;
   6:  using System.Text.RegularExpressions;
   7:  using System.IO;
   8:  using Microsoft.TeamFoundation.Build.Client
   9:  using Microsoft.TeamFoundation.Build.Workflow.Activities;
  10:   
  11:  namespace SharpSolutions.Tfs.Build.BuildTasks.Activities
  12:  {
  13:      [BuildActivity(HostEnvironmentOption.Agent)]
  14:      public sealed class UpdateAssemblyVersion : CodeActivity
  15:      {
  16:          [RequiredArgument]
  17:          public InArgument<string> VersionNumber { get; set; }
  18:   
  19:          [RequiredArgument]
  20:          public InArgument<string> AssemblyInfoFileMask { get; set; }
  21:          
  22:          [RequiredArgument]
  23:          public InArgument<string> SourcesDirectory { get; set; }
  24:   
  25:          // If your activity returns a value, derive from CodeActivity<TResult>
  26:          // and return the value from the Execute method.
  27:          protected override void Execute(CodeActivityContext context)
  28:          {
  29:              // Obtain the runtime value of the input arguments
  30:              string sourcesDirectory = context.GetValue(this.SourcesDirectory);
  31:              string assemblyInfoFileMask = context.GetValue(this.AssemblyInfoFileMask);
  32:              Version newVersion = new Version(context.GetValue(this.VersionNumber));
  33:              
  34:              // Get all AssemblyInfo files
  35:              foreach (string file in Directory.EnumerateFiles(sourcesDirectory, assemblyInfoFileMask, SearchOption.AllDirectories))
  36:              {
  37:                  // Read the text from the AssemblyInfo file
  38:                  string assemblyInfoVersionText = File.ReadAllText(file);
  39:   
  40:                  string updatedContents = Utilities.UpdateAssemblyVersion(assemblyInfoVersionText, newVersion);
  41:   
  42:                  File.WriteAllText(file, updatedContents);
  43:              }
  44:          }
  45:   
  46:      }
  47:  }

Tuesday, February 24, 2009

Team Build: Setting up workspaces

One of the errors you might encounter whilst using team build is the following:

The specified path, file name, or both are too long. The fully qualified file
name must be less than 260 characters, and the directory name must be less than
248 characters.


The guide here below will help you to avoid these. But you should also keep in mind not to make your folder structure to complex or too deep. You can group your projects in your solution using solution folders which are not reflected in your physical project location.

Working Directory Build Agent
Set the working Directory for the Build Agent to a path that is not to long (e.g. C:\BuildWorkSpace\$(BuildDefinitionPath). Be aware to add the $(BuildDefinitionPath) variable in order for every build to be stored in a unique location.

Note: this will be replacing the $(SourceDir) variable. (see below)



Source Control Folder
Set the source control folder correctly to the folder containing the solution file.

See below for Solution structure. Te solution root is the parent folder where the solution resides.



Tuesday, January 13, 2009

Team Build: Enabling Code Coverage without using a test list

Modify the Test Arguments PropertyGroup to contain the RunConfigFile tag and point it to the correct location



<RunConfigFile>$(SolutionRoot)\01 Dev\Sharpsolutions.SharpMoney\LocalTestRun.testrunconfig</RunConfigFile>


After you have enabled ofcourse the code coverage for the correct projects.

Monday, January 12, 2009

Team Build and Referenced Assemblies

This session I am going to give some tip how you should reference shared assemblies.

I am currently building an application that uses several things of Enterprise Library and RhinoMocks for unit testing. Now these references have to be made to fixed locations but this can impose problems when building from different machines (think build agents differebt developer machine setups).

What I did was on my build agent I shared the build folder and mapped a networkdrive to it (in my case s:\). then I created a structure like this:
Enltlib\latest\ to which I copied the complete bin directory from entlib. The big advantages is that if you decide to upgrade later you just rename the folder to v4.1 and create a new latest folder where you copy the latest binaries to. Like this everybody will always be referencing the latest binaries without having to redo all their references in their projects

The advantages of this approach is that its completely independent of your machine setup. And if you have to work offline from your TFS once in a while you just make sure you check out the latest version of your BuildStore share the drive on your local machine and map it to the same network drive and your projects will continue to build without having to redirect the references all the time.