这篇文章介绍的是 CruiseControl,这是一个开放源码软件,可以用它对有多个开发人员参与的软件项目自动进行构建和单元测试。我将解释为什么自动化构建对于成功的开发团队是至关重要的,并一步步介绍运行 CruiseControl 的持续集成系统的配置、安装和维护。
为什么要自动进行构建?
目前的一般实践是使用版本控制系统,例如 CVS 或 Subversion(请参阅参考资料)。当有多个开发人员在同一个系统上工作时,这类协调就至关重要了。另一个正在流行起来的实践是编写单元测试,并把它们作为构建过程的一部分来运行。例如,Maven 这个构建工具就把运行 JUnit 单元测试作为正常构建过程的一部分(请参阅参考资料)。但是采用这些实践仅仅是个开始。它们构成了近几年发展起来的许多轻量和实用软件开发方法的基础。
mozilla.org 上的持续集成从 Mozilla 项目使用的开发方法中,可以学到许多东西,这是以公开方式进行的最大的开发项目之一。Mozilla 团队过程的关键部分,就是保持树的构建,而且他们还记录下了他们采用的实践。他们的一个重要工具就是 tinderbox 系统,它持续地在许多不同的平台上构建和测试源树(请参阅 参考资料 )。
当有许多开发人员在同一个项目上工作时,重要的就是要确保构版本控制系统中代码的最新版本一直被构建……这对于拥有封闭开发团队的项目来说是个好的实践;当开发人员周期性地把自己的工作区与主干同步时,一个不进行构建的源树会继续进行开发,直到能修正它为止。对于开放源码项目,保持主干可以工作是至关重要的。潜在的新开发人员可以在任何时候检出代码,但是如果代码不能构建,新开发人员可能就被挡在了做贡献的队伍之外。
极限编程(XP)方法论主张持续集成 .开发人员应当尽可能频繁地把他们的代码集成进主干 —— 典型的是几小时一次,同时还要确保所有单元测试都能通过。其他敏捷方法论也同意这个建议。
要采用持续集成和单元测试,需要团队接受这些方法和实践,但是这通常还不够。目前的实践依赖手工步骤 —— 集成代码、运行测试、在合适的时间检入代码,这样的实践有可能造成错误。让自动系统来构建代码、运行单元测试,可能是更可靠的解决方案。
配置构建服务器这篇文章剩下的部分将介绍使用 CruiseControl 为 Java 项目配置构建服务器所涉及的步骤,CruiseControl 是一个管理自动构建过程的软件(请参阅参考资料 )。CruiseControl 需要一台可靠的机器,拥有充足的剩余磁盘空间,但并不需要特别快。(需要的是定期构建,但是构建过程本身需要花 2 分钟还是 20 分钟并不是问题。)将要构建的服务器基于 Fedora Core 4,这是一个由 Red Hat 资助的社区开发版的 Linux 发行版(请参阅参考资料 ),所以需要有一些 Unix 经验。这篇文章涉及的主要任务有:
系统的初始配置,以及设置一个运行 CruiseControl 的用户帐户安装 CruiseControl 并配置第一个构建让 CruiseControl 一直运行简化 CruiseControl 配置设置可选的基于浏览器的界面,用来监视 CruiseControl 构建初始配置
第一件事是确保在系统上安装了 Java 的基本开发所需要的全部软件。Fedora Core 4 包含基于 gcj(来自 GNU 编译器集合(gcc)项目的 Java 编译器)的 Java 工具链,但是出于兼容性的原因,最好是安装来自 IBM 或 Sun 的 JDK.最干净的方法是按照 jpackage.org 上的说明(请参阅参考资料 ),构建和安装自己的 Java RPM.Fedora Core 4 自带的 xerces-j2 包构建得不正确,造成 Xalan XSLT 实现不能工作。所以还需要从 Fedora 开发仓库安装更新的 xerces-j2 包(请参阅参考资料 )。
还需要使用其他一些软件:
XMLStarlet,一个有用的命令行程序,用来管理 XML 文档(请参阅参考资料 )。稍后 将用它来简化 CruiseControl 配置文件的维护。
CVS 和 Subversion:需要安装这些工具,以便从构建的源树中下载更新。幸运的是,Fedora Core 4 中包含这两个工具。
要执行这些步骤,必须以 root 登录。首先,下面是系统上应当有的 RPM:
[root@fcvm ~]# ls java-1.4.2-sun-1.4.2.08-1jpp.i586.rpm java-1.4.2-sun-alsa-1.4.2.08-1jpp.i586.rpm java-1.4.2-sun-demo-1.4.2.08-1jpp.i586.rpm java-1.4.2-sun-devel-1.4.2.08-1jpp.i586.rpm java-1.4.2-sun-fonts-1.4.2.08-1jpp.i586.rpm java-1.4.2-sun-jdbc-1.4.2.08-1jpp.i586.rpm java-1.4.2-sun-plugin-1.4.2.08-1jpp.i586.rpm java-1.4.2-sun-src-1.4.2.08-1jpp.i586.rpm xerces-j2-2.6.2-5jpp_2fc.i386.rpm xerces-j2-demo-2.6.2-5jpp_2fc.i386.rpm xerces-j2-javadoc-apis-2.6.2-5jpp_2fc.i386.rpm xerces-j2-javadoc-dom3-2.6.2-5jpp_2fc.i386.rpm xerces-j2-javadoc-impl-2.6.2-5jpp_2fc.i386.rpm xerces-j2-javadoc-other-2.6.2-5jpp_2fc.i386.rpm xerces-j2-javadoc-xni-2.6.2-5jpp_2fc.i386.rpm xerces-j2-scripts-2.6.2-5jpp_2fc.i386.rpm xmlstarlet-1.0.1-1.i586.rpm [root@fcvm ~]#
安装 Java、Xerces、XMLStarlet 和 Subversion 包:
[root@fcvm ~]# rpm -ivh java-1.4.2-sun-1.4.2.08-1jpp.i586.rpm \ java-1.4.2-sun-alsa-1.4.2.08-1jpp.i586.rpm \ java-1.4.2-sun-devel-1.4.2.08-1jpp.i586.rpm \ java-1.4.2-sun-fonts-1.4.2.08-1jpp.i586.rpm \ java-1.4.2-sun-plugin-1.4.2.08-1jpp.i586.rpm \ java-1.4.2-sun-src-1.4.2.08-1jpp.i586.rpm Preparing…… ################################# [100%] 1:java-1.4.2-sun ################################# [ 17%] 2:java-1.4.2-sun-alsa ################################# [ 33%] 3:java-1.4.2-sun-devel ################################# [ 50%] 4:java-1.4.2-sun-fonts ################################# [ 67%] 5:java-1.4.2-sun-plugin ################################# [ 83%] 6:java-1.4.2-sun-src ################################# [100%] [root@fcvm ~]# java -version java version "1.4.2_08" Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_08-b03) Java HotSpot(TM) Client VM (build 1.4.2_08-b03, mixed mode) [root@fcvm ~]# rpm -Uvh xerces-j2-2.6.2-5jpp_2fc.i386.rpm \ xerces-j2-demo-2.6.2-5jpp_2fc.i386.rpm \ xerces-j2-javadoc-apis-2.6.2-5jpp_2fc.i386.rpm \ xerces-j2-javadoc-dom3-2.6.2-5jpp_2fc.i386.rpm \ xerces-j2-javadoc-impl-2.6.2-5jpp_2fc.i386.rpm \ xerces-j2-javadoc-other-2.6.2-5jpp_2fc.i386.rpm \ xerces-j2-javadoc-xni-2.6.2-5jpp_2fc.i386.rpm \ xerces-j2-scripts-2.6.2-5jpp_2fc.i386.rpm Preparing…… ################################# [100%] 1:xerces-j2 ################################# [ 13%] 2:xerces-j2-demo ################################# [ 25%] 3:xerces-j2-javadoc-apis ################################# [ 38%] 4:xerces-j2-javadoc-dom3 ################################# [ 50%] 5:xerces-j2-javadoc-impl ################################# [ 63%] 6:xerces-j2-javadoc-other################################# [ 75%] 7:xerces-j2-javadoc-xni ################################# [ 88%] 8:xerces-j2-scripts ################################# [100%] [root@fcvm ~]# rpm -ivh xmlstarlet-1.0.1-1.i586.rpm Preparing…… ################################# [100%] 1:xmlstarlet ################################# [100%] [root@fcvm ~]# yum install subversion [……] Installed: subversion.i386 0:1.2.3-2.1 Complete! [root@fcvm ~]#
还需要在服务器上创建一个新的用户帐户,由它拥有运行 CruiseControl 时涉及的文件和进程:
[root@fcvm ~]# useradd cruise [root@fcvm ~]# su - cruise [cruise@fcvm ~]$ pwd /home/cruise [cruise@fcvm ~]$
最后,因为将要构建的某些项目要使用 Maven 构建工具,所以需要下载、安装它,并设置适当的环境变量(请参阅参考资料 )。( JAVA_HOME 应当设置为 /usr/lib/jvm/java.)我的习惯是把 Maven 和 CruiseControl 这样的外部包放在叫作 pkg 的目录中。在 Maven 的 Web 站点上有完整的安装说明,所以我在这里就不详细介绍这个步骤了:
[cruise@fcvm ~]$ mkdir pkg [cruise@fcvm ~]$ cd pkg [cruise@fcvm pkg]$ [install Maven]
安装 CruiseControl下一个工作是下载 CruiseControl(请参阅参考资料)并把它安装在 pkg 目录中:
[cruise@fcvm pkg]$ wget -q http://heanet.dl.sourceforge.net/\ sourceforge/cruisecontrol/cruisecontrol-2.2.1.zip [cruise@fcvm pkg]$ unzip cruisecontrol-2.2.1.zip Archive: cruisecontrol-2.2.1.zip creating: cruisecontrol-2.2.1/ creating: cruisecontrol-2.2.1/contrib/ [……] inflating: cruisecontrol-2.2.1/reporting/jsp/webcontent/xsl/testdeta ils.xsl inflating: cruisecontrol-2.2.1/reporting/jsp/webcontent/xsl/unittest s.xsl [cruise@fcvm pkg]$ rm cruisecontrol-2.2.1.zip [cruise@fcvm pkg]$
不需要构建 CruiseControl,因为发行包中包含一个预先构建好的 JAR 文件。
现在可以让第一个自动构建工作了。这里将采用 XStream 项目的源树作为初始示例(请参阅参考资料 )。 稍后您将会学习到如何添加来自本地和远程源代码仓库的更多项目。CruiseControl 从自己的启动目录中叫作 config.xml 的文件中读取要构建的项目的信息。在本文的安装中,这个目录是 /home/cruise.清单 1 显示了一个简单的 config.xml 文件的内容,可以从它开始。要创建它,只要把清单 1 中的文本拷贝到一个新文件就可以了:
清单 1. 构建 XStream 的简单的 CruiseControl config.xml 文件<?xml version="1.0"?> <cruisecontrol> <project name="xstream" buildafterfailed="false"> <listeners> <currentbuildstatuslistener file="log/build/xstream/status.txt"/> </listeners> <modificationset> <filesystem folder="/home/cruise/force-build/xstream"/> <svn LocalWorkingCopy="src/xstream"/> </modificationset> <schedule interval="3600"> <ant antscript="/usr/bin/ant" uselogger="true" antworkingdir="src/xstream" multiple="1" target="library"/> <ant antscript="/usr/bin/ant" uselogger="true" antworkingdir="src/xstream" multiple="5" target="clean library"/> </schedule> <log dir="log/build/xstream"/> <dateformat format="dd/MM/yyyy HH:mm:ss"/> </project> </cruisecontrol>
配置文件向 CruiseControl 提供了关于要构建的每个项目的三部分主要信息:
如何构建项目,在 <schedule> 元素中指定:每 3,600 秒(即每小时)构建项目一次。
用 Ant 进行构建过程。
每进行到第 5 次构建时,清理构建制品(类文件以及前面构建中的类似内容)的源树。
如何检测什么时候 应当 构建项目,在 <modificationset> 元素中指定:用 Subversion( svn )检查源树的本地工作拷贝是否过期。(如果源代码没有变化,就不需要构建。)
检测强制构建目录中叫作 xstream 的文件的时间戳。这样即使源树没有变化,也可以手动强制进行下一次安排的构建。(在这篇文章后面,我将多次谈到可能需要这种手工覆盖。)
对构建的结果要做什么,在 <listeners> 和 <log> 元素中指定:把构建过程的输出放在 log/build/xstream 目录中加了时间戳的文件中。
把构建的整体状态写入这个目录中的一个文件。
现在需要从 XStream 项目的 Subversion 仓库中签出 XStream 源树。为了保持一致,请把所有源树签出为 /home/cruise/src 的子目录,并把 XStream 源树放在 src/xstream 中,就像 config.xml 文件所指定的那样:
[cruise@fcvm pkg]$ cd [cruise@fcvm ~]$ mkdir src [cruise@fcvm ~]$ cd src [cruise@fcvm src]$ svn co https://svn.codehaus.org/\ xstream/trunk/xstream A xstream/LICENSE.txt A xstream/continuous-integration.xml [……] A xstream/build.xml U xstream Checked out revision 614. [cruise@fcvm src]$
然后,设置强制构建子目录:
[cruise@fcvm src]$ cd …… [cruise@fcvm ~]$ mkdir force-build [cruise@fcvm ~]$ touch force-build/xstream [cruise@fcvm ~]$
最后这一步是必需的,因为如果 config.xml 文件的 <filesystem> 元素中指定的文件不存在,CruiseControl 会拒绝启动。
现在构建工作可能没有正常工作,也有可能遗漏了一些依赖项。所以这个时候,应当做一些手动检查,确保能够成功构建 XStream 源树:
[1] [2] [3] 下一页 |