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:  }

Monday, November 29, 2010

Formatting Source code for BLOG

Reminder to myself since I always have to search for it over and over: http://www.manoli.net/csharpformat/format.aspx

5S for .NET

I just finished Implementing lean software development: From Concept to Cash. In chapter 8: Quality (page 192) We find the 5S’s for Java find below my interpretation for .NET.

  • Sort (Seiri): Reduce the size of the code base. Throw away everything that is not needed. Remove:
    1. Dead Code
    2. Unused using statements
    3. Unused references
    4. Unused variables
    5. Unused Methods
    6. Unused Classes
    7. Refactor redundant/duplicate code
    8. Delete code in comments
    9. Delete or fix Ignored Unit Tests
  • Systematize (Seiton): Organize projects and packages. Have a place for everything and everything in its place
    • Resolve package dependency cycles
    • Minimize dependencies
  • Shine (Seiso): Clean up. Problems are more visible when everything is neat and clean.
    • Resolve unit test failures (Pass rate should be 100%)
    • Improve unit test coverage (> 80%)
    • Improve Unit test performance
    • Check duration to run all tests
    • Resolve compiler warnings
    • Resolve TODO’s
    • Resolve FxCop Warnings
    • Refactor methods that are too long
    • Refactor methods where Cyclomatic Complexity > 10
  • Standardize (Seiketsu): Once you get a clean slate, keep it that way. Reduce complexity over time to improve ease of maintenance.
  • Sustain (Shitsuke): Use and follow standard procedures
    • Integrate FxCop in daily build
    • Fail Continuous integration build on unit test failure (Gated Check ins)

These criteria can easily be found using ndepend which is word its price in gold

Wednesday, November 24, 2010

Team Foundation Server 2010 MDX to exclude the weekends

 

WITH 
SET [WeekDays]
AS Filter(
[Date].[Date].[Date]
, COUNT(WTD([Date].[Year - Week - Date Hierarchy])) <> 1
AND COUNT(WTD([Date].[Year - Week - Date Hierarchy])) <> 7
)

SET [DateRangeFrom]
AS FILTER([WeekDays]
, [WeekDays].CurrentMember.Member_Value >= CDATE("11/17/2010")
)

SELECT {
[Measures].[Work Item Count],[Measures].[Revision Count]

}
ON COLUMNS,{
[DateRangeFrom]
// [Date].[Date].[Date]
// , WTD([Date].[Year - Week - Date Hierarchy].CurrentMember)
//
}

ON ROWS
FROM [Team System]