使用CruiseControl.net进行构建部署
我已经看到了一些有关如何进行构建部署的示例,但是我想做一些独特的事情:
- 将内部版本部署到具有内部版本号的文件夹(例如Project \ Builds \ 8423)
- 更改.NET AssmblyInfo.cs中的版本号以匹配内部版本号
有人在使用NAnt + CruiseControl.net的.NET项目中做过此事吗?
解决方案
我还没有用nant完成它,但是我们已经在C语言中编写了一个自定义应用程序,该应用程序读取程序集并增加发行版号。
我们从ccnet配置中的exec块调用它。
创建一个文件夹并复制文件对于添加到该应用程序将是微不足道的
我们的想法是使用Call day,因此,修复/更改用C#编写的构建程序会更快,然后,如果我们必须在此基础上学习nant脚本的内在特性,
显然,如果我们一直使用nant,就没有理由不构建自定义的nant插件来完成这项工作
我同意BumperBox,BumperBox是一个单独的程序集,用于执行增加内部版本号的繁重任务吗?这也是我几年前采用的方法。它也具有能够应付其他外部因素的优势。例如,如果配置文件中存在某些条件,则可能要增加发行版或者内部版本号。
查看这个开源项目。尽管它使用MSBuild,但差异很小。
CC.NET将distrib目录和版本传递给Photon.ccnet脚本,该脚本是Photon.build脚本的简单包装。版本号用于文件夹和程序包的命名以及程序集版本中。
版本号来自CC.NET的svnRevisionLabellerPlugin
这就是最终一切的样子。
我们可以使用传递到NAnt脚本中的CCNetLabel属性来设置部署到的位置。
至于AssemblyInfo,对于MSBuild,MSBuildCommunityTasks中有一个工作得很好的任务。尽管我们可以在更改它的NAnt脚本之前运行MSBuild脚本,但不知道NAnt等同于什么。
配置很简单:
<AssemblyInfo CodeLanguage="C#"
OutputFile="%(YourProjects.RootDir)%(Directory)Properties\AssemblyInfo.cs"
AssemblyVersion="$(CCNetLabel)"
/>
我们将需要添加任何其他需要的属性,这将覆盖AssemblyInfo文件。
将内部版本部署到具有内部版本号的文件夹非常简单。 CruiseControl.NET的NAnt任务会自动将许多属性传递到NAnt脚本。 CCNetLabel属性是我们用来创建部署目录的属性。实际上,CruiseControl.NET文档中有一个稍微不合时宜的示例NAnt脚本。这是一个更好的版本:
<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>
就对二进制文件进行版本控制而言,我发现以下方法比尝试更改AssemblyInfo.cs文件更加干净和容易。基本上,我在与解决方案文件相同的目录中创建一个CommonAssemblyInfo.cs文件,该文件位于任何项目之外。该文件包含了我正在构建的所有程序集所共有的内容,例如公司名称,版权信息,当然还有版本。此文件在Visual Studio中的每个项目中都链接在一起,因此每个项目都包含此信息(以及一个较小的AssemblyInfo.cs文件,其中包含特定于程序集的信息(如程序集标题)。
通过Visual Studio或者NAnt在本地构建项目时,将使用该CommonAssemblyInfo.cs文件。但是,当项目由CruiseControl.NET构建时,我使用NAnt通过<asminfo>任务替换该文件。这是NAnt脚本的样子:
<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>
请注意在版本目标中设置了AssemblyVersionAttribute和AssemblyInformationalVersionAttribute值的位置。 CCNetLabel属性插入到版本号中。为了获得更多好处,我们可以使用CruiseControl.NET插件,如前面提到的SvnRevisionLabeller。使用它,我们得到带有" 2.1.8239.0"之类的标签的构建,其中" 8239"对应于我们从其构建的Subversion修订版号。我们将此内部版本号直接转储到AssemblyVersionAttribute和AssemblyInformationalVersionAttributes中,并且我们的内部版本号和程序集上的版本号都可以轻松地追溯到版本控制系统中的特定修订版。
我对Cruise Control和nAnt也很陌生,但是我发现Scott Hanselman的Blog Post很有帮助。
虽然不完美,也不漂亮,但是确实可以完成工作。
还有一个UpdateVersion实用程序(Scott似乎也有使用过)。

