views:

6321

answers:

6

Myself and my group is horrendous at incrementing assembly version numbers and we frequently ship assemblies with 1.0.0.0 versions. Obviously, this causes a lot of headaches.

We're getting a lot better with our practices via our CI platform and I'd really like to set it up to auto increment the values within the assemblyinfo.cs file so that the versions of our assemblies are auto updated with the code changes in that assembly.

I had previously setup (before we found Hudson) a way to increment the value through either msbuild or the command line (can't remember), but with Hudson, that will update the SVN repository and trigger ANOTHER build. That would result in a slow infinite loop as Hudson polls SVN every hour.

Is having Hudson increment the version number a bad idea? What would be an alternative way to do it?

Ideally, my criteria for a solution would be one that:

  • Increments the build number in assemblyinfo.cs before a build
  • Only increments the build number in assemblies that have changed. This may not be possible as Hudson wipes out the project folder every time it does a build
  • Commits the changed assemblyinfo.cs into the code repository (currently VisualSVN)
  • Does not cause Hudson to trigger a new build the next time it scans for changes

Working this out in my head, I could easily come up with a solution to most of this through batch files / commands, but all of my ideas would cause Hudson to trigger a new build the next time it scans. I'm not looking for someone to do everything for me, just point me in the right direction, maybe a technique to get Hudson to ignore certain SVN commits, etc.

Everything I've found so far is just an article explaining how to get the version number automatically incremented, nothing takes into account a CI platform that could be spun into an infinite loop.

Sorry for all the edits, the corporate Internet connection is CRAZY right now.

+6  A: 

A simple alternative is to let the C# environment increment the assembly version for you by setting the version attribute to major.minor.* (as described in the AssemblyInfo file template.)

You may be looking for a more comprehensive solution, though.

EDIT (Response to the question in a comment):

From AssemblyInfo.cs:

// Version information for an assembly consists of the following four values:
//
//      Major Version
//      Minor Version 
//      Build Number
//      Revision
//
// You can specify all the values or you can default the Build and Revision Numbers 
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
Greg D
I've never come across this before, could you go into a little bit more detail about what it does. Does it only function within one IDE or does it work across a whole team of developers with a CI platform?
Allen
ahhh I have seen that before, that may be an acceptable solution but the # built isn't stored within subversion etc. I have Hudson setup to archive the files and in that way it is stored so that might be acceptable. I will have to do some more research into how that mechanism works, thanks!You wouldn't know how it determines what to put in as values, would you?
Allen
See my answer below for the answer to your question. The values are determined based on the build time.
Kyle Trauberman
Wow, I think this will work. Not sure how we overlooked such a simple solution
Allen
Hope it does, glad I could help. Why do something the hard way when the easy, fast way is also the right way? :)
Greg D
+4  A: 

.NET does this for you. In your AssemblyInfo.cs file, set your assembly version to major.minor.* (for example: 1.0.*).

When you build your project the version is auto generated.

The build and revision numbers are generated based on the date, using the unix epoch, I believe. The build is based on the current day, and the revision is based on the number of seconds since midnight.

Kyle Trauberman
<ring, ring> "hello, product support how may i help?"<customer> "i have an error"<support> "ok, what version are you running?"<customer> "version one point two revision eight five two five three seven four build seven four six three five two nine..."<support> "hold on, just typing that it... hmmm... please repeat the version numbers, we dont seem to have that build and revision listed..." - GRRR!
Jimbo
+7  A: 

Hudson can be configured to ignore changes to certain paths and files so that it does not prompt a new build.

On the job configuration page, under Source Code Management, click the Advanced button. In the Excluded Regions box you enter one or more regular expression to match exclusions.

For example to ignore changes to the version.properties file you can use:

/MyProject/trunk/version.properties

This will work for languages other than C# and allows you to store your version info within subversion.

Matthew Blackford
Hudson can also ignore commits from certain users or not trigger a build depending on the commit message. This way you can ignore all commits from Hudson.
Peter Schuetze
+3  A: 

I've never actually seen that 1.0.* feature work in VS2005 or VS2008. Is there something that needs to be done to set VS to increment the values?

If AssemblyInfo.cs is hardcoded with 1.0.*, then where are the real build/revision stored?

After putting 1.0.* in AssemblyInfo, we can't use the following statement because ProductVersion now has an invalid value - it's using 1.0.* and not the value assigned by VS:

Version version = new Version(Application.ProductVersion);

Sigh - this seems to be one of those things that everyone asks about but somehow there's never a solid answer. Years ago I saw solutions for generating a revision number and saving it into AssemblyInfo as part of a post-build process. I hoped that sort of dance wouldn't be required for VS2008. Maybe VS2010?

TonyG
You have to remove the AssemblyFileVersion. Other than that, its working out awesome for us, the accepted answer that is.
Allen
Yes, removing AssemblyFileVersion allows the version to update, and no more errors with Version. Nice.Note: two Build operations only increment the revision once, but if you ReBuild the revision is updated.As ktrauberman said, it looks like the build.revision = date.time, which explains why the data isn't stored anywhere except in the assembly.Now I need to get a standard MSI Setup to generate a new ProductCode when the primary output project updates. Setups don't allow for revision, only build. I want to install over an existing installation to do an update. Need to research.
TonyG
+6  A: 

Here is an elegant solution that requires a little work upfront when adding a new project but handles the process very easily.

The idea is that each project links to a Solution file that only contains the assembly version information. So your build process only has to update a single file and all of the assembly versions pull from the one file upon compilation.

Steps:
1. Add a class to you solution file *.cs file, I named min SharedAssemblyProerties.cs
2. Remove all of the cs information from that new file
3. Cut the assembly information from an AssemblyInfo file:
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
4. Add the statement "using System.Reflection;" to the file and then paste data into your new cs file (ex SharedAssemblyProperties.cs)
5. Add an existing item to you project (wait... read on before adding the file)
6. Select the file and before you click Add, click the dropdown next to the add button and select "Add As Link".
7. Repeat steps 5 and 6 for all existing and new projects in the solution

When you add the file as a link, it stores the data in the project file and upon compilation pulls the assembly version information from this one file.

In you source control, you add a bat file or script file that simply increments the SharedAssemblyProperties.cs file and all of your projects will update their assembly information from that file.

here is my blog post on this topic: http://cs.blueberryislandmedia.com/blogs/blueberries/archive/2010/02/04/managing-assembly-version.aspx

sondlerd
+1 for a pretty slick solution!
Allen
+5  A: 

Here's what I did, for stamping the AssemblyFileVersion attribute.

Removed the AssemblyFileVersion from AssemblyInfo.cs

Add a new, empty, file called AssemblyFileInfo.cs to the project.

Install the MSBuild community tasks from http://msbuildtasks.tigris.org/ on the hudson build machine.

Edit the project (csproj) file , it's just an msbuild file, and add the following.

Somewhere there'll be a <PropertyGroup> stating the version. Change that so it reads e.g.

 <Major>1</Major>
 <Minor>0</Minor>
 <!--Hudson sets BUILD_NUMBER and SVN_REVISION -->
 <Build>$(BUILD_NUMBER)</Build>
 <Revision>$(SVN_REVISION)</Revision>

Hudson provides those env variables you see there when the project is built on hudson (assuming it's fetched from subversion).

At the bottom of the project file, add

 <Import Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets" Condition="Exists('$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets')" />
  <Target Name="BeforeBuild" Condition="Exists('$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets')">
    <Message Text="Version: $(Major).$(Minor).$(Build).$(Revision)" />
    <AssemblyInfo CodeLanguage="CS" OutputFile="AssemblyFileInfo.cs" AssemblyFileVersion="$(Major).$(Minor).$(Build).$(Revision)" AssemblyConfiguration="$(Configuration)" Condition="$(Revision) != '' " />
  </Target>

This uses the MSBuildCommunityTasks to generate the AssemblyFileVersion.cs to include an AssemblyFileVersion attribute before the project is built. You could do this for any/all of the version attributes if you want.

The result is, whenever you issue a hudson build, the resulting assembly gets an AssemblyFileVersion of 1.0.HUDSON_BUILD_NR.SVN_REVISION e.g. 1.0.6.2632 , which means the 6'th build # in hudson, buit from the subversion revision 2632.

nos
pretty slick, i'll look into this
Allen