Chinaunix首页 | 论坛 | 博客
  • 博客访问: 342100
  • 博文数量: 66
  • 博客积分: 4010
  • 博客等级: 上校
  • 技术积分: 2204
  • 用 户 组: 普通用户
  • 注册时间: 2007-01-23 12:53
文章分类
文章存档

2010年(20)

2009年(30)

2008年(16)

我的朋友

分类: WINDOWS

2009-06-18 15:35:58


CruiseControl服务器安装配置

  1. 认识CruiseControl
CruiseControlCI服务器的老者,诞生已是多年,在许多方面,CruiseControl服务器已经成为持续集成实践的同义词。而现在,CruiseControl已发展成为一个家族式系统,包括CruiseControl.javaCruiseControl.netCruiseControl.ruby等适应不同语言环境的实现,其强大的插件和扩展能力也是诸多同类系统无法比你的。而在这里,我只介绍该家族的本家CruiseControl.java,即CruiseControl
下图是CruiseControl系统的架构图:
 
CruiseControl系统架构图
图中我们可以看到,CruiseControl系统的主体是Build Loop机制,它采用了Source Code轮询机制,对持续集成环境的状态进行定时检测,并根据config.xml配置信息做出相应处理。CruiseControl服务器则使用HTTPRMI机制将持续集成服务公开到Reporting模块,同时使用XML数据格式对每次集成的数据进行归档。同时CruiseControl还可以集成了RSSIME-MAIL等信息发布机制,最大程度将信息广播到团队的每个成员。
CruiseControl系统集成循环的流程图见下图,图中显示了CruiseControl使用轮询机制对版本库进行检测,并对发生变更的代码进行预定操作的流程:
CruiseControl系统运行流程图
  2. CruiseControl的安装
CruiseControl的安装有许多方式。例如,如果使用Windows,会发现最简单的方式是下载二进制可执行文件,当然下载最新版本,然后运行它。要是高兴想研究,还可以下载源代码。
安装之后,CruiseControl预先配置了一个配置文件,轮询SVN(或其它版本控制系统)存储库并执行ANT构建脚本。服务环境不需要安装Web服务器,CruiseControl已经内嵌了Jetty web服务程序。
  3. CruiseControl的配置
CruiseControl服务器启动时,会自动检测配置信息中的任务信息,并对其进行校验和初始化,之后所有的工作,都是依据该配置信息进行的。
CruiseControl的配置使用了其安装目录下的config.xml文件,我们可以通过任一文本编辑器打开该配置文件,编辑各种配置信息。配置信息的定义遵循了标准XML文件格式,同时遵循了ANT自动构建配置信息的规则,因此建立一个普通工程的配置信息并非难事。
config.xml的节点配置说明如下:


xml version='1.0' encoding='gb2312'?>
 2<cruisecontrol>
 3    <project name="projectName">
 4
 5        
 6        <listeners>
 7            
 8            <currentbuildstatuslistener file="logs/${project.name}/status.txt"/>
 9        listeners>
10        
11        
12        <bootstrappers>
13            
14            <svnbootstrapper localWorkingCopy="projects/${project.name}" />
15        bootstrappers>
16
17        
18        
19        <modificationset quietperiod="300">
20            <svn localWorkingCopy="projects/${project.name}"/>
21        modificationset>
22
23        
24        <schedule interval="60">
25            <ant anthome="apache-ant-1.7.0" buildfile="projects/${project.name}/build.xml"/>
26        schedule>
27        
28        
29        <log>
30            
31            <merge dir="projects/${project.name}/test-reports"/>
32        log>
33        
34        
35        <publishers>
36            
37                
38                
40
41            
46            <htmlemail
47                charset="UTF-8"
48                mailhost="test163.com" 
49                defaultsuffix="@xxx.com"
50                username="xxx@163.com"
51                password="xxx"
52                returnname="CruiseControl"
53                returnaddress="xxx@163.com"
54                subjectprefix="构建日志"
55                xsldir="webapps/cruisecontrol/xsl"
56                css="webapps/cruisecontrol/css/cruisecontrol.css">
57                <always address="xxx@xxx.com.cn"/>
58                <failure address="xxx@xxx,yyy@yyy.com.cn"/>
59                
60            htmlemail>
61
62        publishers>
63
64    project>
65cruisecontrol>

配置文件有一个cruisecontrol根结点,其下则是代表一个项目的project子节点,再下层是项目的具体配置,在此示例中,存在了listenersbootstrappersmodificationsetschedulelog几个节点,分别代表了监听器、本地目录、变更目录、构建任务、日志工作。
   3.1.创建一个项目

   
       
...............


项目工程下的build.xml说明:

xml version="1.0" encoding="UTF-8" ?>
  2
  3
  4<project default="CI" name="xxx" basedir=".">
  5
  6    
  7    
  8    <property file="build.properties"/>
  9    
 10    
 11    
 12    
 13    <property name="projectName_CN" value="xxx"/>
 14    
 15    <property name="projectFolder" value="${projcet.path}/${projcet.name}"/>
 16    
 17    
 18    <property name="sourceFolder" value="${projectFolder}/src/main/java"/>
 19    
 20    <property name="configFolder" value="${projectFolder}/src/main/config"/>
 21    
 22    <property name="testFolder" value="${projectFolder}/src/test/java"/>
 23    
 24    <property name="libFolder" value="${projectFolder}/WebRoot/WEB-INF/lib"/>
 25    
 26    <property name="classFolder" value="${projectFolder}/WebRoot/WEB-INF/classes"/>
 27
 28    
 29    <property name="reportFolder" value="${projectFolder}/test-reports"/>
 30    
 31    <property name="reportFileName" value="junit-noframes.html"/>
 32    
 33    
 34    
 35    
 36    <property name="warFile" value="${projectFolder}/${projcet.name}.war"/>
 37    
 38    <property name="webFile" value="${projectFolder}/WebRoot/WEB-INF/web.xml"/>
 39    
 40    <property name="warSource" value="${projectFolder}/target/classes"/>
 41
 42    
 43    
 44    
 45    <path id="compilePath">
 46        
 47        <pathelement path="${classFolder}" />
 48        
 49        <path refid="libPath" />
 50    path>
 51
 52    
 53    <path id="jUnitPath">
 54        
 55        <pathelement path="${classFolder}" />
 56        
 57        <path refid="libPath" />
 58    path>
 59
 60    
 61    <path id="libPath">
 62        
 63        <fileset dir="${libFolder}">
 64            <include name="**/*.jar" />
 65        fileset>
 66    path>
 67    
 68    
 69    
 70    
 71    <target name="CI" depends="init,compile,test,makewar,deploy-catalina" description="持续集成"/>
 72
 73    
 74    <target name="init" description="初始化">
 75        
 76        <echo>正在删除编译程序目录echo>
 77        <delete dir="${classFolder}" />
 78        <echo>正在创建编译程序目录echo>
 79        <mkdir dir="${classFolder}" />
 80        
 81        <echo>正在删除单元测试报告目录echo>
 82        <delete dir="${reportFolder}" />
 83        <echo>正在创建单元测试报告目录echo>
 84        <mkdir dir="${reportFolder}" />
 85    target>
 86
 87    
 88    <target name="compile" depends="init" description="编译">
 89        <echo>编译源程序echo>
 90        
 91        <javac classpathref="compilePath" fork="true" memorymaximumsize="128m"
 92               destdir="${classFolder}" debug="true" deprecation="false"
 93               failonerror="false" verbose="false">
 94            
 95            <src path="${sourceFolder}" />
 96            
 97            <src path="${testFolder}" />
 98            
 99            <src path="${configFolder}" />
100            
101            <include name="**/*.java" />
102        javac>
103        <copy todir="${classFolder}">
104            <fileset dir="${configFolder}">
105                <include name="**/*.*"/>
106            fileset>
107            <fileset dir="${sourceFolder}">
108                <include name="**/*.xml"/>
109            fileset>
110        copy>
111    target>
112
113    
114    <target name="test" description="执行单元测试">
115        <echo>运行单元测试用例echo>
116        
117        <junit printsummary="true">
118            <classpath refid="jUnitPath" />
119            
120            <formatter type="xml"/>
121            
122            <batchtest todir="${reportFolder}">
123                
124                <fileset dir="${classFolder}">
125                    
126                    <include name="**/*Test.class"/>
127                fileset>
128            batchtest>
129        junit>
130        
131        <echo>生成单元测试报告echo>
132        
133        <junitreport todir="${reportFolder}" description="生成单元测试报告">
134            <fileset dir="${reportFolder}">
135                
136                <include name="TEST-*.xml" />
137            fileset>
138            
139            <report format="frames" todir="${reportFolder}" />
140        junitreport>
141    target>
142
143    
144    <target name="makewar" depends="" description="发布WAR文件">
145        <echo>打包成war文件echo>
146        <war destfile="${warFile}" webxml="${webFile}">
147            
148            <fileset dir="${projectFolder}/WebRoot" excludes="WEB-INF/web.xml,WEB-INF/classes/**/*Test.class"/>
149        war>     
150    target>

一个持续集成项目是从project节点开始的,可以对该项目进行的操作都会作为子节点存在与该节点之下。对于每一个project节点,CruiseControl系统都会将其当作一个处理单元,并在最初建立该项目的时候进行初始化操作。
nameproject节点常用的属性,也是必设且值唯一的属性,该属性的值会在整个CruiseControl系统使用,包括配置文件的${project.name}变量值。
在一个项目节点中,我们可以定义监听器、本地目录位置、变更轮询目录位置、轮询间隔、任务执行、单元测试、日志记录等多种项目操作,同时CruiseControl系统支持插件扩展功能,这些扩展插件可以直接在一个项目中使用。
   3.2.轮询版本控制系统
版本库轮询机制是使用modificationset进行配置的。CruiseControl系统内置的轮询模块会根据设定的时间段对版本库进行检测,一旦发现版本库发生变更,就会调用Check OutàBuildàTestàPublish等一系列的操作,对最新的代码进行集成,并运行一系列预先设定的任务。
CruiseControl支持十多种版本控制系统,比如CVSSVNStarteamVSS等,对这些版本控制系统的调用,只需要配置相应的节点名称即可。本文以SVN版本管理系统为例。
modificationset节中,我们看到唯一的一个子节点:

该节点使用了svn关键字,表示当前工程使用的版本控制系统是SVNlocalWorkingCopy属性的值是告诉CruiseControl本地的拷贝目录,其余的工作则由CruiseControl内置的操作模块进行。
   3.3. 执行构建脚本
实质上,执行构建脚本也是CruiseControl的一个可定制任务,但由于自动构建是持续集成的一个重要组成部分,因此在此单独提出。
CruiseControl的自动构建是使用ANT工具来进行的,当然我们也可以使用其它的自动构建工具来替代(比如Maven),这些的工具仅仅是体现在一个任务配置语句上,在此,以ANT工具为例。
schedule节,我们同样使用了一个子节点来描述自动构建工作:

该节点使用了ant关键字,表示该任务使用了ant来进行自动构建任务,anthome属性则指定了ANT工具的具体位置,buildfile属性则指定了ANT进行自动构建所使用的配置文件Build.xml文件的路径。
这样,在CruiseControl决定进行自动构建任务时,会根据设定找到执行所使用到的信息。
   3.4.执行单元测试
CruiseControl可以自动侦测自动构建配置文件中单元测试的任务,并在代码集成完毕将执行结果反馈到相应的模块。
ANT支持xUnit系列的单元测试框架,只需要在配置文件中加入一个target节,即可在自动构建完成之后,进行单元测试工作,有关的详细配置,请参阅ANT官方文档。
  4.CruiseControl的使用
   4.1.启动CruiseControl服务器
通过上一节的配置,CruiseControl系统已经可以正常运行并管理项目了。我们可以通过执行其安装目录下的cruisecontrol.bat文件来启动CruiseControl。控制台显示“BuildQueue    - BuildQueue started”,则说明CruiseControl服务器已成功启动。
在启动服务器之前,我们可以打开cruisecontrol.bat文件并修改倒数第三行相应功能的端口数值来指定服务器占用的系统端口,在本例中我们将-webport指定到了8088端口。
   4.2.管理工程
服务器启动之后,我们就可以在浏览器里访问使用了,如 访问CruiseControlWeb服务器当前CruiseControl系统就会存在一些项目工程,列表中显示了各个工程的相关信息,包括当前状态、上次失败时间、上次成功时间、构建次数等信息,同时Build按钮可以让CruiseControl立即检测工程状态。
点击相应工程名称,则可以进入该工程的详细页面首页,首页清晰明了,主要包括了构建历史信息、最近构建结果、最近构建版本库信息等,该页面可以让我们对当前工程的集成信息一目了然,便于我们对不同的集成结果做出相应的处理。
页面上部的导航按钮可以让我们进入不同信息的查看界面,包括测试结果、XML详细日志文件、状态统计等信息。这些导航按钮根据工程设置的不同扩展任务而有所不同。

  5.工作总结
持续集成为我们带来诸多好处,大量降低集成时间的同时,更重要的是它可以迅速对我们的工作做出反馈,保证了项目的质量。持续集成已经不像以前只存在于理论的名词,只要你愿意你都可以实施持续集成。
当然这些好处是建立在制度的遵循和详尽的单元测试的基础上的,持续集成系统仅仅是我们项目过程中的一个工具而已,正如SCM工具、单元测试一样。工具就是工具,而真正默默起作用的则是项目团队人员之间标准制度的完善与执行。





阅读(1878) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~