views:

2811

answers:

6

I've seen a few examples on how to do build deployment, however I have something unique that I'd like to do:

  1. Deploy the build to a folder that has the build number (eg. Project\Builds\8423)
  2. Alter the version number in the .NET AssmblyInfo.cs to match the build number

Has anyone done this before with .NET projects using NAnt + CruiseControl.net?

+1  A: 

i haven't done it with nant, but we have written a custom application in C# that reads the assembly and increments the release number.

we call it from an exec block in the ccnet config.

creating a folder and copying files would be trivial to add to that application

our thinking was we use C# all day, so it would be quicker to fix/alter the build program written in C#, then if we had to learn the intracies of nant scripts on top of that

obviously if you use nant all the time, there would be no reason not to build a custom nant plugin to do the job

A: 

I agree with BumperBox, a separate assembly to do the heavy(?) lifting of incrementing the build number is the route I took a couple of years ago, too. It has the advantage of being able to cope with other external factors, too. For example, you might want to increment the release or build numbers if a certain criteria exists within a config file.

ZombieSheep
+2  A: 

Check out this open-source project. Although, it uses MSBuild, the differences are minor.

CC.NET passes the distrib directory and version to the Photon.ccnet script, which is a simple wrapper around Photon.build script. Version number is used in folder and package naming and also in the assembly versions.

Version numbers come from the svnRevisionLabellerPlugin for CC.NET

And that's how everything looks in the end.

Rinat Abdullin
A: 

You can use the CCNetLabel property that is passed into your NAnt script to set where it deploys to.

As for the AssemblyInfo, for MSBuild there is a Task in MSBuildCommunityTasks that works well. Don't know what the NAnt equivalent would be although you could run an MSBuild script before your NAnt script that changed it.

Configuration is simple:

<AssemblyInfo CodeLanguage="C#"
 OutputFile="%(YourProjects.RootDir)%(Directory)Properties\AssemblyInfo.cs"
 AssemblyVersion="$(CCNetLabel)"
/>

You will need to add whatever other attributes you need as well as this will overwrite the AssemblyInfo file.

Mike
+7  A: 

Deploying a build to a folder with the build number is pretty straightforward. CruiseControl.NET's NAnt task automatically passes a number of properties to your NAnt script. The CCNetLabel property is the one you'd use to create your deployment directory. There's actually a slightly out of date example NAnt script in the CruiseControl.NET documentation that does just that. Here's a nicer version of it:

<target name="publish">
    <if test="${not property::exists('CCNetLabel')}">
        <fail message="CCNetLabel property not set, so can't create labelled distribution files" />
    </if>

    <property name="publishDirectory" value="D:\Public\Project\Builds\${CCNetLabel}" />

    <mkdir dir="${publishDirectory}" />
    <copy todir="${publishDirectory}">
        <fileset basedir="${buildDirectory}\bin">
            <include name="*.dll" />
        </fileset>
    </copy>   
</target>

As far as versioning your binaries goes, I find the following approach much cleaner and easier than trying to alter your AssemblyInfo.cs files. Basically I create a CommonAssemblyInfo.cs file that lives outside of any projects, in the same directory as your solution file. This file includes things that are common to all assemblies I'm building, like company name, copyright info, and of course - version. This file is linked in each project in Visual Studio, so each project includes this info (along with a much smaller AssemblyInfo.cs file that includes assembly-specific info like assembly title).

When projects are built locally, either through Visual Studio or NAnt, that CommonAssemblyInfo.cs file is used. However, when projects are built by CruiseControl.NET, I use NAnt to replace that file via the <asminfo> task. Here's what the NAnt script looks like:

<target name="version">
    <property name="commonAssemblyInfo" value="${buildDirectory}\CommonAssemblyInfo.cs" />

    <!-- If build is initiated manually, copy standard CommonAssemblyInfo.cs file. -->
    <if test="${not property::exists('CCNetLabel')}">
        <copy file=".\src\CommonAssemblyInfo.cs" tofile="${commonAssemblyInfo}" />
    </if>

    <!-- If build is initiated by CC.NET, create a custom CommonAssemblyInfo.cs file. -->
    <if test="${property::exists('CCNetLabel')}">
        <asminfo output="${commonAssemblyInfo}" language="CSharp">
            <imports>
                <import namespace="System" />
                <import namespace="System.Reflection" />
            </imports>
            <attributes>
                <attribute type="AssemblyCompanyAttribute" value="My Company" />
                <attribute type="AssemblyCopyrightAttribute" value="Copyright © 2008 My Company" />
                <attribute type="AssemblyProductAttribute" value="My Product" />
                <attribute type="AssemblyVersionAttribute" value="1.0.0.${CCNetLabel}" />
                <attribute type="AssemblyInformationalVersionAttribute" value="1.0.0.${CCNetLabel}" />
            </attributes>
            <references>
                <include name="System.dll" />
            </references>
        </asminfo>
    </if>
</target>

<target name="build-my-project" depends="version">
    <csc target="library" output="${buildDirectory}\bin\MyProject.dll">
        <sources>
            <include name=".\src\MyProject\*.cs"/>
            <include name=".\src\MyProject\**\*.cs"/>
            <include name="${commonAssemblyInfo}"/>
        </sources>
    </csc>
</target>

Note where the AssemblyVersionAttribute and AssemblyInformationalVersionAttribute values are set in the version target. The CCNetLabel property is inserted into the version numbers. For added benefit, you could use a CruiseControl.NET plugin like the previously mentioned SvnRevisionLabeller. Using that, we get builds with labels like "2.1.8239.0", where the "8239" corresponds to the Subversion revision number we're building from. We dump this build number directly into our AssemblyVersionAttribute and AssemblyInformationalVersionAttributes, and our build numbers and the version numbers on our assemblies can all be easily traced back to a specific revision in our version control system.

scott.caligan
+2  A: 

I'm quite new to Cruise Control and nAnt as well but I found Scott Hanselman's Blog Post very helpful.

Not perfect and not pretty but it does get the job done.

There is also an UpdateVersion Utility (which Scott also appears to have had a hand in).

DilbertDave