【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 有哪些不正確的,歡迎跟帖指正。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM