浅谈CruiseControl的部署

ANT是用过的最好的Build工具.CruiseControl则通过不断检查SCM (VSS, ClearCase, StarTeam, etc), 一旦发现改动, 调用ANT进行编译, 部署, 实现即时的集成. 一旦编译失败, 则立刻自动发Email给"始作俑"者, 提醒其修正代码. CC自带了一个Web应用, 可是随时查看编译状况和历史状况(包括自从前一次Build, 有哪些文件,是谁做了改动, Build失败的原因, Build的成果(自定义的, 比如最后的打包文件, 自动生成的JavaDoc) 总之, 通过集成Ant和CC, 尽量避免了Daily Build容易Broken的缺点, 而且自动化程度更高. 另外Ant和CC都分别有.net版本, 在下一个.net项目中, 还打算使用它们来进行集成控制. 安装CruiseControl 和AntHill一样,使用CruiseControl构建持续集成系统,需要Tomcat,Ant,CVSNT和WinCVS的支持(参见AntHill:构建Nightly Build系统)。安装CruiseControl很简单,下载cruisecontrol-2.2.zip(参见持续集成资源),解压到安装目录C:/BuildServer,即可完成安装。 安装Tomcat4.1到C:/BuildServer目录,并在C:/BuildServer目录创建workingCopy子目录,作为CruiseControl的工作目录。BuildServer的目录结构如下图所示,其中CruiseControl的启动脚本cruisecontrol.bat(或cruisecontrol.sh)位于BuildServer/cruisecontrol-2.2/main/bin目录下。 准备构建目录结构 1.创建CruiseControl的日志目录:C:/BuildServer/cruisecontrol-2.2/main/logs/frameworkProject。 2.创建CVS的工作目录:C:/BuildServer/workingCopy/frameworkProject。 3.创建工作目录的代码库目录:C:/BuildServer/workingCopy/frameworkProject/lib。 4.创建工作目录的单元测试报告目录:C:/BuildServer/workingCopy/frameworkProject/reports/junit/data。 5.创建工作目录的jar文件存放目录:C:/BuildServer/workingCopy/frameworkProject/dist。 初始化代码工作目录 在C:/BuildServer/workingCopy/frameworkProject目录下,使用WinCVS CheckOut src模块:cvs co src。 准备项目的依赖代码库 把构建项目的依赖代码库复制到C:/BuildServer/workingCopy/frameworkProject/lib。完成之后的目录结构如上图所示。 编写项目构建脚本 构建脚本build.xml和build-cc.xml位于C:/BuildServer/workingCopy/frameworkProject目录下。其中build.xml是项目的Ant构建脚本,而build-cc.xml负责帮助CruiseControl从CVS服务器上update源代码到本地的工作目录,然后调用build.xml构建项目。 build-cc.xml
<?xml version="1.0"?>
<project name="CruiseControlWrapperForFrameworkProject" default="build" basedir=".">
 <target name="update">
  <!-- update the working copy from the cvs -->
  <exec executable="cvs">
   <arg line="-d :pserver:talent:talent @10.75.140.128:/cvsroot update src"/>
  </exec>
 </target>
  <target name="build" depends="update">
  <!-- invoke the project's build script -->
  <ant antfile="build.xml" target="jar"/>
 </target>
</project>
build.xml
<?xml version="1.0"?>
<project name="frameworkProject" default="compile">
    <description>
        This is our framework project which we're putting on CruiseControl
    </description>
        <target name="setup" depends="setup.properties, setup.paths" />
    <target name="setup.properties">
        <property name="src.main" value="src" />
        <!--<property name="src.test" value="src/test" />-->
        <property name="classes" value="classes"/>
        <property name="classes.main" value="${classes}/main" />
        <!--<property name="classes.test" value="${classes}/test" />-->
        <property name="libs" value="lib" />
        <property name="dist" value="dist" />
        <property name="reports" value="reports" />
        <property name="reports.junit.data" value="${reports}/junit/data" />
    </target>
    <target name="setup.paths">
        <path id="classpath.main">
            <pathelement location="${classes.main}" />
        </path>
        <path id="classpath.lib">
         <fileset dir="${libs}">
          <include name="**/*.jar" />
         </fileset>
        </path>
    </target>
    <target name="clean" depends="setup">
        <delete dir="${classes}" failonerror="false" />
        <delete dir="${reports}" failonerror="false" />
        <delete dir="${dist}" failonerror="false" />
    </target>
    <target name="compile" depends="setup, compile.main" />
    <target name="compile.main" depends="setup">
        <mkdir dir="${classes.main}" />
        <javac srcdir="${src.main}" destdir="${classes.main}">
         <classpath refid="classpath.lib" />
        </javac>
    </target>
    <target name="compile.tests" depends="setup">
        <mkdir dir="${classes.test}" />
        <javac srcdir="${src.test}"
               destdir="${classes.test}"
               classpathref="classpath.lib" />
    </target>
    <target name="test" depends="compile">
        <delete dir="${reports.junit.data}" failonerror="false" />
        <mkdir dir="${reports.junit.data}" />
        <junit printsummary="yes" haltonfailure="no" 
               failureproperty="tests.failed">
            <classpath refid="classpath.lib" />
            <formatter type="xml" />
            <batchtest fork="yes" todir="${reports.junit.data}" 
                       failureproperty="tests.failed">
                <fileset dir="${src.test}">
                    <include name="**/*Test*.java" />
                    <exclude name="**/AllTests.java" />
                </fileset>
            </batchtest>
        </junit>
        <fail if="tests.failed" message="Some unit tests failed" />
    </target>
    <target name="jar" depends="compile, test">
        <mkdir dir="${dist}" />
        <jar destfile="${dist}/framework.jar" basedir="${classes.main}" />
    </target>
    <target name="all" depends="jar" />
</project>
配置CruiseControl config.xml 下面以一个简单的config.xml文件为例,说明CruiseControl的配置方法。配置文件config.xml位于C:/BuildServer/cruisecontrol-2.2/main/bin目录下,和启动脚本cruisecontrol.bat放在一起。
<?xml version="1.0"?>
<cruisecontrol>
 <project name="frameworkProject">
  <dateformat format="yyyy/MM/dd HH:mm:ss" />
  <bootstrappers>
   <currentbuildstatusbootstrapper file="../logs/currentbuild.txt" />
  </bootstrappers>
  <modificationset quietperiod="60" >
   <cvs LocalWorkingCopy="../../../workingCopy/frameworkProject/src"/>
  </modificationset>
  <schedule interval="3600" >
   <ant antWorkingDir="../../../workingCopy/frameworkProject" buildfile="build-cc.xml" />
  </schedule>
  <log dir="../logs/frameworkProject">
   <merge dir="../../../workingCopy/frameworkProject/reports/junit/data"/>
  </log>
  <publishers>
   <currentbuildstatuspublisher file="../logs/currentbuild.txt" />
   <artifactspublisher dir="../../../workingCopy/frameworkProject/dist" dest="../logs/frameworkProject" />
   <htmlemail mailhost="talenttech.com.cn"
    returnaddress="buildmaster@talenttech.com.cn" 
    subjectprefix="[Talent Build Server]"//自己替换[]
buildresultsurl="http://10.75.140.128:9000/cruisecontrol/buildresults/ ;frameworkProject"
logdir="C:/BuildServer/cruisecontrol-2.2/main/logs/frameworkProject"
            xsldir="C:/BuildServer/cruisecontrol-2.2/reporting/jsp/xsl"
css="C:/BuildServer/cruisecontrol-2.2/reporting/jsp/css/cruisecontrol.css">
    <failure address="liutao@talenttech.com.cn" />
    <success address="liutao@talenttech.com.cn" />
    <success address="wangkai@talenttech.com.cn" />
    <success address="wangchuang@talenttech.com.cn" />
    <success address="wu.gaofeng@126.com" />
   </htmlemail>
  </publishers>
 </project>
</cruisecontrol>
<cruisecontrol> <cruisecontrol>是配置文件的根元素,它可以拥有一个或多个<project>子元素。本例中它拥有一个项目名为frameworkProject。 <project> <project>元素是一个完整的build任务,包括检查配置管理库是否有新的修改,构建项目并发布项目构建结果。它告诉CruiseControl构建什么,何时构建,如何构建以及如何发布构建报告。它有一个必需的属性name和一个可选属性buildafterfailed。 属性buildafterfailed定义了当构建失败时,是否要继续进行,缺省是"true"。 <project>元素的子元素包括,<bootstrappers>,<modificationset>,<schedule>,<log>,<publishers>,<dateformat>和<plugin>,其中<modificationset>和<schedule>是必需的元素。 <dateformat> <dateformat>用于定义日期的格式,缺省格式是:MM/dd/yyyy HH:mm:ss。 <bootstrappers> <bootstrappers>元素是启动任务Plugin的容器,用于定义构建任务启动前需要执行的任务。常用的Plugin包括: 1. <currentbuildstatusbootstrapper>,定义一个CruiseControl的构建状态信息文件。CruiseControl的Build Result JSP从该文件读取状态信息并显示在页面上。属性file用于指定构建状态文件目录和文件名。 2. <cvsbootstrapper>,用于在项目构建开始前从CVS服务器上update指定的文件。通常可以用于更新项目的构建脚本。属性localWorkingCopy指定CVS本地工作目录,属性file指定需要update的文件名,相对于属性localWorkingCopy指定的目录。 <modificationset> <modificationset>元素用于告诉CruiseControl是否需要构建项目,即配置管理库的代码是否存在更新。它拥有两个可选属性requiremodification和quietperiod。 属性requiremodification告诉CruiseControl,在配置管理库没有代码更新的情况下,是否需要构建。缺省为"true",即没有更新则无须进行构建。 属性quietperiod告诉CruiseControl,最新一次代码提交后CruiseControl需要等待的时间(秒)。用于防止CruiseControl在开发人员提交代码时进行项目构建。缺省为"60"秒。 在本例中使用<cvs>来检查和工作目录相关的代码在CVS配置管理库是否有更新。<cvs>使用"cvs log"命令来检查最新更新工作目录和当前代码库的差异。 <schedule> 到目前为止,以上的配置文件内容已经定义了CruiseControl构建什么以及何时构建。<schedule>元素告诉CruiseControl每隔多长时间(秒)启动一次构建任务。它有一个可选的属性interval,用于定义以秒为单位的时间间隔。缺省为"300"秒。 在本例中,属性interval设为"3600",这意味着CruiseControl每隔一个小时使用<modificationset>定义的任务检查一次代码库。 <schedule>元素拥有三个子元素<ant>,<maven>和<parse>。 <ant>子元素告诉CruiseControl何时或每隔几次运行Ant来构建项目。 在本例中,antWorkingDir属性设定Ant的工作目录,buildfile属性设定构建脚本build file的目录。 属性multiple告诉CruiseControl每隔几次执行一次本<ant>任务。 除此之外,还可以指定Ant的运行时间(time属性),build file的target(target属性,不设定则为build file的缺省target)。 请参见CruiseControl的配置文档(位于${CruiseControl_Home}/main/docs目录下)。 <log> <log>元素设定CruiseControl日志文件的存放目录,并通过<merge>子元素指定合并什么样的XML文件(构建过程中产生的文件)到CruiseControl的日志文件中。 <merge>子元素的pattern属性定义匹配的文件名模式,缺省为".xml";dir属性用于指定一个目录,这个目录下所有匹配模式的文件将合并到CruiseControl的日志文件中。 <publishers> <publishers>元素用于指定构建任务结束后,CruiseControl如何发布项目构建结果。项目构建结果的发布方式可以是Email,网页,复制代码库到指定的目录,或是发布代码库到FTP服务器。 在本例中,共有<currentbuildstatuspublisher>,<artifactspublisher>和<htmlemail>三个publisher。 <currentbuildstatuspublisher> publisher把下次构建的时间写入指定文件,文件名由file属性设定。 <artifactspublisher> publisher元素把项目构建产品复制到指定的目录,dir属性定义源目录,dest定义目标目录的父目录(实际目录还要加上构建时的时间戳,如:父目录/19890604203828)。 <htmlemail> publisher把构建结果以HTML格式通过Email发布。缺省情况下,HTML格式的Emai和CruiseControl Web应用的构建结果JSP页面相同。 本例中<htmlemail>的属性和子元素的作用很容易理解,更多的配置项参见联机文档。 创建CruiseControl的Web应用 1. 在C:/BuildServer/cruisecontrol-2.2/reporting/jsp目录下运行build war命令; 2. 提示设置user.log.dir属性时,输入C:/BuildServer/cruisecontrol-2.2/main/logs; 3. 提示设置user.build.status.file属性时,输入currentbuild.txt; 4. 提示设置cruise.build.artifacts.dir属性时,输入/artifacts/frameworkProject; 5. Web应用构建完成后,可以在C:/BuildServer/cruisecontrol-2.2/reporting/jsp/dis目录下找到cruisecontrol.war文件; 6. 把cruisecontrol.war复制到tomcat的webapps目录下,发布CruiseControl的Web应用; 启动CruiseControl 使用C:/BuildServer/cruisecontrol-2.2/main/bin目录下cruisecontrol.bat启动CruiseControl。用法如下: C:/BuildServer/cruisecontrol-2.2/main/bin>cruisecontrol [options] 命令cruisecontrol的选项包括: -port [number] JMX服务器的Http Controller的端口;缺省为8000 -rmiport [number] JMX服务器的RMI Controller的端口;缺省为1099 -xslpath directory JMX的XSL文件存放目录; -configfile file 配置文件的路径;缺省为当前目录下的config.xml文件 -debug 将CruiseControl内部的日志级别调整到DEBUG 只有指定port和/或rmiport属性时,JMX服务器才启动。如果要修改port参数(不使用缺省的8000端口),必须要修改reporting/jsp目录下的controlpanel.jsp文件,然后再重新创建和发布CruiseControl的Web应用;也可以直接修改Tomcat/webapps/cruisecontrol目录下的controlpanel.jsp页面。 CruiseControl的Web界面 在浏览器地址栏输入:http://BuildServer-IP:9000/cruisecontrol/,可以访问CruiseControl的Web应用,如下图所示: 在左侧区域,按时间顺序列出最新Build结果的连接。如果Build结果超过10个,左侧区域只显示10个连接,其余的Build结果可以在下面的下拉框中找到。上图中因为Build结果少于10个,所以下拉框是空的。 当点击右上角的Control Panel按钮时,如果出现错误,则是因为没有使用CruiseControl的JMX支持。要启动JMX支持,请看下节内容。 使用JMX控制台 要使用CruiseControl的JMX控制台很简单,只需在启动cruisecontrol时指定JMX Server的Http Controller端口即可:cruisecontrol -port 8000。 进入CruiseControl的Web应用界面,点击右上角的Control Panel按钮,则出现CruiseControl的"JMX Control Panel"。 可以通过JMX控制面板在运行时修改配置,而不需要重启CruiseControl。点击CruiseControl Project MBean,尝试它的管理功能。 例如,可以修改MBean的"BuildInterval"属性,来更改项目构建的时间间隔;修改ConfigFileName,则可以更改CruiseControl的配置文件;点击MBean的build操作"invoke"按钮,则可以强制启动项目构建任务。 持续集成资源 1. 持续集成:http://www.martinfowler.com/articles/continuousIntegration.html 2. AntHill:http://www.urbancode.com/projects/anthill/ 3. CruiseControl:http://cruisecontrol.sourceforge.net/ 4. CVSNT:http://www.cvsnt.org/ 5. WinCVS中文版:http://www.8848software.com/wincvs/ 6. Driving On CruiseControl Part1: http://www.javaranch.com/journal/200409/DrivingOnCruiseControl_Part1.html 7. Driving On CruiseControl Part2: http://www.javaranch.com/journal/200410/DrivingOnCruiseControl_Part2.html 8. Scheduled Builds:http://www.pragmaticprogrammer.com/starter_kit/au/scheduled.pdf Java代码规范检查工具很多,CheckStyle是其中最有名的,它的Eclipse插件,使用非常方便。我在最近的项目中,之所以选择JCSC,是因为JCSC不但可以检查代码规范,而且给出了NCSS(Non Commenting Source Statements)和CCN(Cyclomatic Complexity Number),前者近似等于Java的有效代码行,后者则用于评价类方法的复杂度。 下面的安装配置延续我的Blog,CruiseControl:持续集成工具的例子。 安装JCSC 1、从SourceForge下载JCSC.zip 2、将JCSC.zip解压到D:/BuildServer目录 3、添加JCSC_HOME系统环境变量,本例中为D:/BuildServer/jcsc 4、添加JCSC_HOME/bin到系统路径 配置ANT 1、把JCSC_HOME/jcsc/lib的jar文件复制到/ANT_HOME/lib 配置CruiseControl 1、把JCSC_HOME/lib的jar文件复制到DEFAULT_CCDIR/main/lib 2、修改cruisecontrol.bat,在cruisecontrol.jar之前添加%LIBDIR%/JCSC.jar,在类路径后面添加%LIBDIR%/xercesImpl.jar 3、复制/JCSC_HOME/html/xml/xsl/cruisecontrol/jcsc.xsl文件到TOMCAT_HOME//webapps/cruisecontrol/xsl目录 4、修改TOMCAT_HOME//webapps/cruisecontrol/xsl/jcsc.xsl文件,把JCSC Details的链接改成"/cruisecontrol/jcsc/index.html" 5、在TOMCAT_HOME/webapps/cruisecontrol/buildresults.jsp页面中添加 6、在webapps/cruisecontrol目录下创建jcsc目录 7、复制JCSC_HOME/html/xml目录下的xsl子目录和index.html文件到webapps/cruisecontrol/jcsc目录 8、复制JCSC_HOME/html/web/jcsc-result/rules.jcsc.xml文件到webapps/cruisecontrol/jcsc目录 9、把JCSC生成的overview.xml合并到CruiseControl的log.xml文件。修改CruiseControl的config.xml文件,如 <log dir="../logs/frameworkProject"> <merge dir="../../../workingCopy/frameworkProject/reports/junit/data" /> <merge file="D:/BuildServer/tomcat-4.1.31/webapps/cruisecontrol/jcsc/overview.xml" /> </log> 修改ANT的构建脚本build.xml 1、添加JCSC属性
   <!-- jcsc home config -->
    <property name="jcsc.home" value="D:/BuildServer/jcsc" />
    <property name="jcsc.log.dir" value="D:/BuildServer/tomcat-4.1.31/webapps/cruisecontrol/jcsc" />
    <property name="jcsc.rules.dir" value="D:/BuildServer/tomcat-4.1.31/webapps/cruisecontrol/jcsc/rules.jcsc.xml" />
2、定义JCSC的ANT Task
<taskdef name="jcsc" classname="rj.tools.jcsc.ant.JCSCTask" />
3、<target name="clean">中添加删除JCSC日志文件的任务
<delete failonerror="false">
        <fileset dir="${jcsc.log.dir}" includes="*.xml" excludes="xsl,rules.jcsc.xml,index.html" />
</delete> 4、添加JCSC Target
<target name="jcsc">
  <jcsc rules="${jcsc.rules.dir}" destdir="${jcsc.log.dir}">
   <fileset dir="${src.main}" includes="**/*.java" />
  </jcsc>
 </target>
5、调用JCSC Task
<target name="all" depends="clean, jar, test, coverage.report, jcsc" />
使用Rules Editor修改Rules文件 1、运行JCSC_HOME/bin/ruleseditor.bat命令,使用Rules Editor编辑Rules定义文件,可以编辑Open Brace'{' On New Line,Class/I-Face Header等选项 2、也可以直接修改rules.jcsc.xml文件 集成在CruiseControl的JCSC报告如下图所示。 在htmlmail邮件中集成JCSC报告 要在CruiseControl的htmlmail邮件中集成JCSC报告,需要修改CruiseControl的代码。在HTMLEmailPublisher类的String[] xslFileNames变量中加入jcsc.xsl,即可在htmlmail中包含JCSC报告的概要部分。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值