Thursday, May 17, 2007

Continuous Integration with Subversion and AssemblyInfo

Building a continuous integration environment is becoming easier every day. How nice is it to have all of your source code automatically versioned with each build from continuous integration?
Here are some steps that might help when using Subversion:

A task to retrieve the latest subversion change number from the repository


<echo message="Retrieving Subversion revision number"/>
<property name="svn.revision" value="not_available"/>
<exec
program="c:\program files\subversion\bin\svn.exe"
commandline="log ${code.trunk} -r HEAD --xml"
output="_revision.xml"
failonerror="false"/>
<xmlpeek
file="_revision.xml"
xpath="/log/logentry/@revision"
property="svn.revision"
failonerror="false"/>
<echo message="Using Subversion revision number: ${svn.revision}"/>


Now add a task that will update all of the CommonAssemblyInfo.cs and AssemblyInfo.cs files that have the AssemblyVersion attribute defined.


<target name="SetVersions" description="Stamp the version info onto assemblyinfo.cs files">
<foreach item="File" property="filename">
<in>
<items basedir=".">
<include name="**\AssemblyInfo.cs"></include>
<include name="**\CommonAssemblyInfo.cs"></include>
</items>
</in>
<do>
<script language="C#">
<code><![CDATA[
public static void ScriptMain(Project project)
{
StreamReader reader = new StreamReader(project.Properties["filename"]);
string contents = reader.ReadToEnd();
reader.Close();
string pattern = @"\[assembly: AssemblyVersion\("".*""\)\]";
if (Regex.IsMatch(contents, pattern))
{
string replacement = string.Format(
"[assembly: AssemblyVersion(\"{0}.{1}.{2}.{3}\")]",
project.Properties["build.version.major"],
project.Properties["build.version.minor"],
project.Properties["build.version.build"],
project.Properties["build.version.revision"]
);
string newText = Regex.Replace(contents, pattern, replacement);
StreamWriter writer = new StreamWriter(project.Properties["filename"], false);
writer.Write(newText);
writer.Close();
}
}
]]>
</code>
</script>
</do>
</foreach>
</target>



And now tie it all together with this little task before executing your build, and you should have an accurately versioned build every time!


<property name="build.version.major" value="1" />
<property name="build.version.minor" value="0" />
<property name="build.version.build" value="0" />
<property name="build.version.revision" value="*" />

<target name="UpdateVersions">
<call target="RetrieveSVNChangeNumber" />
<property name="build.version.build" value="${svn.revision}" />

<call target="SetVersions" />
</target>



Of course the next step could be to check in all of those updated assembly info files...

kick it on DotNetKicks.com Shout it

No comments: