【Hello CC.NET】CC.NET 实现自动化集成

一、背景

公司的某一金融项目包含 12 个子系统,新需求一般按分支来开发,测完后合并到主干发布。开发团队需要同时维护开发环境、测试环境、模拟环境(主干)。目前面临最大的两个问题:

  1.子系统太多,每次发布(包括开发环境、测试环境、模拟环境)都比较耗时间

  2.业务数据和报表的数据(主要是汇率、金额、手续费之类)仍依赖 Tester 人工验证,一个 sprint 一般需要走一周 以上。

自动化测试和持续集成提了近一年,但由于各种因素的影响,还是在原地踏步。所幸仍有一两个不怕背黑锅的搭档,今日终于迈出这最艰难的第一步。

 

二、关于持续集成(Continuous integration,CI)

一个比较简单的定义如下:持续集成(CI)是一种实践,可以让团队在持续的基础 上收到反馈并进行改进,不必等到开发周期后期才寻找和修复缺陷。

一般地包括以下几个步骤:

  1.CI 服务器从版本管理服务器检查代码版本,如果有新的提交,则下载最新的源码版本

  2.编译最新版本的源码

  3.运行所有测试脚本

  4.进行代码分析

  5.产生更新包,提供发布(或写脚本自动发布)

以上步骤串行执行,任何一个环节失败,则该 build  失败。CI 服务器将给开发团队相应的反馈。

 

三、关于 CruiseControl.Net

CruiseControl.Net 是一款开源的自动集成工具 http://www.cruisecontrolnet.org/projects/ccnet/wiki

源码地址:https://github.com/ccnet/CruiseControl.NEThttp://sourceforge.net/projects/ccnet/files/

 

四、环境准备

找一个干净的虚拟机环境,WInServer2008/Win7,安装以下工具:

安装 IIS / SFTP

.NET/编译/Test 环境:VS 2010(用到其中的 MsBuild,MsTest)

源码管理服务器:VisualSVNServer 2.1

CC.NET 服务端:CruiseControl.NET-1.8.3

 开发机(本机)安装以下工具:

  开发工具:VS 2010

源码管理客户端:TortoiseSVN-1.8

CC.NET 客户端:CruiseControl.NET-CCTray

步骤

1.安装 IIS / SFTP 

 控制版面>程序和功能>打开或关闭 Windows 功能

2. VS 2010

 这里用的是旗舰版

3.安装好 VisualSVNServer 2.1 ,添加一个项目 Test,添加两个用户 ci、harvey.choi

(申请公司开通 ci@XXXcompany.com 邮箱,后面配置 publisher 时会用到)

4.安装 CC.NET 服务端,安装目录下有一个 webdashboard 文件夹,在 IIS 中添加一个网站,指向这个文件夹

5.创建一个测试解决方案,添加 Lib/LibTest 项目,提交到 SVN Server

测试的逻辑尽量简单

 1 //Lib/Calculator.cs
 2 namespace Lib
 3 {
 4     public class Calculator
 5     {
 6         public int Add(params int[] items)
 7         {
 8             var result = 0;
 9             foreach (var i in items)
10                 result += i;
11             return result;
12         }
13     }
14 }
15 
16 //LibTest/Test.cs
17 namespace LibTest
18 {
19     [TestClass]
20     public class Test
21     {
22         [TestMethod]
23         public void Calculator_Add()
24         {
25             var c = new Lib.Calculator();
26 
27             var result = c.Add(1, 2, 3);
28 
29             Assert.AreEqual(result, 6);
30         }
31     }
32 }

 

五、CC.NET 配置

CC.NET 的配置文件是 安装目录\server\ccnet.config

官方文档:http://www.cruisecontrolnet.org/attachments/download/10/customisingcruisecontrol-net.pdf

在线:http://www.cruisecontrolnet.org/projects/ccnet/wiki/Configuration

CC.NET 提供 windows 服务 及 控制台程序两种方式运行。windows 服务需要手动启动(可按需修改为自动启动);控制台程序为 安装目录\安装目录\server\ccnet.exe。本 demo 中用控制台方式运行,方便查看运行结果。

 

1.源代码管理

ccnet.config 配置如下:

<cruisecontrol xmlns:cb="urn:ccnet.config.builder">
  <project name="Lib.Sln">
    <!--标签-->
    <labeller type="dateLabeller"/>
    <artifactDirectory>C:\CC.NET\Server\Test\ArtifactDirectory</artifactDirectory>
    <!--项目的目录-->
    <workingDirectory >C:\CC.NET\Server\Test\WorkingDirectory</workingDirectory>
    <!--自动构建结果的查看地址-->
    <webURL>http://vw-caihaihua/CC/server/local/project/Lib.Sln/ViewProjectReport.aspx</webURL>
    <!--自动运行时间间隔-->
    <triggers>
      <!--源码修改触发-->
      <intervalTrigger seconds="10"  />
    </triggers>
    <maxSourceControlRetries>5</maxSourceControlRetries>
    <!--源代码管理(SVN)-->
    <sourcecontrol type="svn">
      <trunkUrl>https://vw-caihaihua/svn/Test/trunk/</trunkUrl>
      <executable>C:\Program Files (x86)\VisualSVN Server\bin\svn.exe</executable>
      <workingDirectory>C:\CC.NET\Server\Test\WorkingDirectory\</workingDirectory>
      <username>ci</username>
      <password>123456</password>
    </sourcecontrol>
  </project>
</cruisecontrol>

 

 执行 ccnet.exe 得到结果如下。配置的工作目录中已经是最新版本的代码:

 

我们可以 CC.NET 自带的 Dashboard 站点查看实时的信息,另外 Dashboard 站点还提供了 ForceBuild 功能:

 

2.触发器

CC.NET 提供多种触发器。本 Demo 中使用两种触发器

intervalTrigger 间隔触发,条件为如果源码有更新(IfModificationExists),同时配置 modificationDelaySeconds 节点;为了方便看到效果,这里 intervalTrigger seconds 设为 10,modificationDelaySeconds 设为 30。

scheduleTrigger 定时触发,条件为强制触发(ForceBuild),用于 DailyBuild。

ccnet.config 配置如下:

    <!--自动运行时间间隔-->
    <triggers>
      <!--源码修改触发-->
      <intervalTrigger seconds="10" buildCondition="IfModificationExists" />
      <!--每日构建-->
      <scheduleTrigger time="19:00" buildCondition="ForceBuild">
        <weekDays>
          <!--<weekDay>Sunday</weekDay>-->
          <weekDay>Monday</weekDay>
          <weekDay>Tuesday</weekDay>
          <weekDay>Wednesday</weekDay>
          <weekDay>Thursday</weekDay>
          <weekDay>Friday</weekDay>
          <!--<weekDay>Saturday</weekDay>-->
        </weekDays>
      </scheduleTrigger>
    </triggers>
    <!--对源码修改延迟处理时间间隔-->
    <modificationDelaySeconds>30</modificationDelaySeconds>
    <maxSourceControlRetries>5</maxSourceControlRetries>

 

客户端修改代码并提交到 SVN,结果如下:

 

3.编译

编译方式可以用 VS 工具,也可以用 .NET Framework 自带的 MsBuild。

ccnet.config 配置如下:

<tasks>
<!--<devenv> <solutionfile>C:\CC.NET\Server\Test\WorkingDirectory\Lib.sln</solutionfile> <configuration>Debug</configuration> </devenv>--> <!--清理解决方案--> <msbuild> <executable>C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe</executable> <buildArgs>/t:clean /t:rebuild /p:configuration=debug</buildArgs> <workingDirectory>C:\CC.NET\Server\Test\WorkingDirectory</workingDirectory> <projectFile>Lib.sln</projectFile> <logger>ThoughtWorks.CruiseControl.MsBuild.XmlLogger,C:\Program Files (x86)\CruiseControl.NET\server\ThoughtWorks.CruiseControl.MsBuild.dll</logger> </msbuild> </tasks>

 

 

Dashboard 站点中触发 ForceBuild,结果如下:

 

4.运行 UnitTest

测试脚本用的是 VS 自带的 UnitTest。

ccnet.config 配置如下:

    <tasks>
      <!--运行UnitTest-->
      <exec>
        <executable>C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\MSTest.exe</executable>
        <baseDirectory>C:\CC.NET\Server\Test\WorkingDirectory</baseDirectory>
        <buildArgs>/testcontainer:LibTest\bin\Debug\LibTest.dll</buildArgs>
        <buildTimeoutSeconds>6000</buildTimeoutSeconds>
      </exec>
    </tasks>

 

Dashboard 站点中触发 ForceBuild,结果如下:

客户端修改测试脚本,提交,结果如下:

        [TestMethod]
        public void Calculator_Add()
        {
            var c = new Lib.Calculator();

            var result = c.Add(1, 2, 3);

            Assert.AreEqual(result, 6);
            //Error Test
            Assert.AreEqual(7, 6);
        }

 

5.发布网站(Asp.NET 网站/WebServcie/WcfService)

首先在解决方案中添加 WcfService/WcfServiceTest 项目,提交到 SVN

公司的 Wcf 服务是寄宿在 IIS 上,我们需要用 MsBuild 编译成安装包。

ccnet.config 配置如下:

    <tasks>
<!--发布Wcf服务到本机--> <msbuild> <executable>C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe</executable> <workingDirectory>C:\CC.NET\Server\Test\WorkingDirectory\WcfService</workingDirectory> <projectFile>WcfService.csproj</projectFile> <buildArgs> /t:ResolveReferences;Compile /t:_CopyWebApplication /p:Configuration=Release /p:WebProjectOutputDir=C:\CC.NET\Server\Test\PublishDirectory\WcfService /p:OutputPath=C:\CC.NET\Server\Test\PublishDirectory\WcfService\bin </buildArgs> </msbuild> </tasks>

 

结果如下:

 

6.WcfService Test

由于项目的 Wcf 服务是寄宿在 IIS。VS 工具中用到的是 Asp.NET Development Server(WebDev.WebServer40.EXE),但我没想到怎么用。

此处用到的方法是在 IIS 中创建一个站点,用 MsBuild 发布 Wcf 服务到该站点(第 5 点)。然后把 WcfServiceTest 的服务引用指向该站点。

ccnet.config 配置如下:

      <!--运行UnitTest-->
      <exec>
        <executable>C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\MSTest.exe</executable>
        <baseDirectory>C:\CC.NET\Server\Test\WorkingDirectory</baseDirectory>
        <buildArgs>/testcontainer:WcfServiceTest\bin\Debug\WcfServiceTest.dll</buildArgs>
        <buildTimeoutSeconds>6000</buildTimeoutSeconds>
      </exec>

 

结果如下:

 

7.ftp 发布

当开发环境(或测试环境)在 CC.NET 服务器,可以用第 5 点的方法来完成自动发布。

但是往往 CI 跟环境是独立的。这时候我们可以用 ftp 来发布。

首先添加一个 ftp 站点,指向开发环境(或测试环境)的 Wcf 服务的目录,创建一个账户 admin 并分配权限到该 ftp 站点。

ccnet.config 配置如下:

    <tasks>
      <ftp>
        <serverName>127.0.0.1</serverName>
        <userName>admin</userName>
        <password>admin</password>
        <action>UploadFolder</action>
        <ftpFolderName></ftpFolderName>
        <localFolderName>C:\CC.NET\Server\Test\PublishDirectory\WcfService</localFolderName>
        <recursiveCopy>true</recursiveCopy>
        <timeDifference>1</timeDifference>
      </ftp>
    </tasks>

 

ForceBuild 结果如下:

 

8.打包

发布更新包配置如下:

   <tasks>
<package> <name>Lib.sln</name> <compression>9</compression> <manifest type="defaultManifestGenerator" /> <packageList> <packageFile sourceFile="C:\CC.NET\Server\Test\PublishDirectory\WcfService\*.svc" targetFolder="WcfService" /> <packageFile sourceFile="C:\CC.NET\Server\Test\PublishDirectory\WcfService\*.Release.config" targetFolder="WcfService" /> <packageFile sourceFile="C:\CC.NET\Server\Test\PublishDirectory\WcfService\bin\*.dll" targetFolder="WcfService\bin" /> <!--<packageFolder sourceFolder="C:\CC.NET\Server\Test\PublishDirectory\WcfService" targetFolder="WcfService" fileFilter="*.*" flatten="false" includeSubFolders="false" />--> </packageList> </package> </tasks>

 

ForceBuild 结果如下:

我们可以通过 CCTracy 工具下载下载更新包:

 

9.历史备份

配置 publishDir ,则每次 Build 成功后都会把该版本的源码备份到指定目录,配置如下:

    <publishers>
      <!--标签备份(如果成功)-->
      <buildpublisher>
        <sourceDir>C:\CC.NET\Server\Test\WorkingDirectory</sourceDir>
        <publishDir>C:\CC.NET\Server\Test\HistoryVersion</publishDir>
      </buildpublisher>
      <modificationHistory/>
      <statistics/>
      <xmllogger/>
    </publishers>

 

 

10.邮件通知

CC.NET 提供 email 方式反馈给开发团队,触发条件有 Always/Success/Change/Fixed/Failed/Exception

  (1)Modifier:一般情况下,SVN 的用户名跟公司邮箱名是对应的,用 converters 配置简单实现,更复杂的场景尚待研究

  (2)特定人员或角色:配置 users + groups。

按设想的场景中,CI leader 需要得到 Change 和 Exception 的反馈;Tester 需要得到 Fixed 的反馈;开发团队需要得到 Success/Fixed/Failed 的反馈;源码修改者需要得到 Failed/Fixed 的反馈。合理性尚待验证。

ccnet.config 配置如下:

 <publishers>
      <!--邮件通知-->
      <email mailhost="smtp.live.com" mailport="25"
           mailhostUsername="ci@XXXXCompany.com" mailhostPassword="*********"
           from="ci@XXXXCompany.com"
           useSSL="TRUE" includeDetails="true">
        <!--邮件标题配置-->
        <subjectPrefix>[CI@XXXCompany]</subjectPrefix>
        <subjectSettings>
          <!-- Success/Broken/StillBroken/Fixed/Exception-->
          <subject buildResult="Success" value="${CCNetProject} Build Successful: Label ${CCNetLabel}, last checkin(s) by ${CCNetModifyingUsers}.(at ${CCNetBuildDate} ${CCNetBuildDate})" />
          <subject buildResult="Fixed" value="${CCNetProject} Build Fixed: Label ${CCNetLabel}, last checkin(s) by ${CCNetModifyingUsers}.(at ${CCNetBuildDate} ${CCNetBuildDate})" />
          <subject buildResult="Broken" value="${CCNetProject} Broke: last checkin(s) by ${CCNetFailureUsers}.(at ${CCNetBuildDate} ${CCNetBuildDate})" />
          <subject buildResult="StillBroken" value="${CCNetProject} Still Broken: last checkin(s) by ${CCNetFailureUsers}.(at ${CCNetBuildDate} ${CCNetBuildDate})" />
          <subject buildResult="Exception" value="${CCNetProject} In Exception: Please check status of network / sourcecontrol.(at ${CCNetBuildDate} ${CCNetBuildDate})" />
        </subjectSettings>
        <!--通知相关的源码修改者-->
        <converters>
          <regexConverter find="$" replace="@XXXXCompany.com"/>
        </converters>
        <modifierNotificationTypes>
          <notificationType>Failed</notificationType>
          <notificationType>Fixed</notificationType>
        </modifierNotificationTypes>
        <!--通知特定人员(角色)-->
    <users> <user group="leader" name="ci.XXXCompany" address="ci@XXXCompany.com"/> <user group="developer" name="harvey.choi" address="harvey.choi@XXXXCompany.com"/> <user group="tester" name="jolin" address="jolin.tang@XXXCompany.com"/> </users> <groups> <group name="leader"> <notifications> <!--Always/Success/Change/Fixed/Failed/Exception --> <notificationType>Change</notificationType> <notificationType>Exception</notificationType> </notifications> </group> <group name="developer"> <notifications> <notificationType>Success</notificationType> <notificationType>Fixed</notificationType> <notificationType>Failed</notificationType> </notifications> </group> <group name="tester"> <notifications> <notificationType>Fixed</notificationType> </notifications> </group> </groups> </email> <xmllogger/> </publishers>

 

用 harvey.choi 账户修改源码并提交到 SVN。结果如下:

harvey.choi@XXXXCompany.com 收到以下邮件:

 

完整的 ccnet.config 配置如下,注意 tasks 是按顺序串行执行,任一步骤出错则整个 build 失败:

<cruisecontrol xmlns:cb="urn:ccnet.config.builder">
  <project name="Lib.Sln">
    <!--标签-->
    <labeller type="dateLabeller"/>
    <artifactDirectory>C:\CC.NET\Server\Test\ArtifactDirectory</artifactDirectory>
    <!--项目的目录-->
    <workingDirectory >C:\CC.NET\Server\Test\WorkingDirectory</workingDirectory>
    <!--自动构建结果的查看地址-->
    <webURL>http://vw-caihaihua/CC/server/local/project/Lib.Sln/ViewProjectReport.aspx</webURL>
    <!--自动运行时间间隔-->
    <triggers>
      <!--源码修改触发-->
      <intervalTrigger seconds="10" buildCondition="IfModificationExists " />
      <!--每日构建-->
      <scheduleTrigger time="19:00" buildCondition="ForceBuild">
        <weekDays>
          <!--<weekDay>Sunday</weekDay>-->
          <weekDay>Monday</weekDay>
          <weekDay>Tuesday</weekDay>
          <weekDay>Wednesday</weekDay>
          <weekDay>Thursday</weekDay>
          <weekDay>Friday</weekDay>
          <!--<weekDay>Saturday</weekDay>-->
        </weekDays>
      </scheduleTrigger>
    </triggers>
    <!--对源码修改延迟处理时间间隔-->
    <modificationDelaySeconds>30</modificationDelaySeconds>
    <maxSourceControlRetries>5</maxSourceControlRetries>
    <!--源代码管理(SVN)-->
    <sourcecontrol type="svn">
      <trunkUrl>https://vw-caihaihua/svn/Test/trunk/</trunkUrl>
      <executable>C:\Program Files (x86)\VisualSVN Server\bin\svn.exe</executable>
      <workingDirectory>C:\CC.NET\Server\Test\WorkingDirectory\</workingDirectory>
      <username>ci</username>
      <password>123456</password>
    </sourcecontrol>
    <tasks>
      <!--<devenv>
        <solutionfile>C:\CC.NET\Server\Test\WorkingDirectory\Lib.sln</solutionfile>
        <configuration>Debug</configuration>
      </devenv>-->
      <!--清理解决方案-->
      <msbuild>
        <executable>C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe</executable>
        <buildArgs>/t:clean /t:rebuild /p:configuration=debug</buildArgs>
        <workingDirectory>C:\CC.NET\Server\Test\WorkingDirectory</workingDirectory>
        <projectFile>Lib.sln</projectFile>
        <logger>ThoughtWorks.CruiseControl.MsBuild.XmlLogger,C:\Program Files (x86)\CruiseControl.NET\server\ThoughtWorks.CruiseControl.MsBuild.dll</logger>
      </msbuild>
      <!--运行UnitTest-->
      <exec>
        <executable>C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\MSTest.exe</executable>
        <baseDirectory>C:\CC.NET\Server\Test\WorkingDirectory</baseDirectory>
        <buildArgs>/testcontainer:LibTest\bin\Debug\LibTest.dll</buildArgs>
        <buildTimeoutSeconds>6000</buildTimeoutSeconds>
      </exec>
      <!--发布Wcf服务到本机-->
      <msbuild>
        <executable>C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe</executable>
        <workingDirectory>C:\CC.NET\Server\Test\WorkingDirectory\WcfService</workingDirectory>
        <projectFile>WcfService.csproj</projectFile>
        <buildArgs>
          /t:ResolveReferences;Compile
          /t:_CopyWebApplication
          /p:Configuration=Release
          /p:WebProjectOutputDir=C:\CC.NET\Server\Test\PublishDirectory\WcfService
          /p:OutputPath=C:\CC.NET\Server\Test\PublishDirectory\WcfService\bin
        </buildArgs>
      </msbuild>
      <!--运行UnitTest-->
      <exec>
        <executable>C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\MSTest.exe</executable>
        <baseDirectory>C:\CC.NET\Server\Test\WorkingDirectory</baseDirectory>
        <buildArgs>/testcontainer:WcfServiceTest\bin\Debug\WcfServiceTest.dll</buildArgs>
        <buildTimeoutSeconds>6000</buildTimeoutSeconds>
      </exec>
      <!--启动 Asp.NET Development Server-->
      <!--<exec>
        <executable>C:\Program Files (x86)\Common Files\microsoft shared\DevServer\10.0\WebDev.WebServer40.EXE</executable>
        <buildArgs>/port:9999 /path:C:\CC.NET\Server\Test\PublishDirectory\WcfService</buildArgs>
        <buildTimeoutSeconds>6000</buildTimeoutSeconds>
      </exec>-->
      <!--ftp发布Wcf服务到开发环境-->
      <ftp>
        <serverName>127.0.0.1</serverName>
        <userName>admin</userName>
        <password>admin</password>
        <action>UploadFolder</action>
        <ftpFolderName></ftpFolderName>
        <localFolderName>C:\CC.NET\Server\Test\PublishDirectory\WcfService</localFolderName>
        <recursiveCopy>true</recursiveCopy>
        <timeDifference>1</timeDifference>
      </ftp>
      <package>
        <name>Lib.sln</name>
        <compression>9</compression>
        <manifest type="defaultManifestGenerator" />
        <packageList>
          <packageFile sourceFile="C:\CC.NET\Server\Test\PublishDirectory\WcfService\*.svc" targetFolder="WcfService" />
          <packageFile sourceFile="C:\CC.NET\Server\Test\PublishDirectory\WcfService\*.Release.config" targetFolder="WcfService" />
          <packageFile sourceFile="C:\CC.NET\Server\Test\PublishDirectory\WcfService\bin\*.dll" targetFolder="WcfService\bin" />
          <!--<packageFolder sourceFolder="C:\CC.NET\Server\Test\PublishDirectory\WcfService" targetFolder="WcfService" 
                         fileFilter="*.*" flatten="false" includeSubFolders="false" />-->
        </packageList>
      </package>
    </tasks>
    <state type="state" directory="C:\CC.NET\server\CCState"/>
    <publishers>
      <!--标签备份(如果成功)-->
      <buildpublisher>
        <sourceDir>C:\CC.NET\Server\Test\WorkingDirectory</sourceDir>
        <publishDir>C:\CC.NET\Server\Test\HistoryVersion</publishDir>
      </buildpublisher>
      <modificationHistory/>
      <statistics/>
      <!--邮件通知-->
      <email mailhost="smtp.live.com" mailport="25"
           mailhostUsername="ci@XXXCompany.com" mailhostPassword="******"
           from="ci@XXXCompany.com"
           useSSL="TRUE" includeDetails="true">
        <!--邮件标题配置-->
        <subjectPrefix>[CI@XXXCompany]</subjectPrefix>
        <subjectSettings>
          <!-- Success/Broken/StillBroken/Fixed/Exception-->
          <subject buildResult="Success" value="${CCNetProject} Build Successful: Label ${CCNetLabel}, last checkin(s) by ${CCNetModifyingUsers}.(at ${CCNetBuildDate} ${CCNetBuildDate})" />
          <subject buildResult="Fixed" value="${CCNetProject} Build Fixed: Label ${CCNetLabel}, last checkin(s) by ${CCNetModifyingUsers}.(at ${CCNetBuildDate} ${CCNetBuildDate})" />
          <subject buildResult="Broken" value="${CCNetProject} Broke: last checkin(s) by ${CCNetFailureUsers}.(at ${CCNetBuildDate} ${CCNetBuildDate})" />
          <subject buildResult="StillBroken" value="${CCNetProject} Still Broken: last checkin(s) by ${CCNetFailureUsers}.(at ${CCNetBuildDate} ${CCNetBuildDate})" />
          <subject buildResult="Exception" value="${CCNetProject} In Exception: Please check status of network / sourcecontrol.(at ${CCNetBuildDate} ${CCNetBuildDate})" />
        </subjectSettings>
        <!--收件人配置-->
        <converters>
          <regexConverter find="$" replace="@XXXCompany.com"/>
        </converters>
        <modifierNotificationTypes>
          <notificationType>Failed</notificationType>
          <notificationType>Fixed</notificationType>
        </modifierNotificationTypes>
        <users>
          <user group="leader" name="ci.XXXCompany" address="ci@XXXCompany.com"/>
          <user group="developer" name="harvey.choi" address="harvey.choi@XXXCompany.com"/>
          <user group="tester" name="jolin" address="jolin.tang@XXXCompany.com"/>
        </users>
        <groups>
          <group name="leader">
            <notifications>
              <!--Always/Success/Change/Fixed/Failed -->
              <notificationType>Change</notificationType>
              <notificationType>Exception</notificationType>
            </notifications>
          </group>
          <group name="developer">
            <notifications>
              <notificationType>Success</notificationType>
              <notificationType>Fixed</notificationType>
              <notificationType>Failed</notificationType>
            </notifications>
          </group>
          <group name="tester">
            <notifications>
              <notificationType>Fixed</notificationType>
            </notifications>
          </group>
        </groups>
      </email>
      <xmllogger/>
    </publishers>
  </project>
</cruisecontrol>

 

六、结语

CI走得好累,概括来说:高层的态度是关键,如果领导不批啥都不用说;旧员工的态度往往是最大的阻力,一个有历史的团队总有一些人更愿意按旧的流程走,不愿意接受新的东西,不求有功但求无过

关于 CC.NET 中文的资料相对比较少,最好还是耐心的啃下官方的 E 文文档。

这个 CC.NET 的 Demo 断断续续搭了一周(日常任务不变,时间得自己挤),也差不多有定论。当然从 HelloWorld 到真正落地还需解决n多问题。

如果你发现 Demo 有哪些不正确的,欢迎跟帖指正。

 

posted @ 2013-07-22 19:11  海华  阅读(2558)  评论(21编辑  收藏  举报