65.9K
CodeProject 正在变化。 阅读更多。
Home

构建自动化工作流程

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.67/5 (5投票s)

2010年10月28日

CPOL

5分钟阅读

viewsIcon

39069

downloadIcon

495

使用 NAnt 和 Cruise Control 描述构建自动化的通用流程。

引言

每个解决方案都有其自己的配置集。因此,自动化构建系统所需的操作系统取决于项目。在这里,我建议了对每个项目都相同的有效工作流程和操作系统。

自动化流程

我使用了 Cruise Control 和 NAnt 进行构建自动化。Cruise control 是一个出色的工具,您可以使用它轻松地自动化您的构建并在团队中实现持续集成。它还非常容易集成其他服务输出,例如单元测试、NCover 结果,以改进构建过程并确保产品质量和可部署性。

Cruise control 定时器(<intervalTrigger seconds="60"/>)会在一定时间后触发,以检查是否有任何内容已提交到源代码控制,或者强制构建并启动构建过程。在我的项目中,我们的源代码控制由我们的客户维护,我们通过互联网访问。如果我们在每次提交后都签出整个解决方案进行构建,那么会花费很多时间,而我们只需要合并最后一次提交的文件。因此,我们创建一个名为 SVNFOLDER 的文件夹,其中我们只签出一次整个解决方案,然后每次 cruise control 只更新最新文件,但我们会在该签出位置运行构建过程,以确保我们的代码在 cruise control 下次获取最新更改时不会发生任何冲突。我们创建另一个名为 BUILDFOLDER 的文件夹,我们将新的代码从 SVNFOLDER 复制到其中,并执行所有构建解决方案的操作。这些操作我都是使用 NAnt 完成的。更新最新代码后,cruise control 会调用 config 文件中定义的 NAnt 脚本。

NAnt 操作可以通过以下步骤描述:

  1. 将整个源从 SNVFolder 复制到 BuildFolder
  2. 获取 SVN 修订号和 CCNet 级别来创建版本号。版本号格式为 <CCNetLevel>.<SVN Revision>
  3. 使用版本号和其他设置修改 GlobalAssembly.cs,并使用发布配置修改 web.config
  4. 使用所有配置运行 MSBuild 以重新构建解决方案。
  5. 如果您的项目包含单元测试,则运行单元测试。
  6. 运行 NCoverage(可选)。
  7. 您还可以运行 FxCop 和其他工具来分析您的构建。此步骤也是可选的。
  8. 创建安装程序文件或其他可部署的输出。
  9. 将可部署的输出与版本号一起复制到 SetupFolder

当从 CCNET 点击 ForceBuild 或 BuildCondition = “ForceBuild” 时,Nant 会执行上述 1 到 9 的所有操作。而对于开发人员的常规提交,NAnt 只执行步骤 1 到 7,以确保开发人员的最后一次提交是安全的,可以创建可部署的输出。

构建自动化的工作流程如下:

NANTBuildDiagram.png

实现

我在这里包含了 ccnet 配置文件和 Nant 构建脚本,这些脚本是根据上述步骤实现的。现在我将在此描述我的 CCNet 和 Nant 脚本。

在团队环境中,我们需要确保我提交到源代码控制的代码不会破坏构建,并且还要确保我的代码也是可部署的。为了确保我们提交的代码不会破坏构建,我们可以使用构建自动化工具在每次提交后构建解决方案,或者可以进行预提交构建(TeamCity CI 工具),这可以确保最后一次提交的代码对团队开发是安全的。成功构建后,我们可以创建安装程序文件或可部署的输出,但这不是每次提交都需要的,这可能会增加我们的自动化处理时间。但是,为了确保可部署的输出/安装程序文件也是安全的,我们可以通过夜间构建自动创建安装程序文件。我们可以很容易地通过 cruise control 的 <triggers> 选项来实现。

<triggers>
  <intervaltrigger seconds="60">
  <scheduletrigger time="04:00" buildcondition="ForceBuild">
</scheduletrigger></intervaltrigger></triggers>

在这里,CCNet 每 60 秒触发一次,以检查是否有任何新的代码提交到 SVN。如果发现开发人员有任何最新的提交,它就会运行 NAnt 脚本。并且使用计划触发器,它会在早上 6 点以强制构建模式运行 Nant,而不管是否有任何最新代码提交到 SVN。如果您愿意,可以在 Force build 条件为 true 时创建 Setup 文件/可部署输出,否则只重新构建解决方案,然后您可以在 Nant 中创建一个目标,该目标根据您的 BuildCondition 做出此决定。

<target name="Run">
		<property value="" name="CCNetBuildCondition" overwrite="false"/>
		<call target="BuildPublish" 
			unless="${CCNetBuildCondition=='ForceBuild'}">
		<call target="BuildSetup" if="${CCNetBuildCondition=='ForceBuild'}"/>
</target> 

在此,“Run”目标调用另外两个目标“BuildPublish”和“BuildSetup”。当您按下 CCNet 的“Force Build”按钮或使用 BuildCondition =”ForceBuild” 时,它将调用“BuildSetup”目标,否则对于源代码的常规提交,它将运行“BuildPublish”以确保您的源代码始终可部署。

在“BuildPublish”目标中,它首先调用“setversion”目标,并以发布模式运行 MSBuild 来重新构建解决方案,这是上述流程的第 4 步。您还可以在 MSBuild 命令之后包含单元测试脚本和 NConverage 脚本调用,以确保您的单元测试代码在提交后运行良好。

<target name="BuildPublish" depends="setversion">

  <echo message="Build is published"/>    
	<exec program="${MSBuildPath}">
		<arg value="${BuildDir}\${SolutionFileName}" />
		<arg value="/property:Configuration=release" />    
              <arg value="/t:Rebuild" />
	</exec>	 
</target> 

在这里,在重新构建解决方案之前,它首先调用“setversion”目标(步骤 3)。“setversion”目标还依赖于另一个名为“get”的目标,并在执行“get”目标后,调用“getSubversionRevision”,这是步骤 2。这对于维护版本号至关重要,以便了解我们的构建系统正在使用哪个 SVN 最新修订版本。获取修订号后,它会设置程序集通用程序集文件的版本。因此,我们的程序集也知道 CCNet 构建号和 SVN 修订号。

  <target name="setversion" depends="get">
    <call target="getSubversionRevision"/>
    <asminfo output="${BuildDir}\GlobalAssemblyInfo.cs" language="CSharp">
      <attributes>
        <attribute
                type="System.Reflection.AssemblyFileVersionAttribute"
                value="${CCNetLabel}.${RevisionNumber}"/>
      </attributes>
    </asminfo>
  </target>

现在,基本的第一步是将 SVN 文件夹复制到 BUILD 文件夹,以运行上述目标,这样 SVN 文件夹将保持与最新 SVN 存储库相同,并减少获取最新提交所需的时间。NAnt 在 BUILD 文件夹上进行的所有修改都是 SVN 文件夹的副本。因此,SVN 文件夹始终安全,不会与 SVN 存储库发生冲突。

<target name="clean" description="Remove all files from target folder.">
    <delete dir="${BuildDir}" failonerror="false" />
    <mkdir dir="${BuildDir}" />
  </target>

  <target name="get" depends="clean">
    <copy todir="${BuildDir}">
      <fileset basedir="${SVNDir}">
        <include name="**/**"/>
      </fileset>
    </copy>
  </target> 

在此,我描述了开发人员提交代码后,并且 BuildCondition 不等于“ForceBuild”时执行的步骤 1 到 4。

现在,当 Build Condition 为“ForceBuild”时,它会调用“BuildSetup”目标,该目标也依赖于“BuildPublish”。这意味着对于“ForceBuild”,将先执行步骤 1 到 4,然后创建安装程序文件。此目标是

<target name="BuildSetup" depends="BuildPublish" >
    <echo message="Build is setup"/>
    <script language="c#">

      <code>

        <![cdata[ 

       Here have some code which used to change product code so that running setup 
       allowed on machine with already contained previous version of this product.
]]>
        
      </code>

    </script>

    <exec program="${VisualStudio9}" failonerror="true"   
	commandline="/build Release ${BuildDir}\${SolutionFileName} 
	/project MYPROJECT.Setup">
    </exec>

    <property name="publish.dir" value="${ResultDir}\${CCNetLabel}.${RevisionNumber}" />

    <mkdir dir="${publish.dir}" />
    <copy todir="${publish.dir}">
      <fileset basedir="${BuildDir}\MYPROJECT.Setup\release">
        <include name="*"/>
      </fileset>
    </copy>

  </target>

在执行完“BuildPublish”目标的所有步骤后,它首先运行 Setup 项目并创建安装程序文件。然后,它在部署文件夹中创建版本文件,并将安装程序文件复制到该位置,以便于了解此安装程序是为哪个 SVN 修订和 CCNet 标签创建的。

结论

我在这里描述了构建自动化的所有步骤及其实现,这些都是所有项目通用的。我没有在此包含一些 NAnt 目标,例如 NUnit、NCover、NCoverExplorer、FxCop,它们在我的一些项目中有所实现。我没有包含这些 NAnt 目标,因为它们对于所有项目来说都不是必需的。

© . All rights reserved.