前言

团队开发需要进行集中的项目文件管理与有效的协调,我们采用源代码管理工具协助我们管理,卓有成效。限定重要文件的访问权限、使用悲观锁杜绝成员同时编辑同一份文件、不允许长时间迁出文件等规则让我们在某一时间段内非常愉快。但是慢慢的,有人抱怨“我获取了源代码怎么编译错误?”。于是增加规定:迁入之前必须获取最新,然后再一次编译,成功后方可迁入VSS。这种办法是很不错,但是工作繁琐了,尤其对大型项目,更加的苦不堪言。看来我们需要一个机器人帮我们,那就是持续集成。持续集成是一种实践,可以让团队在持续的基础上收到反馈并进行改进,不必等到开发周期后期才寻找和修复缺陷。通俗一点儿说,就是指对于开发人员的每一次代码提交,都自动地把代码仓库中所有代码获取下来,执行编译、并自动运行所有的测试用例,如出现错误则通知人员这是一个失败的提交。一个适合的集成频率非常重要,根据团队的实际情况采用灵活的集成频率,过于频繁的频率会加大持续集成的实施难度,甚至最后实施失败。接下来简单介绍一下在.NET上常用的持续集成软件CruiseControl.NET和它的使用方法。

CruiseControl.NET实际应用

 

 

在实验部署中,CruiseControl.NET集成了如下功能:

  1. MsBuild集成编译
  2. 电子邮件提醒功能
  3. Nunit单元测试报告
  4. 自动发布网站应用程序到指定目录

CruiseControl.NET安装

目前CruiseControl.NET官方网站提供的最新版本为1.4.2,提供三种方式下载——源代码、zip压缩包、windows安装文件。选择windows安装文件最为方便,下载相应的exe文件,点击选择安装目录安装即可。安装完成后,我们可以选择点击ccnet.exe来启动软件也可以选择从系统服务启动。

CruiseControl.NET配置

程序配置文件ccnet.config是CruiseControl.NET Server最核心的文件,借助CCNetConfig图形化工具我们可以很方便的进行配置的修改,下面我就分别介绍每一项如何进行配置:

基础配置

配置文件为xml格式,最外层的标签为cruisecontrol,包含一个完整的配置,如下所示:

Xml代码 复制代码 收藏代码
  1. <cruisecontrol> 
  2.     <queuename="Q1"duplicates="ApplyForceBuildsReplace"/> 
  3.         ... ...  
  4. </cruisecontrol> 
<cruisecontrol>
    <queue name="Q1" duplicates="ApplyForceBuildsReplace"/>
        ... ...
</cruisecontrol>

queue标签

queue标签允许进行集成请求序列配置,规定重复的集成请求如何被处理,一共有三种处理方式:

  • UseFirst:默认的处理方式,处理第一个添加的请求
  • ApplyForceBuildsReplace:允许强制集成替换现有的请求序列,但是不改变请求序列的位置
  • ApplyForceBuildsReAdd:允许强制集成删除即将执行的请求,同时重新添加强制集成进入序列

  配置项目

Xml代码 复制代码 收藏代码
  1. <!--name:项目名称;queue:采用何种序列处理方式;queuePriority:序列的优先级--> 
  2. <projectname="Project 1"queue="Q1"queuePriority="1"> 
  3.     <!--工作目录的配置,设定一个绝对路径作为集成的工作目录--> 
  4.     <workingDirectory>yourWorkingDirectory</workingDirectory> 
  5.     <!--集成结果保存路径,每个项目配置一个唯一路径--> 
  6.     <artifactDirectory>yourArtifactDirectory</artifactDirectory> 
  7.     <!--web界面集成报告的URL,这个URL一般用在邮件内容中--> 
  8.     <webURL>http://server1/ccnet/server/local/project/testProject/ViewLatestBuildReport.aspx</webURL> 
  9.     <!--源代码迁入与启动集成的最少时间间隔--> 
  10.     <modificationDelaySeconds>2</modificationDelaySeconds> 
  11.     <!--触发模式,一般采用间隔触发器--> 
  12.     <triggers> 
  13.         <!--name:触发器名称;seconds:间隔时间;BuildCondition:构建条件,有两个选项——强制集成ForceBuild和文件变动时集成IfModificationExists;initialSeconds:server启动与第一次构建的时间间隔--> 
  14.         <intervalTriggername="continuous"seconds="30"buildCondition="ForceBuild"initialSeconds="30"/> 
  15.     </triggers> 
  16. </project> 
<!--name:项目名称;queue:采用何种序列处理方式;queuePriority:序列的优先级-->
<project name="Project 1" queue="Q1" queuePriority="1">
    <!--工作目录的配置,设定一个绝对路径作为集成的工作目录-->
    <workingDirectory>yourWorkingDirectory</workingDirectory>
    <!--集成结果保存路径,每个项目配置一个唯一路径-->
    <artifactDirectory>yourArtifactDirectory</artifactDirectory>
    <!--web界面集成报告的URL,这个URL一般用在邮件内容中-->
    <webURL>http://server1/ccnet/server/local/project/testProject/ViewLatestBuildReport.aspx</webURL>
    <!--源代码迁入与启动集成的最少时间间隔-->
    <modificationDelaySeconds>2</modificationDelaySeconds>
    <!--触发模式,一般采用间隔触发器-->
    <triggers>
        <!--name:触发器名称;seconds:间隔时间;BuildCondition:构建条件,有两个选项——强制集成ForceBuild和文件变动时集成IfModificationExists;initialSeconds:server启动与第一次构建的时间间隔-->
        <intervalTrigger name="continuous" seconds="30" buildCondition="ForceBuild" initialSeconds="30"/>
    </triggers>
</project>

配置源代码管理

源代码管理为项目配置中的一个子结点,下面以VSS为例做一下详细的介绍,示例及解释如下:

Xml代码 复制代码 收藏代码
  1. <sourcecontroltype="vss"> 
  2.    <!--VSS的执行文件--> 
  3.    <executable>C:\Program Files\Microsoft Visual Studio\VSS\win32\SS.EXE</executable> 
  4.    <!--源代码的VSS路径--> 
  5.    <project>$/CCNET</project> 
  6.    <!--VSS用户名--> 
  7.    <username>buildguy</username> 
  8.    <!--VSS密码--> 
  9.    <password>buildguypw</password> 
  10.    <!--VSS路径,包含SRCSAFE.INI的目录--> 
  11.    <ssdir>\\192.168.1.1\vss</ssdir> 
  12.    <!--VSS工作目录,源代码将获取到改目录中--> 
  13.    <workingDirectory>c:\myBuild</workingDirectory> 
  14.    <!--VSS操作的过期时间--> 
  15.    <timeoutunits="minutes">10</timeout> 
  16. </sourcecontrol> 
<sourcecontrol type="vss">
   <!--VSS的执行文件-->
   <executable>C:\Program Files\Microsoft Visual Studio\VSS\win32\SS.EXE</executable>
   <!--源代码的VSS路径-->
   <project>$/CCNET</project>
   <!--VSS用户名-->
   <username>buildguy</username>
   <!--VSS密码-->
   <password>buildguypw</password>
   <!--VSS路径,包含SRCSAFE.INI的目录-->
   <ssdir>\\192.168.1.1\vss</ssdir>
   <!--VSS工作目录,源代码将获取到改目录中-->
   <workingDirectory>c:\myBuild</workingDirectory>
   <!--VSS操作的过期时间-->
   <timeout units="minutes">10</timeout>
</sourcecontrol>

配置编译

源代码配置完成后,CCNet Server就能够把源代码获取到本地了,下面我们就可以配置构建节点,让CCNet为我们进行自动构建。CCNet支持NAnt、MSBuild两种构建方式,通过这两种方式我们可以方便的进行项目集成编译。NAnt是功能非常强大的开源.NET编译工具,但是需要编写build文件,该文件负责指导Nant进行编译,NAnt也可以直接编译sln文件,但是对2005支持不好。MSBuild是微软随VS2005一起发布的一个集成编译工具,和NAnt类似,可以直接编译sln文件,功能上完全可以替代NAnt,下面就以MSBuild为例介绍一下如何进行配置:

Xml代码 复制代码 收藏代码
  1. <msbuild> 
  2.   <!--MSBuild的路径--> 
  3.   <executable>C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\MSBuild.exe</executable> 
  4.   <!--工作路径--> 
  5.   <workingDirectory>C:\dev\ccnet</workingDirectory> 
  6.   <!--解决方案或项目文件--> 
  7.   <projectFile>CCNet.sln</projectFile> 
  8.   <!--MSBuild的构建参数--> 
  9.   <buildArgs>/noconsolelogger /p:Configuration=Debug /v:diag</buildArgs> 
  10.   <!--构建目标--> 
  11.   <targets>Build</targets> 
  12.   <!--超时时间--> 
  13.   <timeout>900</timeout> 
  14.   <!--日志文件处理模快--> 
  15.   <logger>C:\Program Files\CruiseControl.NET\server\ThoughtWorks.CruiseControl.MsBuild.dll</logger> 
  16. </msbuild> 
<msbuild>
  <!--MSBuild的路径-->
  <executable>C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\MSBuild.exe</executable>
  <!--工作路径-->
  <workingDirectory>C:\dev\ccnet</workingDirectory>
  <!--解决方案或项目文件-->
  <projectFile>CCNet.sln</projectFile>
  <!--MSBuild的构建参数-->
  <buildArgs>/noconsolelogger /p:Configuration=Debug /v:diag</buildArgs>
  <!--构建目标-->
  <targets>Build</targets>
  <!--超时时间-->
  <timeout>900</timeout>
  <!--日志文件处理模快-->
  <logger>C:\Program Files\CruiseControl.NET\server\ThoughtWorks.CruiseControl.MsBuild.dll</logger>
</msbuild>

 

通过设定msbuild的参数还可以执行很多复杂的任务,例如发布网站到指定目录。

 

配置单元测试

如果某个类库或应用程序包含单元测试,我们可以配置是的ccnet在集成过程中运行单元测试,基本配置范例与说明如下:

Xml代码 复制代码 收藏代码
  1. <nunit> 
  2.     <!--nunit的路径--> 
  3.     <path>D:\dev\ccnet\ccnet\tools\nunit\nunit-console.exe</path> 
  4.     <!--需要进行单元测试的程序集--> 
  5.     <assemblies> 
  6.         <assembly>D:\dev\Refactoring\bin\Debug\Refactoring.exe</assembly> 
  7.         <assembly>D:\dev\Refactoring\bin\Debug\Refactoring.Core.dll</assembly> 
  8.     </assemblies> 
  9. </nunit> 
<nunit>
    <!--nunit的路径-->
    <path>D:\dev\ccnet\ccnet\tools\nunit\nunit-console.exe</path>
    <!--需要进行单元测试的程序集-->
    <assemblies>
        <assembly>D:\dev\Refactoring\bin\Debug\Refactoring.exe</assembly>
        <assembly>D:\dev\Refactoring\bin\Debug\Refactoring.Core.dll</assembly>
    </assemblies>
</nunit>

配置邮件提醒

邮件提醒任务需要部署在publishers节点下面,若部署在tasks节点下面,发生构建失败将不会执行后续任务,因此无法收到失败的提醒邮件。配置的示例代码及解释如下:

Xml代码 复制代码 收藏代码
  1. <!--from:邮件发件人;mailhost:邮件服务器地址;mailport:smtp端口;includeDetail:是否包含详细报告信息;mailhostUsername:smtp用户名;mailhostPassword:smtp密码;useSSL:是否使用ssl发送邮件--> 
  2. <emailfrom="buildmaster@mycompany.com"mailhost="smtp.mycompany.com"mailport="25"includeDetails="TRUE" 
  3.            mailhostUsername="smtpuser"mailhostPassword="smtppassword"useSSL="FALSE"> 
  4.     <!--定义一组接收邮件的用户--> 
  5.     <users> 
  6.         <!--name:用户名称,必须同源代码管理系统的帐号一致;group:所属分组;address:邮件地址;--> 
  7.         <username="BuildGuru"group="buildmaster"address="buildguru@mycompany.com"/> 
  8.         <username="JoeDeveloper"group="developers"address="joedeveloper@thoughtworks.com"/> 
  9.     </users> 
  10.     <!--用户组--> 
  11.     <groups> 
  12.         <!--name:组名称;nitification:通知策略——Always[每次构建均发送通知]、Changed[构建结果发生改变时发送通知,例如从success变为fail]、Failed[当构建失败时发送通知]、Success[当构建成功时发送通知]、Fixed[当构建从失败到通知时发送通知]、Exception[构建发生异常时发送通知]--> 
  13.         <groupname="developers"notification="change"/> 
  14.         <groupname="buildmaster"notification="always"/> 
  15.     </groups> 
  16.     <!--设置提交者通知测略,当构建完成后,符合符合设置的条件将邮件通知所有此次源代码改变的参与者--> 
  17.     <modifierNotificationTypes> 
  18.        <NotificationType>Failed</NotificationType> 
  19.        <NotificationType>Fixed</NotificationType> 
  20.     </modifierNotificationTypes> 
  21. </email> 
<!--from:邮件发件人;mailhost:邮件服务器地址;mailport:smtp端口;includeDetail:是否包含详细报告信息;mailhostUsername:smtp用户名;mailhostPassword:smtp密码;useSSL:是否使用ssl发送邮件-->
<email from="buildmaster@mycompany.com" mailhost="smtp.mycompany.com" mailport="25" includeDetails="TRUE"
           mailhostUsername="smtpuser" mailhostPassword="smtppassword" useSSL="FALSE">
    <!--定义一组接收邮件的用户-->
    <users>
        <!--name:用户名称,必须同源代码管理系统的帐号一致;group:所属分组;address:邮件地址;-->
        <user name="BuildGuru" group="buildmaster" address="buildguru@mycompany.com"/>
        <user name="JoeDeveloper" group="developers" address="joedeveloper@thoughtworks.com"/>
    </users>
    <!--用户组-->
    <groups>
        <!--name:组名称;nitification:通知策略——Always[每次构建均发送通知]、Changed[构建结果发生改变时发送通知,例如从success变为fail]、Failed[当构建失败时发送通知]、Success[当构建成功时发送通知]、Fixed[当构建从失败到通知时发送通知]、Exception[构建发生异常时发送通知]-->
        <group name="developers" notification="change"/>
        <group name="buildmaster" notification="always"/>
    </groups>
    <!--设置提交者通知测略,当构建完成后,符合符合设置的条件将邮件通知所有此次源代码改变的参与者-->
    <modifierNotificationTypes>
       <NotificationType>Failed</NotificationType>
       <NotificationType>Fixed</NotificationType>
    </modifierNotificationTypes>
</email>

配置范例

为节省大家时间,这里提供了一个基本的配置文件,包含单元测试、编译、网站发布、邮件通知。

Xml代码 复制代码 收藏代码
  1. <cruisecontrol> 
  2.   <projectname="CI2.0"queue="Q1"queuePriority="1"> 
  3.     <workingDirectory>E:\Integration\CI2.0\WorkingDirectory</workingDirectory> 
  4.     <artifactDirectory>E:\Integration\CI2.0\Artifacts</artifactDirectory> 
  5.     <webURL>http://192.168.1.1/ccnet/server/local/project/CI2.0/ViewLatestBuildReport.aspx</webURL> 
  6.     <modificationDelaySeconds>10</modificationDelaySeconds> 
  7.     <sourcecontroltype="vss"> 
  8.       <project>$/CI2.0</project> 
  9.       <username>tianc</username> 
  10.       <password>password</password> 
  11.       <executable>D:\Program Files\Microsoft Visual SourceSafe\SS.EXE</executable> 
  12.       <ssdir>\\192.168.1.2\vss</ssdir> 
  13.       <autoGetSource>True</autoGetSource> 
  14.       <applyLabel>False</applyLabel> 
  15.       <workingDirectory>E:\Integration\CI2.0\WorkingDir</workingDirectory> 
  16.       <timeoutunits="Minutes">10</timeout> 
  17.       <culture>zh-CN</culture> 
  18.       <cleanCopy>True</cleanCopy> 
  19.     </sourcecontrol> 
  20.     <triggers> 
  21.       <intervalTriggername="continuous"seconds="60"/> 
  22.     </triggers> 
  23.     <tasks> 
  24.       <msbuild> 
  25.         <executable>C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\MSBuild.exe</executable> 
  26.         <workingDirectory>E:\Integration\CI2.0\WorkingDir</workingDirectory> 
  27.         <projectFile>E:\Integration\CI2.0\WorkingDir\Src\2.0\CI.Web\CI.Web.csproj</projectFile> 
  28.         <buildArgs>/noconsolelogger /p:Configuration=Release;OutDir=E:\Integration\CI2.0\WorkingDir\Release\2.0\ /v:diag</buildArgs> 
  29.         <targets>CLean;Build;_CopyWebApplication</targets> 
  30.         <logger>D:\Program Files\CruiseControl.NET\server\ThoughtWorks.CruiseControl.MSBuild.dll</logger> 
  31.         <timeout>600</timeout> 
  32.       </msbuild> 
  33.       <nunit> 
  34.         <path>D:\Program Files\NUnit 2.4.8\bin\nunit-console.exe</path> 
  35.         <outputfile>E:\Integration\Bitauto.Review2.0\Artifacts\nunit-results.xml</outputfile> 
  36.         <assemblies> 
  37.         <assembly>E:\Integration\CI2.0\WorkingDir\Src\2.0\CI.Data\bin\Release\CI.Data.dll</assembly> 
  38.           <assembly>E:\Integration\CI2.0\WorkingDir\Src\2.0\CI.BLL\bin\Release\CI.BLL.dll</assembly> 
  39.         </assemblies> 
  40.       </nunit> 
  41.       <buildpublisher> 
  42.         <sourceDir>E:\Integration\CI2.0\WorkingDir\Release\2.0\_PublishedWebsites</sourceDir> 
  43.         <publishDir>E:\Integration\CI2.0\Release</publishDir> 
  44.       </buildpublisher> 
  45.     </tasks> 
  46.     <publishers> 
  47.       <xmlloggerlogDir="E:\Integration\CI2.0\XmlLogger"/> 
  48.       <emailmailhost="mail.CI.com"from="ci@CI.com"> 
  49.         <mailhostUsername>tianc</mailhostUsername> 
  50.         <mailhostPassword>password</mailhostPassword> 
  51.         <includeDetails>True</includeDetails> 
  52.         <users> 
  53.           <username="tianc"address="tianc@CI.com"group="developer"/> 
  54.           <username="lizd"address="lizd@CI.com"group="developer"/> 
  55.           <username="xiongyh"address="xiongyh@CI.com"group="developer"/> 
  56.         </users> 
  57.         <groups> 
  58.           <groupname="developer"notification="Always"/> 
  59.         </groups> 
  60.         <converters/> 
  61.         <modifierNotificationTypes> 
  62.           <NotificationType>Always</NotificationType> 
  63.         </modifierNotificationTypes> 
  64.       </email> 
  65.     </publishers> 
  66.     <statetype="state"directory="E:\Integration\CI2.0\CCNetState"/> 
  67.   </project> 
  68. </cruisecontrol>