版本控制及测试

作者在 2009-08-22 23:55:46 发布以下内容
CruiseControl简介

CruiseControl: 简称CC,持续集成工具,主要提供了基于版本管理工具(如CVS)感知变化或每天定时的持续集成,并提供持续集成报告、Email、Jabber等等方式 通知相关负责人,其要求是需要进行日构建的项目已编写好全自动的项目编译脚本(可基于Maven或Ant)。

在这里以一个项目来简要的说说cc的使用,通常项目对于日构建的类型的需求分为两种:
1、每天的定时自动集成。
2、感知版本管理工具中的变化而进行自动集成。

项目对于日构建的目标通常为:
1、感知版本管理工具的变化,如发现有变化,则进行集成。
2、调用项目编译脚本进行项目集成。
3、合并项目编译脚本产生的单元测试、功能测试的日志。
4、将集成报告发布至网站中。
5、将集成的结果以邮件、jabber等等方式通知相应的负责人。

基于上面的要求,项目编译脚本采用Maven,版本管理工具采用CVS,持续集成工具采用CC,假设已编写好了基于Maven的项目编译脚本,CruiseControl的脚本如下编写:
<?xml version="1.0" encoding="UTF-8"?>
<cruisecontrol>
  <project name="demo" buildafterfailed="true">
    <!-- 每次检测是否有变化时先运行此处 -->
    <bootstrappers>
      <currentbuildstatusbootstrapper file="logs/demo/buildstatus.txt"/>
 </bootstrappers>


    <!-- 检测是否有变化,如有变化则开始集成 -->
    <modificationset quietperiod="10">
           <!-- 基于cvs的检测 -->
           <cvs localworkingcopy="demo"/>
    </modificationset>


    <!-- 持续集成-->
    <schedule interval="18">
   <!-- 项目的编译脚本 -->
    <maven mavenscript="D:/tools/maven/bin/maven.bat"
    projectfile="demo/project.xml"
    goal="demo:build"/>
    </schedule>


    <!-- 持续集成过程的日志记录以及需要合并的日志 -->
    <log dir="logs/demo">
    <!-- 合并项目编译脚本中产生的单元、功能测试日志 -->
  <merge dir="demo/target/test-reports"/>
 </log>


    <!-- 持续集成后结果的公布 -->
    <publishers>
      <currentbuildstatuspublisher file="logs/demo/buildstatus.txt"/> 
     <!-- 发布持续集成的结果至网站中,此方法还不是最理想的 -->
      <execute command="D:/tools/cc/reporting/jsp/build.bat war"/>
      <!-- 邮件通知相关的负责人 -->
      <email mailhost="smtp.yourdomain.com"
        returnaddress="buildmaster@yourdomain.com"
        skipusers="true"
        reportsuccess="fixes"
        subjectprefix="[CruiseControl]"
        buildresultsurl="http://buildserver:8080/cruisecontrol/buildresults">
        <failure address="developers@yourdomain.com" />
        <success address="developers@yourdomain.com" />
      </email>
    </publishers>
  </project>
</cruisecontrol>

关于CC 的脚本中xml的规范、cc的安装和运行请参考CruiseControl的官方网站:
cruisecontrol.sourceforge.net


技术 | 阅读 2436 次
文章评论,共4条
vfdff(作者)
2009-08-22 23:57
1
Subversion 与 Mantis 整合作法<br />
<br />
当 Mantis 有张贴一个新的 Issue 时, 与这个 Issue 相关的 Subversion 更动纪录可以自动回写至 Mantis 这个 Issue 内的 Bug 笔记内.<br />
<br />
&nbsp;&nbsp;&nbsp; * Mantis 与 Subversion 都安装在相同的主机上 或 Subversion 主机可以透过 ssh 不需输入密码方式登入 Mantis 主机<br />
&nbsp;&nbsp;&nbsp; * Mantis 版本为 1.0.7 安装在 /var/www/html/mantis<br />
&nbsp;&nbsp;&nbsp; * Subversion 版本为 1.4.3-1<br />
<br />
&nbsp;&nbsp;&nbsp; * 建立 svnbot 这个特殊的 userid<br />
&nbsp;&nbsp;&nbsp; * 存取权限设定为开发者 (如果有多个项目, 每个项目都要授与 svnbot 这个权限)<br />
<br />
vi /var/www/html/mantis/config_inc.php<br />
<br />
:<br />
<br />
:<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#Source Control<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$g_source_control_account = 'svnbot';<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$g_source_control_regexp = '/\b(?:bug|issue|mantis)\s*[#]{0,1}(\d+)\b/i';<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$g_source_control_set_status_to = RESOLVED;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$g_source_control_set_resolution_to = FIXED;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$g_source_control_fixed_regexp = '/\bfix(?:ed|es)\s+(?:bug|issue|mantis)?\s*[#]{0,1}(\d+)\b/i';<br />
<br />
:<br />
<br />
&nbsp;&nbsp;&nbsp; * 设定 svnbot 为这个整合的 mantis 内特殊 user<br />
&nbsp;&nbsp;&nbsp; * 只要 SubVersion 内的纪录出现 bug 或 issue 或 mantis #编号 表示整合 Mantis 内的 Issue # Bug 笔记<br />
&nbsp;&nbsp;&nbsp; * 只要 SubVersion 内的纪录出现 fixed 或 fixes + bug 或 issue 或 mantis #编号 表示整合 Mantis 内的 Issue # Bug 笔记外, 更会将 issue 状态改成已修正解决<br />
<br />
直接执行以下的命令, 可以在 mantis 内的 Issue#2 新增 Bug 笔记<br />
<br />
php /var/www/html/mantis/core/checkin.php &lt;&lt;&lt; &quot;Test issue #2 by svnbot.&quot;<br />
<br />
直接执行以下的命令, 可以在 mantis 内的 Issue#2 新增 Bug 笔记以及将问题状态更改为以解决<br />
<br />
php /var/www/html/mantis/core/checkin.php &lt;&lt;&lt; &quot;Test fixed issue #2 by svnbot.&quot;<br />
<br />
vi /var/www/svn2mantis.pl<br />
<br />
#!/usr/bin/perl<br />
<br />
#<br />
<br />
# 上午 11:15 2007年6月22日<br />
<br />
# Jonathan Tsai<br />
<br />
# Ver 1.10<br />
<br />
#<br />
<br />
# 自动将 svn 讯息写入 mantis 纪录内<br />
<br />
#<br />
<br />
# 参考 http://www.ichiayi.com/trywiki/tech/svnmantis 的说明方式<br />
<br />
# 本 script 需配合:<br />
<br />
#&nbsp;&nbsp;1. /var/www/svn/xxxrepos/hooks/post-commit 一起使用<br />
<br />
#&nbsp;&nbsp;2.apache user 可使用 ssh 免密码登入 Mantis 主机 &lt;- SVN 主机与 Mantis 主机不同时需要<br />
<br />
#<br />
<br />
# 1.00 (2007/3/26) 第一版启用<br />
<br />
# 1.01 (2007/3/26) 增加 commit 后自动整合的说明<br />
<br />
# 1.10 (2007/6/22) 增加 远程登入 Mantis 主机功能设定<br />
<br />
#<br />
$prgname = substr($0, rindex($0,&quot;/&quot;)+1);<br />
<br />
$ver = &quot;1.10 (2007/6/22)&quot;;<br />
<br />
# $sshcmd 设为空字符串表示 SVN 与 Mantis 安装在相同主机<br />
<br />
$sshcmd = &quot;&quot;;<br />
<br />
# 否则应该输入由 svn 主机免密码登入 Mantis 主机的命令列<br />
<br />
#$sshcmd = &quot;/usr/bin/ssh jonathan@10.10.10.96&quot;;<br />
<br />
 <br />
<br />
# 读取参数数据<br />
<br />
$REPOS=$ARGV[0];<br />
<br />
$REV=$ARGV[1];<br />
<br />
 <br />
<br />
# 定义外部指令<br />
<br />
$svnlook = &quot;export LANG=zh_TW.UTF-8;/usr/bin/svnlook&quot;;<br />
<br />
$phpcmd = &quot;/usr/bin/php&quot;;<br />
<br />
$checkincmd = &quot;/var/www/html/mantis/core/checkin.php&quot;;<br />
<br />
 <br />
<br />
# 取得 svn 相关信息<br />
<br />
$auth=`$svnlook author -r $REV $REPOS`;<br />
<br />
$dt=`$svnlook date -r $REV $REPOS`;<br />
<br />
$changed=`$svnlook changed -r $REV $REPOS`;<br />
<br />
$log=`$svnlook log -r $REV $REPOS`;<br />
<br />
$msg=&quot;Changeset [&quot;.$REV.&quot;] by $auth\n$dt\n$log\n$changed&quot;;<br />
<br />
 <br />
<br />
# 传送至 mantis<br />
<br />
if (length($sshcmd)&gt;0) {<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`$sshcmd $phpcmd -q $checkincmd &lt;&lt;&lt; &quot;$msg&quot;`;<br />
<br />
}<br />
<br />
else {<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`$phpcmd -q $checkincmd &lt;&lt;&lt; &quot;$msg&quot;`;<br />
<br />
}<br />
<br />
&nbsp;&nbsp;&nbsp; * 假设 servercfg 的 svn 存放在 /var/www/svn/servercfg<br />
&nbsp;&nbsp;&nbsp; * 假设 servercfg 的 Reversion 644 讯息内容有出现 mantis #2 ← 表示整合至 Mantis Issue #2<br />
<br />
<br />
chmod a+x /var/www/svn2mantis.pl<br />
<br />
/var/www/svn2mantis.pl /var/www/svn/servercfg 644<br />
<br />
&nbsp;&nbsp;&nbsp; * 这样就可以看到 Mantis Issue #2 内新增一个 Bug 笔记, 内容如下:<br />
<br />
Changeset [644] by jonathan<br />
<br />
 <br />
<br />
2007-03-26 11:29:55 +0800 (一, 26 3月 2007)<br />
<br />
 <br />
<br />
将 svnlook 命令前加入 LANG=zh_TW.UTF-8 来测试整合 mantis 中文讯息问题.<br />
<br />
 <br />
<br />
mantis#2<br />
<br />
 <br />
<br />
U PD-920/var/www/svn2mantis.pl<br />
<br />
如果有多个 svn repos 就在每个 repos 内依照这步骤一一执行, 以下还是以 servercfg 的 svn repos 为例<br />
<br />
cd /var/www/svn/servercfg<br />
<br />
cd hooks<br />
<br />
vi post-commit<br />
<br />
#!/bin/sh<br />
<br />
 <br />
<br />
REPOS=&quot;$1&quot;<br />
<br />
REV=&quot;$2&quot;<br />
/var/www/svn2mantis.pl &quot;$REPOS&quot; &quot;$REV&quot;<br />
<br />
chown apache:apache post-commit<br />
<br />
chmod a+x post-commit<br />
<br />
这样一但 commit 后, 会马上执行这个 post-commit 的 shell script, 来执行 svn2mantis.pl 将 SVN 内的纪录内容整合到 Mantis 的 Issue Bug 笔记内.<br />
<br />
&nbsp;&nbsp;&nbsp; * SVN Server : 10.10.10.91<br />
&nbsp;&nbsp;&nbsp; * Mantis Server : 10.10.10.96<br />
&nbsp;&nbsp;&nbsp; * 假设 svn server 是与 httpd 整合, 透过 apache 执行<br />
&nbsp;&nbsp;&nbsp; * 先设定 SVN 主机内的 jonathan 账号可以不用密码以相同账号登入 Mantis 主机<br />
&nbsp;&nbsp;&nbsp; * 再设定 SVN 主机内的 apache 账号可以不用密码以 jonathan 账号登入 Mantis 主机<br />
<br />
&nbsp;&nbsp;&nbsp; * 在 /home/jonathan/.ssh 内产生凭证与公钥<br />
&nbsp;&nbsp;&nbsp; * 将公钥复制到 Mantis 主机内改命名为 10.10.10.91_authorized_keys2<br />
<br />
<br />
su - jonathan<br />
<br />
ssh 10.10.10.96 &lt;- 输入密码确认可以登入<br />
<br />
exit &lt;- 回到 svn 主机<br />
<br />
cd .ssh<br />
<br />
ssh-keygen -d &lt;- 产生 id_dsa.pub (询问时均 Enter 跳下不输入任何字符)<br />
<br />
scp id_dsa.pub 10.10.10.96:/home/jonathan/.ssh/10.10.10.91_authorized_keys2<br />
<br />
&nbsp;&nbsp;&nbsp; * 将 SVN 主机公钥加入认证公钥清单文件内<br />
&nbsp;&nbsp;&nbsp; * 将认证公钥清单文件权限设为只有自己可以读写<br />
<br />
<br />
su - jonathan<br />
<br />
cd .ssh<br />
<br />
cat 10.10.10.91_authorized_keys2 &gt;&gt; authorized_keys2<br />
<br />
chmod 600 authorized_keys2<br />
<br />
&nbsp;&nbsp;&nbsp; * 先使用 jonathan 账号登入 SVN 主机<br />
&nbsp;&nbsp;&nbsp; * 执行 ssh 10.10.10.96 就可以发现不需要密码就可登入 Mantis 主机<br />
<br />
[jonathan@eddev ~]$ ssh jonathan@10.10.10.96<br />
<br />
Last login: Fri Jun 22 10:14:40, 2007 from 10.10.10.91<br />
<br />
[jonathan@tryboxap04 ~]$<br />
&nbsp;&nbsp;&nbsp; * 登入 SVN 主机, 切换成 root<br />
&nbsp;&nbsp;&nbsp; * 将上面设定的 /home/jonathan/.ssh 目录复制到 /var/www 内就可以<br />
<br />
<br />
su -<br />
<br />
cd /var/www<br />
<br />
cp -a ~jonathan/.ssh .<br />
<br />
chown -R apache:apache .ssh<br />
<br />
vi /var/www/svn2mantis.pl<br />
<br />
#!/usr/bin/perl<br />
<br />
#<br />
<br />
# 上午 11:15 2007年6月22日<br />
<br />
# Jonathan Tsai<br />
<br />
# Ver 1.10<br />
<br />
#<br />
<br />
# 自动将 svn 讯息写入 mantis 纪录内<br />
<br />
#<br />
<br />
# 参考 http://www.ichiayi.com/trywiki/tech/svnmantis 的说明方式<br />
<br />
# 本 script 需配合:<br />
<br />
#&nbsp;&nbsp;1. /var/www/svn/xxxrepos/hooks/post-commit 一起使用<br />
<br />
#&nbsp;&nbsp;2.apache user 可使用 ssh 免密码登入 Mantis 主机 &lt;- SVN 主机与 Mantis 主机不同时需要<br />
<br />
#<br />
<br />
# 1.00 (2007/3/26) 第一版启用<br />
<br />
# 1.01 (2007/3/26) 增加 commit 后自动整合的说明<br />
<br />
# 1.10 (2007/6/22) 增加 远程登入 Mantis 主机功能设定<br />
<br />
#<br />
<br />
 <br />
<br />
$prgname = substr($0, rindex($0,&quot;/&quot;)+1);<br />
<br />
$ver = &quot;1.10 (2007/6/22)&quot;;<br />
<br />
# $sshcmd 设为空字符串表示 SVN 与 Mantis 安装在相同主机<br />
<br />
#$sshcmd = &quot;&quot;;<br />
<br />
# 否则应该输入由 svn 主机免密码登入 Mantis 主机的命令列<br />
<br />
$sshcmd = &quot;/usr/bin/ssh jonathan@10.10.10.96&quot;;<br />
<br />
 <br />
<br />
# 读取参数数据<br />
<br />
$REPOS=$ARGV[0];<br />
<br />
$REV=$ARGV[1];<br />
<br />
 <br />
<br />
# 定义外部指令<br />
<br />
$svnlook = &quot;export LANG=zh_TW.UTF-8;/usr/bin/svnlook&quot;;<br />
<br />
$phpcmd = &quot;/usr/bin/php&quot;;<br />
<br />
$checkincmd = &quot;/var/www/html/mantis/core/checkin.php&quot;;<br />
<br />
 <br />
<br />
# 取得 svn 相关信息<br />
<br />
$auth=`$svnlook author -r $REV $REPOS`;<br />
<br />
$dt=`$svnlook date -r $REV $REPOS`;<br />
<br />
$changed=`$svnlook changed -r $REV $REPOS`;<br />
<br />
$log=`$svnlook log -r $REV $REPOS`;<br />
<br />
$msg=&quot;Changeset [&quot;.$REV.&quot;] by $auth\n$dt\n$log\n$changed&quot;;<br />
<br />
 <br />
<br />
# 传送至 mantis<br />
<br />
if (length($sshcmd)&gt;0) {<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`$sshcmd $phpcmd -q $checkincmd &lt;&lt;&lt; &quot;$msg&quot;`;<br />
<br />
}<br />
<br />
else {<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`$phpcmd -q $checkincmd &lt;&lt;&lt; &quot;$msg&quot;`;<br />
<br />
}<br />
<br />
&nbsp;&nbsp;&nbsp; * 假设 moeaprj 的 svn 存放在 /var/www/svn/moeaprj<br />
&nbsp;&nbsp;&nbsp; * 假设 moeaprj 的 Reversion 1700 讯息内容有出现 mantis #516 ← 表示整合至 Mantis Issue #516<br />
<br />
<br />
chmod a+x /var/www/svn2mantis.pl<br />
<br />
/var/www/svn2mantis.pl /var/www/svn/moeaprj 1700<br />
<br />
&nbsp;&nbsp;&nbsp; * 这样就可以看到 Mantis Issue #516 内新增一个 Bug 笔记, 内容如下:<br />
<br />
Changeset [1700] by chou<br />
<br />
 <br />
<br />
2007-06-20 12:09:04 +0800 (三, 20 6月 2007)<br />
更改发文查询的本文含附件打印 mantis#516<br />
<br />
 <br />
<br />
U EDOC2/Source/docsrv_html/inc/templates/edrecvquery_2.inc.htm<br />
<br />
如果有多个 svn repos 就在每个 repos 内依照这步骤一一执行, 以下还是以 moeaprj 的 svn repos 为例<br />
<br />
cd /var/www/svn/moeaprj<br />
<br />
cd hooks<br />
<br />
vi post-commit<br />
<br />
#!/bin/sh<br />
<br />
 <br />
<br />
REPOS=&quot;$1&quot;<br />
<br />
REV=&quot;$2&quot;<br />
<br />
 <br />
<br />
/var/www/svn2mantis.pl &quot;$REPOS&quot; &quot;$REV&quot;<br />
<br />
chown apache:apache post-commit<br />
<br />
chmod a+x post-commit<br />
<br />
这样一但 commit 后, 会马上执行这个 post-commit 的 shell script, 来执行 svn2mantis.pl 将 SVN 内的纪录内容整合到 Mantis 的 Issue Bug 笔记内.
vfdff(作者)
2009-08-23 00:05
2
最近在研究Maven,发现国内这方面的文章很少。自己捉摸了几天,看了几篇文章,觉得其实没有什么可比较的,因为从功能上说Maven是大于Ant的。但事实上持续集成要选择Maven还是Ant,还要看具体的需要啦,假如你现在已经有CruiseControl +Ant了就没有必要非专成CruiseControl +Maven了,假如你现在正预备做持续集成,那你就不妨试一下Maven了。<br />
  其实很多时候拿两个东西作比较是多余的,因为很多时候使用一个东西往往更自己的个人喜好有关系。比如有人喜欢用JBuilder有人喜欢用Eclipse,它们谁好谁坏呢?我不知道。对于Maven来说,我们现在已经有 CruiseControl +Ant,但我还是想转成CruiseControl +Maven,因为我喜欢Maven(我的地盘我做主)。说了一 堆有的没有的,我都不知所云,现在回到主题说说我对它们的比较:<br />
  1:功能:Ant是用于构建Java项目的;而Maven不但包含构建,还有治理java项目<br />
  2:构建:Ant是将构建所需的jars放入Classpath;Maven则维护一个本地Repository负责存放jars,这样不同 的项目可以共享一个jars Repository
vfdff(作者)
2009-08-23 00:09
3
cruisecontrol、ant、svn持续集成<br />
<br />
文章摘要:自己两个多星期以来对持续集成的概念和应用有了一些了解。下面主要对自己配置持续集成的环境进行总结。(看上去简单,但是对我开始对持续集成都没什么了解的人来说确实费了不少周折) 一 本次持续集成环境的搭建所使用的工具有 cruisecontrol、ant、svn、junit、Slik-Subversion-1.5.6-win32、svnant-1.1.0- RC2.zip cruise<br />
-<br />
<br />
自己两个多星期以来对持续集成的概念和应用有了一些了解。下面主要对自己配置持续集成的环境进行总结。(看上去简单,但是对我开始对持续集成都没什么了解的人来说确实费了不少周折)<br />
<br />
一&nbsp;&nbsp;本次持续集成环境的搭建所使用的工具有<br />
<br />
 cruisecontrol、ant、svn、junit、Slik-Subversion-1.5.6-win32、svnant-1.1.0-RC2.zip<br />
<br />
 cruisecontrol:是一种持续集成过程的框架,包括了邮件通知,ant 和各种源码控&nbsp;&nbsp;制工具的插 件。并提供了web接口,用于查看当前和以前的创建的结果.<br />
<br />
ant:构建工具。<br />
<br />
svn:版本控制工具。<br />
<br />
junit:单元测试工具。<br />
<br />
slik-subversion:是为了调用svn的客户端命令安装的。<br />
<br />
svnant:主要是用到它里面的lib中的jar包,它具体使用还不是很清楚<br />
<br />
另外本次的辅助环境还有jdk,相信大家都再也熟悉不过了。<br />
<br />
二 环境的搭建步骤:<br />
<br />
&nbsp;&nbsp;&nbsp;1. jdk的安装:根据jdk安装包的提示安装jdk。设置系统的环境变量:<br />
<br />
a) JAVA_HOME指明JDK安装路径,就是刚才安装时所选择的路径D:\java\jdk1.5.0_08,此路径下包括lib,bin,jre等文件夹(此变量最好设置,因为以后运行tomcat都需要依赖此变量);<br />
<br />
b) Path使得系统可以在任何路径下识别java命令,设为%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin;<br />
<br />
 c)CLASSPATH为java加载类(class or lib)路径,只有类在&nbsp;&nbsp;classpath中,java命令才能识别,设为:.;JAVA_HOME\lib\dt.jar;JAVA_HOME%&nbsp;&nbsp;&nbsp;\lib\tools.jar (要加.表示当前路径);%JAVA_HOME%就是引用前面指定的JAVA_HOME;不过本人还是比较相信绝对路径的。 <br />
<br />
2 ant的安装:ant是集成构建工具,想必大家都不太陌生了。只需要到ant.apache.org的网站下载ant的适当版本解压缩后,配置系统的环境变量:ANT_HOME:d:\apache-ant-1.7.0, path:d:\apache-ant-1.7.0\bin 后,ant就可以在任意目录下运行了,如cmd下运行ant,显示:buildfile:build.xml does not exsit。。。。。<br />
<br />
3 安装svn,因为cruisecontrol要用到svn(不知道这两个有什么先后顺序没,因为cc要用svn就先装cc喽)。svn的安装TortoiseSVN-1.5.3.13783-win32-svn-1.5.2.msi安装提示装就可以了。<br />
<br />
4 安装tomcat ,设置系统环境变量CATALINA_HOME=c:\tomcat,CLASSPATH=C:\tomcat\common\lib(加载必要的包)。<br />
<br />
5 cuisecontrol的安装,因为本文使用的操作系统为XP,就使用CruiseControl-2.8.2.exe安装就可以了(.exe文件还是很受大家喜欢的)。配置系统的环境变量:CC_HOME=d:\cruisecontrol<br />
<br />
6 安装slik-subversion,它会自动写入到path=D:\SlikSvn\bin\ 如果没有写入的话,要麻烦手动加入到系统的环境变量path中,本人曾经遇到过,cmd窗口已经打开但是配置文件执行过程中svn的命令总不能识别发现此处的路径没有加入到path中。<br />
<br />
7下载svnant-1.1.0-RC2.zip,把lib包中的jar考到ant的jar中。<br />
<br />
三 以上的准备工作已经基本搞定,下面就介绍一下配置文件。此次环境的搭建配置文件是很关键的,因为他们各自有自己的标签,所以还要想达到什么功能慢慢查找,(如果有时间系统学习一下就好了)。<br />
<br />
1 ant的关键文件为build.xml(当然也可以起别的名称,自己还要改它的启动文件,就用这个名称吧)下面是一个实例:<br />
<br />
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;<br />
<br />
定义basedir当前的根目录,default默认执行的标签,name工程名<br />
&lt;project basedir=&quot;.&quot; default=&quot;all&quot; name=&quot;framework&quot;&gt;<br />
 &lt;property environment=&quot;env&quot; /&gt;<br />
<br />
定义tomcat的安装目录<br />
 &lt;property name=&quot;TOMCAT_DIR&quot; location=&quot;D:/Tomcat 5.5&quot; /&gt;<br />
<br />
定义debug的级别<br />
 &lt;property name=&quot;debuglevel&quot; alue=&quot;source,lines,vars&quot; /&gt;<br />
<br />
为了引用tomcat固有包方便所以增加次属性<br />
 &lt;property name=&quot;coolink.dist.path&quot; location=&quot;D:/Tomcat 5.5/webapps/txsd/WEB-INF&quot; /&gt;<br />
<br />
指定要编译的工程目录<br />
 &lt;property name=&quot;CLASS_DIR&quot; location=&quot;D:/CruiseControl/projects/framework&quot; /&gt;<br />
 &lt;property name=&quot;target&quot; value=&quot;1.5&quot; /&gt;<br />
 &lt;property name=&quot;source&quot; value=&quot;1.5&quot; /&gt;<br />
<br />
编译时候所使用的类路径,id为引用的名称<br />
 &lt;path id=&quot;Apache Tomcat v5.5 [Apache Tomcat v5.5].libraryclasspath&quot;&gt;<br />
&nbsp;&nbsp;&lt;pathelement location=&quot;${TOMCAT_DIR}/common/lib/commons-el.jar&quot; /&gt;<br />
&nbsp;&nbsp;....<br />
&nbsp;&nbsp;&lt;pathelement location=&quot;${TOMCAT_DIR}/common/lib/servlet-api.jar&quot; /&gt;<br />
 &lt;/path&gt;<br />
 &lt;path id=&quot;Web App Libraries.libraryclasspath&quot;&gt;<br />
&nbsp;&nbsp;&lt;pathelement location=&quot;${coolink.dist.path}/lib/activation.jar&quot; /&gt;<br />
&nbsp;&nbsp;.............<br />
&nbsp;&nbsp;&lt;pathelement location=&quot;${coolink.dist.path}/lib/xmlParserAPIs.jar&quot; /&gt;<br />
 &lt;/path&gt;<br />
&nbsp;&nbsp;&lt;path id=&quot;ant.svn.classpath&quot;&gt;<br />
&nbsp;&nbsp;&lt;fileset dir=&quot;D:/CruiseControl/apache-ant-1.7.0/lib&quot;&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;include name=&quot;*.jar&quot; /&gt;<br />
&nbsp;&nbsp;&lt;/fileset&gt;<br />
 &lt;/path&gt;<br />
 &lt;taskdef name=&quot;svn&quot; classname=&quot;org.tigris.subversion.svnant.SvnTask&quot;&gt;<br />
&nbsp;&nbsp;&lt;classpath refid=&quot;ant.svn.classpath&quot; /&gt;<br />
 &lt;/taskdef&gt;<br />
 &lt;path id=&quot;txsd.classpath&quot;&gt;<br />
&nbsp;&nbsp;&lt;path refid=&quot;Apache Tomcat v5.5 [Apache Tomcat v5.5].libraryclasspath&quot; /&gt;<br />
&nbsp;&nbsp;&lt;path refid=&quot;Web App Libraries.libraryclasspath&quot; /&gt;<br />
 &lt;/path&gt;<br />
<br />
clean操作,如果build之前不执行此操作,build检查到原有的class文件就不再编译。<br />
 &lt;target name=&quot;clean&quot;&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;delete file=&quot;${CLASS_DIR}/longcon-framework.jar&quot; /&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;delete dir=&quot;target&quot; quiet=&quot;true&quot; /&gt;<br />
&nbsp;&nbsp;&lt;delete dir=&quot;${CLASS_DIR}/source/classes&quot; /&gt;<br />
 &lt;/target&gt;<br />
<br />
要build模块的名称build-framework看来可以随便起名字,但是有人说必须和模块名称一致,至今还不知道为什么<br />
 &lt;target name=&quot;build-framework&quot;&gt;<br />
&nbsp;&nbsp;&lt;echo message=&quot;${ant.project.name}: ${ant.file}&quot; /&gt;<br />
&nbsp;&nbsp;&lt;mkdir dir=&quot;${CLASS_DIR}/source/classes&quot; /&gt;<br />
&nbsp;&nbsp;&lt;copy includeemptydirs=&quot;false&quot; todir=&quot;source/classes&quot;&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;fileset dir=&quot;${CLASS_DIR}/source&quot; excludes=&quot;**/*.launch, **/*.java&quot; /&gt;<br />
&nbsp;&nbsp;&lt;/copy&gt;<br />
&nbsp;&nbsp;&lt;javac debug=&quot;true&quot; debuglevel=&quot;${debuglevel}&quot; destdir=&quot;${CLASS_DIR}/source/classes&quot; source=&quot;${source}&quot; target=&quot;${target}&quot; encoding=&quot;UTF-8&quot;&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;src path=&quot;${CLASS_DIR}/source&quot; /&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;exclude name=&quot;**/.svn/**&quot; /&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;classpath refid=&quot;txsd.classpath&quot; /&gt;<br />
&nbsp;&nbsp;&lt;/javac&gt;<br />
 &lt;/target&gt;<br />
<br />
单元测试的部分<br />
 &lt;target name=&quot;test&quot;&gt;<br />
&nbsp;&nbsp;&lt;mkdir dir=&quot;target/test-classes&quot; /&gt;<br />
&nbsp;&nbsp;&lt;javac encoding=&quot;UTF-8&quot; srcdir=&quot;${CLASS_DIR}/test&quot; destdir=&quot;target/test-classes&quot;&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;classpath&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;pathelement location=&quot;${CLASS_DIR}/source/classes&quot; /&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;path refid=&quot;Apache Tomcat v5.5 [Apache Tomcat v5.5].libraryclasspath&quot; /&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;path refid=&quot;Web App Libraries.libraryclasspath&quot; /&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;/classpath&gt;<br />
&nbsp;&nbsp;&lt;/javac&gt;<br />
<br />
&nbsp;&nbsp;&lt;mkdir dir=&quot;target/test-results&quot; /&gt;<br />
&nbsp;&nbsp;&lt;junit haltonfailure=&quot;no&quot; printsummary=&quot;on&quot;&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;classpath&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;pathelement location=&quot;${CLASS_DIR}/source/classes&quot; /&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;pathelement location=&quot;${coolink.dist.path}/lib/junit.jar&quot; /&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;pathelement location=&quot;target/test-classes&quot; /&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;/classpath&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;formatter type=&quot;brief&quot; usefile=&quot;false&quot; /&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;formatter type=&quot;xml&quot; /&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;batchtest todir=&quot;target/test-results&quot;&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;fileset dir=&quot;target/test-classes&quot; includes=&quot;**/*.class&quot; /&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;/batchtest&gt;<br />
&nbsp;&nbsp;&lt;/junit&gt;<br />
 &lt;/target&gt;<br />
<br />
打包放到指定目录<br />
 &lt;target name=&quot;jar&quot;&gt;<br />
&nbsp;&nbsp;&lt;jar destfile=&quot;${CLASS_DIR}/longcon-framework.jar&quot; encoding=&quot;UTF-8&quot; update=&quot;false&quot; excludes=&quot;**/*Test*.class&quot;&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;fileset dir=&quot;${CLASS_DIR}/source/classes&quot; /&gt;<br />
&nbsp;&nbsp;&lt;/jar&gt;<br />
&nbsp;&nbsp;&lt;copy includeemptydirs=&quot;false&quot; todir=&quot;${coolink.dist.path}/lib&quot;&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;fileset file=&quot;${CLASS_DIR}/longcon-framework.jar&quot; excludes=&quot;**/*.launch, **/*.java&quot; /&gt;<br />
&nbsp;&nbsp;&lt;/copy&gt;<br />
 &lt;/target&gt;<br />
<br />
调用svn命令,这与三中的步骤7有密切的联系<br />
&lt;target name=&quot;commit&quot;&gt;<br />
 &lt;svn username=&quot;aaa&quot; password=&quot;aaa&quot;&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;commit file=&quot;${coolink.dist.path}/lib/longcon-framework.jar&quot; message=&quot;${msg.commit}&quot;&nbsp;&nbsp;/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/svn&gt;<br />
 &lt;/target&gt;<br />
 &lt;target name=&quot;all&quot;&nbsp;&nbsp;depends=&quot;clean,build-framework,jar,commit&quot;/&gt;<br />
<br />
&lt;/project&gt;<br />
注释:<br />
<br />
a设置编译所需要的类路径可以用:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;classpath&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;pathelement path=&quot;${classpath}&quot;/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;fileset dir=&quot;lib&quot;&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;include name=&quot;**/*.jar&quot;/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/fileset&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;pathelement location=&quot;classes&quot;/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;dirset dir=&quot;build&quot;&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;include name=&quot;apps/**/classes&quot;/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;exclude name=&quot;apps/**/*Test*&quot;/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/dirset&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;filelist refid=&quot;third-party_jars&quot;/&gt;<br />
<br />
&nbsp;&nbsp;&nbsp;&lt;/classpath&gt;<br />
<br />
b &lt;target name=&quot;test&quot; depends=&quot;clean&quot;&gt;depends表示依赖关系<br />
 2 cruisecontrol的config文件,CC启动的时候会自动寻找此文件,当然你可以通过修改启动文件修改config.xml名称,只要两处一致就能找到,下面是一个config文件的实例:<br />
<br />
&lt;cruisecontrol&gt;//cc的固有标签,cc中可以有多个project<br />
<br />
 &lt;project name=&quot;framework&quot;&gt;// 工程名称<br />
<br />
&lt;plugin name=&quot;labelincrementer&quot; classname=&quot;net.sourceforge.cruisecontrol.labelincrementers.SVNLabelIncrementer&quot;/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;labelincrementer workingcopypath=&quot;projects/${project.name}&quot;/&gt; // 显示svn的版本号<br />
<br />
listeners:监听器,来报告cc的此项目的运行信息<br />
&nbsp;&nbsp;&lt;listeners&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;currentbuildstatuslistener file=&quot;logs/${project.name}/status.txt&quot; /&gt;<br />
&nbsp;&nbsp;&lt;/listeners&gt;<br />
<br />
bootstrappers从svn源码控制程序更新本地版本,据说还有向其它插件提供当前创建的状态<br />
<br />
&nbsp;&nbsp;&lt;bootstrappers&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;svnbootstrapper localWorkingCopy=&quot;projects/${project.name}&quot; username=&quot;luojing&quot; password=&quot;luojing&quot; /&gt;<br />
&nbsp;&nbsp;&lt;/bootstrappers&gt;<br />
&nbsp;&nbsp;&lt;bootstrappers&gt;//向ant提供当前信息<br />
&nbsp;&nbsp;&nbsp;&lt;antbootstrapper anthome=&quot;apache-ant-1.7.0&quot; buildfile=&quot;projects/${project.name}/build.xml&quot; target=&quot;jar&quot; /&gt;<br />
&nbsp;&nbsp;&lt;/bootstrappers&gt;<br />
&nbsp;&nbsp;&lt;modificationset quietperiod=&quot;30&quot;&gt;// 通过svn更新原代码<br />
&nbsp;&nbsp;&nbsp;&lt;!-- touch any file in connectfour project to trigger a build --&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;svn localWorkingCopy=&quot;projects/${project.name}&quot; username=&quot;luojing&quot; password=&quot;luojing&quot; /&gt;<br />
&nbsp;&nbsp;&lt;/modificationset&gt;<br />
<br />
&lt;schedule interval=&quot;28800&quot;&gt;设定检查编译build版本的时间单位s<br />
&nbsp;&nbsp;&nbsp;&lt;ant anthome=&quot;apache-ant-1.7.0&quot; buildfile=&quot;projects/${project.name}/build.xml&quot; /&gt;<br />
&nbsp;&nbsp;&lt;/schedule&gt;<br />
&nbsp;&nbsp;&lt;log&gt;//显示单元测试信息<br />
&nbsp;&nbsp;&nbsp;&lt;merge dir=&quot;projects/${project.name}/framework/target/test-results&quot; /&gt;<br />
&nbsp;&nbsp;&lt;/log&gt;<br />
&nbsp;&nbsp;&lt;publishers&gt;//发布版本<br />
&nbsp;&nbsp;&nbsp;&lt;onsuccess&gt;//成功,并生成有时间戳的目录<br />
&nbsp;&nbsp;&nbsp; &lt;artifactspublisher dest=&quot;D:/CruiseControl/artifacts/${project.name}&quot; file=&quot;projects/${project.name}/longcon-framework.jar&quot; /&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;/onsuccess&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;onfailure&gt;//失败发送邮件到响应的人员<br />
&nbsp;&nbsp;&nbsp; &lt;htmlemail buildresultsurl=&quot;http://localhost:8080/cruisecontrol/buildresults/${project.name}&quot; mailhost=&quot;邮件服务器&quot; password=&quot;密码&quot; username=&quot;用户名&quot; defaultsuffix=&quot;@**.com.cn&quot; returnname=&quot;PetClinic Continuous Integration&quot; returnaddress=&quot;sunny@**.com.cn&quot; charset=&quot;UTF-8&quot; skipusers=&quot;true&quot; xsldir=&quot;webapps/cruisecontrol/xsl&quot; css=&quot;webapps/cruisecontrol/css/cruisecontrol.css&quot;&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;always address=&quot;接收邮件方的邮箱&quot; /&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/htmlemail&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;/onfailure&gt;<br />
&nbsp;&nbsp;&lt;/publishers&gt;<br />
 &lt;/project&gt;<br />
 &lt;project name=&quot;site&quot;&gt;<br />
&nbsp;&nbsp;&lt;listeners&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;currentbuildstatuslistener file=&quot;logs/${project.name}/status.txt&quot; /&gt;<br />
&nbsp;&nbsp;&lt;/listeners&gt;<br />
<br />
&nbsp;&nbsp;&lt;bootstrappers&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;svnbootstrapper localWorkingCopy=&quot;projects/${project.name}&quot; username=&quot;sunny&quot; password=&quot;sunny&quot; /&gt;<br />
&nbsp;&nbsp;&lt;/bootstrappers&gt;<br />
&nbsp;&nbsp;&lt;bootstrappers&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;antbootstrapper anthome=&quot;apache-ant-1.7.0&quot; buildfile=&quot;projects/${project.name}/build.xml&quot; target=&quot;jar&quot; /&gt;<br />
&nbsp;&nbsp;&lt;/bootstrappers&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;modificationset&gt;//设置只有framework工程成功了才执行此次的操作,体现了project的依赖关系<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;buildstatus logdir=&quot;logs/framework&quot;/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/modificationset&gt;<br />
 &lt;/project&gt;<br />
&lt;/cruisecontrol&gt;<br />
<br />
四 启动CC可以实现集成编译、集成构建、单元测试的功能,对于持续构建这是最简单不过了,要继续努力学习哦。<br />
<br />
五 持续集成使用了一段时间发现了源代码目录总是不能自动更新,认真查找发现是因为自己对标签&lt;svnbootstrapper&gt;的理解不正确,现在就是在ant的build.xml中调用svn的提交命令来解决的,不知道思路是否正确,请大家指教。<br />
<br />
下面就更清晰的介绍一下常用的标签把。<br />
<br />
CC配置文件范connectfour范例Config.xml如下:<br />
<br />
&lt;cruisecontrol&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;project name=&quot;connectfour&quot;&gt;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;listeners&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;currentbuildstatuslistener file=&quot;logs/${project.name}/status.txt&quot;/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/listeners&gt;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;bootstrappers&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;antbootstrapper anthome=&quot;apache-ant-1.7.0&quot; buildfile=&quot;projects/${project.name}/build.xml&quot; target=&quot;clean&quot; /&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/bootstrappers&gt;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;modificationset quietperiod=&quot;30&quot;&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!-- touch any file in connectfour project to trigger a build --&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;filesystem folder=&quot;projects/${project.name}&quot;/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/modificationset&gt;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;schedule interval=&quot;300&quot;&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;ant anthome=&quot;apache-ant-1.7.0&quot; buildfile=&quot;projects/${project.name}/build.xml&quot;/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/schedule&gt;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;log&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;merge dir=&quot;projects/${project.name}/target/test-results&quot;/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/log&gt;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;publishers&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;onsuccess&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;artifactspublisher dest=&quot;artifacts/${project.name}&quot; file=&quot;projects/${project.name}/target/${project.name}.jar&quot;/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/onsuccess&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/publishers&gt;<br />
<br />
&nbsp;&nbsp;&nbsp; &lt;/project&gt;<br />
&lt;/cruisecontrol&gt;<br />
<br />
&lt;cruisecontrol&gt;根元素是&lt;cruisecontrol&gt;,该元素很简单,没什么需要配置的属性。<br />
<br />
目前CC支持多项目(multiproject),因此可以有多个并行的&lt;project&gt;元素。支持的子元素包括:<br />
 &lt;project&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;plugin/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;dateformat/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;labelincrementer/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;listeners&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;cmsynergysessionmonitor/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;currentbuildstatusftplistener/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;currentbuildstatuslistener/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;currentbuildstatuspagelistener/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;lockfilelistener/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/listeners&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;bootstrappers&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;accurevbootstrapper/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;alienbrainbootstrapper/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;antbootstrapper/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;clearcasebootstrapper/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;clearcaseviewstrapper/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;cmsynergybootstrapper/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;currentbuildstatusbootstrapper/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;currentbuildstatusftpbootstrapper/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;cvsbootstrapper/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;execbootstrapper/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;gitbootstrapper/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;harvestbootstrapper/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;lockfilebootstrapper/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mercurialbootstrapper/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;p4bootstrapper/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;plasticscmbootstrapper/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;snapshotcmbootstrapper/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;starteambootstrapper/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;surroundbootstrapper/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;svnbootstrapper/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;tfsbootstrapper/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;vssbootstrapper/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/bootstrappers&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;modificationset&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;accurev&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;alienbrain/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;alwaysbuild/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;buildstatus/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;clearcase/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;cmsynergy/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;compound&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;targets/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;triggers/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/compound&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;cvs/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;darcs/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;filesystem/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;forceonly/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;git/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;harvest/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;httpfile/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mavensnapshotdependency/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;maven2snapshotdependency/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mercurial/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mks/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;p4/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;plasticscm/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;pvcs/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;snapshotcm/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;starteam/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;store/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;surround/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;svn/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;tfs/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;timebuild&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;ucm&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;veto/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;vss/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;vssjournal/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/modificationset&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;schedule&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;ant/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;maven/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;maven2/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;pause/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;nant/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;phing/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;rake/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;exec/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;composite/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/schedule&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;log&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;merge/&gt;<br />
&lt;gzip/&gt;<br />
&lt;delete/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/log&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;publishers&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;antpublisher/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;artifactspublisher/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;clearcasebaselinepublisher/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;cmsynergybaselinepublisher/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;cmsynergytaskpublisher/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;compoundpublisher/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;currentbuildstatuspublisher/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;currentbuildstatusftppublisher/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;email/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;execute/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;ftppublisher/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;htmlemail/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;http&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;jabber/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;onfailure/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;onsuccess/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;rss/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;sametimeannouncement/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;scp/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;sfeedocman/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;sfeefrs/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;sfeetracker/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;socket/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;weblog&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;x10/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;xsltlogpublisher/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;yahoopublisher/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/publishers&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;/project&gt;<br />
子元素过多所以详情可以参看官方文档的说明。<br />
<br />
这里只介绍几个常用的子元素:<br />
<br />
&lt;bootstrappers&gt;:&lt;bootstrappers&gt;在创建之前会运行,相当于一个预处理的作用,&lt;bootstrappers&gt;下面每个子元素都是独立的,因此可以同时配置多个bootstrappers。<br />
<br />
CC提供的bootstrappers包括两种,一种用于向其他插件提供项目当前创建的状态,还有一种是从某个源码控制系统更新本地文件,其中最常用的就是&lt;currentbuildstatusbootstrapper&gt; 和&lt;svnbootstrappers&gt;。&lt;currentbuildstatusbootstrapper&gt;指定了状态文件的位置,主要是用来访问项目当前创建的状态,CC的&lt;currentbuildstatusbootstrapper&gt;会将创基爱你的状态写入这个文件。<br />
<br />
&lt;svnbootstrapper&gt;的作用有点难理解,因为我们每次项目的创建都应该基于最新的代码,因此在创建之前就要获得最新的项目文件,如果使用的是ant来完成这个任务,那么buildfile本身在创建开始之前发生了变化,我们是不是应该先更新这个buildfile,然后才通过buildfile来对项目进行构建呢?&lt;svnbootstrapper&gt;就是为从源码控制系统更新buildfile文件而设计的(还有一种替代的使用方法是使用wrapper buildfile,这样就不用使用&lt;svnbootstrapper&gt;了,wrapper buildfile也是推荐的方法,&lt;modificationset&gt;部分会进行详细的讨论)。<br />
<br />
&lt;modificationset&gt;:包括了SourceControl插件的配置信息,用于检查各个源码控制系统中是否发生变化,&lt;schedule&gt;会用到这里的配置信息,如果检测到变化,会触发创建过程。<br />
<br />
&lt;modificationset&gt;的属性quietperiod(单位为秒)定义了一个时间值。如果CC检查到了变化,会自检查到变化的源码控制系统的最后一次check in 的时间开始等待,等待时间由quietperiod决定,等待结束之后才触发创建(build)过程,主要是防止有人在check in的过程当中就触发创建过程(可能check in只做了一半,这个时候触发创建显然是不正确的).<br />
<br />
下面是一个modificationset的例子:<br />
<br />
&lt;modificationset quietperiod=&quot;30&quot;&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;svn localworkingcopy=&quot;projects/SFA&quot;/&gt;<br />
&lt;/modificationset&gt;
vfdff(作者)
2009-08-23 00:17
4
如何用CruiseControl.Net来进行持续化集成[转]<br />
<br />
本文的目的: http://www.uml.org.cn/jchgj/200904082.asp<br />
<br />
本文总结了过去一年中使用CruiseControl.Net来对工作流程进行持续化集成的经验教训,详细地讲述安装,配置,使用 CruiseControl.Net的具体步骤,希望通过阅读本文,能理解和掌握使用CruiseControl.Net的基本使用技巧,用工具来改善工作流程和提高工作效率。<br />
<br />
什么是持续化集成<br />
<br />
首先,我们先搞清楚什么是持续化集成?它对我们的日常工作有什么样的帮助?在过去几年中,敏捷已经是一个非常热门的话题,它高效的工作方式和快速的需求应对能力,赢得了很多中小软件厂商的关注。那么敏捷除了一些经常谈论到编程思维和迭代的开发模式等,其实还部分依赖于好的改善工作流程的工具。持续化集成工具便是服务于敏捷软件开发的一个系列。它主要将原本分散,无序的工作流程,通过工具软件有机的组织起来,并且在组织的过程中,参与开发设计测试的各个部门的人员都能从中获取到自动化方面的优惠。使得团队的工作效率大大提升。<br />
<br />
CruiseControl.Net是什么?<br />
<br />
上面讲解了什么是持续化集成,那CruiseControl.Net就是一款由ThoughtWorks公司提供给我们的轻量级的持续化集成工具。它能够将代码版本控制,单元测试,代码规范检查,项目的发布部署等工作步骤有机的组织起来,并且利用其调度性可作自动化处理,它还有强大的日志记录功能,能将集成结果及时地反馈给项目管理人员和项目开发人员。在下文中凡是用到CruiseControl.Net均用CC.Net来代替。下面是CC.Net 的工作流程图<br />
<br />
如何安装CC.Net<br />
<br />
CC.Net是一款开源软件,它的官方主页是: http://confluence.public.thoughtworks.org/display/CCNET/Welcome+to+CruiseControl.NET<br />
<br />
打开它的主页,便能看出他的官方采用另外一款非常出色的团队协作平台:Confluence,用它结合jira Bug管理系统,也能极大限度的提高团队协作能力,有关他们的介绍请访问:http://www.jira.com/ 。好了,返回来继续介绍CC.Net,当前官方已经发布了最新的CruiseControl.NET-1.3.0.2918,在首页的release栏中,便可以找到下载最新版CC.Net的连接,它是一款开源软件,你也可以在http://www.sf.net中找到它的源码和安装文件。如果你就是想使用CC.Net直接下载exe文件即可。下载后,在本地的安装过程如下:<br />
<br />
1.双击CruiseControl.NET-1.3-Setup.exe程序,打开软件安装界面,如下:<br />
<br />
2.一直点击Next,选择软件安装路径,等待软件安装完成,界面如下:<br />
<br />
3.软件安装完成之后,在系统windows服务中将增加名为CruiseControl.Net Server的系统服务,如下:<br />
<br />
注意,默认情况该服务是出于未启动状态的。<br />
<br />
因为CC.Net是一个集成持续工具在部署CC.Net之前,单独靠它自己是没有实际意义的,所以在部署配置CC.Net之前,您需要事先准备好并且安装下述软件:<br />
<br />
1.代码版本管理工具如VSS<br />
<br />
2.代码构建工具,如果您是vs.net的用户,强烈建议不要使用NAnt,配置起来比较麻烦,建议使用MsBuild来做构建工具。 MsBuild是随.Net FrameWork 2.0一起安装的,所您需要在CC.Net服务器上安装.Net FrameWork 2.0或者以上版本。<br />
<br />
3.代码规范检查工具,.Net用户推荐使用FxCop.exe,下载地址:http://www.microsoft.com/downloads/details.aspx?FamilyID=3389f7e4-0e55-4a4d-bc74-4aeabb17997b&amp;displaylang=en,很不幸的是,它原来的官方主页 http://code.msdn.microsoft.com/GotDotNet.aspx 关闭了,在新的站点中,我没有搜索到它。<br />
<br />
4.单元测试工具:Nunit,官方主页:http://sourceforge.net/projects/nunit<br />
<br />
5.发布部署工具,如果是asp.net网站,可以使用ASP.NET 编译工具 (Aspnet_compiler.exe),但我感觉它不好用,于是我自己实现了一系列的代码发布,FTP上传,XCopy安装等组件,在后面会提到。<br />
<br />
除了上述,CC.Net还支持NCover,Simian和Fitness,我没有具体应用,便不多讲。<br />
<br />
如何配置和部署 <br />
<br />
假定上述的几个工具已经成功安装,下面就用一个项目来演示一下如何实现自动化构建,单元测试,代码规范检测,自动发布部署。并且可以演示项目管理和开发人员通过什么样的手段能及时了解持续集成化的结果。<br />
<br />
在演示制作之前,我们先来看一下当前的持续集成环境。<br />
<br />
 <br />
<br />
首先,我们创建用于演示的解决方案Jillzhang.DailyBuild,其中包括四个项目: <br />
<br />
 <br />
<br />
建立好解决方案之后,将其添加到VSS项目管理器中。层次结构如下:<br />
<br />
 <br />
<br />
下面我让我们看一下,如何配置CC.Net使其工作起来。 <br />
<br />
1.在CC.Net服务器上,点击开始菜单,在所有程序中选择CruiseControl.Net,打开CruiseControl.NET Config配置文件。<br />
<br />
2.CC.Net支持同时监控和集成多个解决方案,每个解决方案在CC.Net中被称为1个Project.,在 CruiseControl.NET Config中1个Project被一个&lt;project&gt;元素来描述。当然我们还要为每个Project指定名称和工作目录和日志存放目录。阅读CC.Net的文档,你可以了解&lt;project&gt;元素的一些属性和子元素。这里我只讲述一些我用到的。<br />
<br />
name ,如&lt;project name=&quot;Project1&quot;&gt;表示1个名称为Project1的新工程,这个名称在日后会作为项目的标识显示给查看报告的用户。比如显示在 cctray上或者在网站doashboard上进行显示。还有一个比较重要的子元素&lt;workingDirectory&gt;这个元素非常类似于WCF配置中的&lt;baseAddress&gt;,用它来指示工程的工作目录,也就是从版本管理器上下载文件的根目录。除了这些我们还需要设定子元素&lt;artifactDirectory &gt;它用来指示日志记录的保存位置。CC.Net为我们提供了几种版本管理方式,可以用&lt;labeler&gt;来指定使用哪种类型的版本标签,如Date Labeller,Default Labeller等,具体也可以查阅文档。我们这里使用Date Laberller,所以设置为&lt;labeler type=&quot;dateLabeller&quot;/&gt;。下面可以设置源代码管理器,CC.Net支持目前绝大多数主流的版本控制工具,如 CVS,VSS,Rational ClearCase,VSTS, Alienbrain等十几种。我们这里使用VSS,根据上文VSS和解决方案的配置,我们这里设置为: <br />
<br />
将autoGetSource设置为true,CC.Net会通过监视VSS中代码的版本变化,自动从版本管理器中获取源代码。Project是要使用的解决方案在vss中的路径,值为如下:<br />
<br />
Username为访问vss的用户名,password为访问vss的密码。ssdir是 vss代码库的共享路径,我这里为http://www.cnblogs.com/lovko/admin/file://192.168.1.200/vss/ 。如果将cleanCopy设置为true,那么CC.Net每次获取最新文件的时候是否完全覆盖更新文件。<br />
<br />
当前,我们的配置文件为:<br />
<br />
设置好VSS后,我们可以启动CC.Net了,方法如下,打开Services.Msc,找到CruismControl.Net Server服务,在启动之前,需要先解决一下可能最影响情绪的问题:我们知道windows services默认情况下是用本地系统账户运行的,可一般情况下我们会在当前操作用户下设置对vss共享目录的访问权限,比如当前windows运行账户为administrator,那么我们在administrator中通过net use设置对http://www.cnblogs.com/lovko/admin/file://192.168.1.200/vss/的访问,也可以通过Source Safe Client打开该代码库,可这往往是一个烟雾弹,当我们在CC.Net中试图用服务来访问http://www.cnblogs.com/lovko/admin/file://192.168.1.200/vss/ 的时候,系统服务账户并没有与该共享目录建立会话,所以会拒绝访问http://www.cnblogs.com/lovko/admin/file://192.168.1.200/vss/,连访问权限都没有,更不用说获取代码了。所以首先要注意的是启动前,先设置服务的运行账户:<br />
<br />
 <br />
<br />
只有这样,我们才能进行下面的工作:<br />
<br />
启动CruismControl.Net Server服务,重新签出,嵌入一下解决方案,稍等一段时间,我们便会在工作目录E:\DailyBuild中看到自动获取过来的文件。还要值得注意的一点是在log目录中最好事先创建好buildlogs,如果您在启动CrusimControl.Net Server服务的时候有错误出现,比如在启动的时候总是出现:<br />
<br />
 <br />
<br />
很可能得情况就是上面的配置有错误,您可以通过下面两种方式来确定服务到底出现了什么样的问题:<br />
<br />
1.按照提示,在事件查看器中查看错误,如: <br />
<br />
 <br />
<br />
2.您还可以到CrusimControl.Net Server的应用程序目录查找名为ccnet.log的文件,里面有CC.Net详细的操作步骤。<br />
<br />
如果没有启动错误并且在ccnet.log中没有明显的异常,可以打开监视网站来查看集成结果,监视网站的地址是在&lt;project&gt;元素上通过设置webURL属性来完成的,我们打开这个网址,如图:<br />
<br />
 <br />
<br />
当Last Build Status为Success的时候表示项目集成成功,此时点击项目名,可以查看具体的集成结果:<br />
<br />
 <br />
<br />
如果调用MsBuild来对代码进行生成,调用FxCop进行代码规范检查,和调用NUnit进行单元测试集成,还需要对CC.Net进行下一步的配置。<br />
<br />
代码规范检侧工具FxCop不能被CC.Net直接使用,它必须附加到MsBuild.Exe的命令行中,有关如何使用MSBuild,可以参考 msdn,不做具体介绍。为此我们创建一个用于生成并检查代码规范的任务,CC.Net支持自定义任务,方法是:使用Task中的Executable Task。<br />
<br />
首先在工作目录,创建一个用于msbuild参数的DailyBuild.msbuild文件,文件内容如下:<br />
<br />
这个MsBuild选项会使得msbuild.exe在生成完成之后调用工作目录中的exeu.bat文件,exeu.bat中是关于使用FxCop方法的,内容如下:<br />
<br />
目的就是通过调用FxCop安装目录下的FxCopCmd命令行工具,对指定的程序集进行规范性检查,上述代码中,E:\DailyBuild \Jillzhang.DailyBuild.FxCop是事先生成好的FxCop项目文件,生成办法是打开FxCop 可视化界面,添加target,并保存到此为位置即可,如图:<br />
<br />
 <br />
<br />
并保存到E:\DailyBuild\Jillzhang.DailyBuild.FxCop<br />
<br />
添加能生成代码并且检测代码规范性的配置如下:<br />
<br />
注意,buildTimeoutSeconds是生成操作的超时时间,还有最好设置/p:Configuration=Release,因为这样有利于以后发布。而Merge是将上面各个任务中生成的日志进行合并。<br />
<br />
下面重新签出嵌入,观察集成结果:<br />
<br />
 <br />
<br />
可以看到,已经release成功。<br />
<br />
下面就看一下生成的DailyBuild.FxCop.xml,<br />
<br />
打开看里面的内容便可以发现代码检测结果。
游客请输入验证码
浏览1943095次