对于构建成功或失败时应当给谁发送电子邮件,CruiseControl 在这方面相当灵活。在这里使用的配置将向后一次构建之后向版本控制系统中提交变更的每个开发人员发送电子邮件。持续集成构建可能还包含在其他地方开发的开放源码项目(我将把它们称作 远程项目),这时,当远程项目的开发人员弄糟了什么事的时候,可能并不想让构建系统向他们发送电子邮件。在这种情况下,可以向一个地址发送邮件,这个地址通常是一个邮件列表,如果团队成员经常想知道构建的状态,可以订阅这个邮件列表。这可以让团队负责人尽早发现构建发生了损坏。

清单 4 显示了 meta-config.xml 文件的语法:

清单 4. meta-config.xml 的语法

    <projects>
  <project name="project-name" [interval="seconds"]>
    <svn/>|<cvs/>
    <ant/>|<maven/>
    <clean>goals or targets to clean source tree</clean>
    <build>goals or targets to build</build>
    [<srcdir>source directory</srcdir>]
    [<remote-project/>]
    [<repo-dependency>groupId</repo-dependency>*]
    [<srcdir-dependency>project-name</srcdir-dependency>*]
    [<modificationset>CruiseControl elements</modificationset>]
  </project>*
</projects>


配置文件基本上是个 <project> 元素列表。每个项目都有一个 name 属性。可选的 interval 属性覆盖了 CruiseControl 默认的 5 分钟的构建间隔时间。可以提高远程项目的构建间隔,以减轻它们的版本控制仓库的负担。

利用 <svn/> 或 <cvs/> 空元素,每个项目必须指定自己用来更新源树的版本控制工具。项目还必须指定要使用的构建工具,或者是 <ant/> 或者是 <maven/>。项目还必须包含两个元素,说明要使用哪个目标(或哪个 Maven 的目标)清理和构建源树。对于 Maven,典型的值可能是 <clean>clean</clean> 和 <build>jar:install-snapshot</build>。对于 Ant,可能需要检查 build.xml 文件来找到目标的名称。

假设项目的源在 /home/cruise/src 目录下,根据项目命名,那么 name 属性为 my-project 的项目的源应当在 /home/cruise/src/my-project 中。有些项目拥有大型源树,拥有可以单独构建的子目录;为了处理这种情况,<project> 元素可以包含可选的 <srcdir> 元素,由它指定 /home/cruise/src 目录的特定子目录。例如:

<project name="my-utils">
  <srcdir>big-project/my-utils</srcdir>
  ...


CruiseControl 默认的行为是向上次构建之后签入变更的每个人发送电子邮件。如果是从远程版本控制仓库中拉出源代码,请添加 <remote-project/> 元素,这可以使电子邮件发送到 meta-config.xsl 文件中指定的 developers-address 地址。

项目间的依赖关系

CruiseControl 并不知道项目之间的依赖关系。可能有一个项目生成的 JAR 文件包含的工具类集合是其他许多项目依赖的,但是除非向 CruiseControl 解释这个关系,否则它对这个关系将毫不知情。可以对工具类的项目进行修改,从而造成它被重新构建,但是依赖它的项目不会针对工具类的新版本重新被构建和测试。这可能会降低集成测试的价值,所以出现了对这一问题的一些解决方案。

CruiseControl 为这个目的提供的主要工具是 <filesystem> 元素。可以把这个元素包含在某个项目的 <modificationset> 小节中,这样只要文件系统的某些区域发生了修改,项目会被重新构建。清单 1 中初始的 config.xml 文件采用这种方式,在强制构建目录中的文件发生修改时,触发重新构建。所有的项目都会在文件系统的某个位置创建或更新制品。(例如,作为工具类项目的构建结果,会更新自己产生的 JAR 文件。)可以在 <filesystem> 元素中用这些位置,触发依赖这些制品的项目进行构建。

Ant 在项目构建的方式方面有很高的灵活性,所以不可能确定地指出项目重新构建时会更新文件系统的哪个区域。在这里可以采用的方法是检查每个文件的 build.xml 文件,找出它把构建的制品放在哪儿。然后才能把合适的 <filesystem> 元素添加到依赖这些制品的项目中。简化的 meta-config.xml 文件支持一个 <modificationset> 元素,里面可以包含任何 CruiseControl 元素。它们会被拷贝到 config.xml 文件中。例如,依赖 XStream 的项目可能包含以下内容:

<project name="my-project">
  [...]
  <modificationset>
    <filesystem
          folder="/home/cruise/src/xstream/xstream-SNAPSHOT.jar"/>
  </modificationset>
</project>


Maven 在每个项目上放了一个公共构建过程,所以在 Maven 项目间指定依赖性时,可以提供一些公共规则。项目可以对 Maven 仓库中由指定群组创建的制品指定依赖。更准确地说,包含 <repo-dependency>classworlds</repo-dependency> 可以让项目在 /home/cruise/.maven/repository/classworlds 下的文件发生变化时,重新进行构建。假设 classworlds 构建是在本地 Maven 仓库中安装了制作好的 JAR 文件,那么任何包含这个元素的项目都会自动重新构建。

项目也可以指定对其他项目的构建输出的依赖。包含 <srcdir-dependency>classworlds</srcdir-dependency> 可以让项目在 ${srcdir}/target 下的文件发生变化时重新进行构建,其中 ${srcdir} 是命名项目的源目录。

向构建添加项目

下面是向持续集成构建添加新项目的步骤:

    作为 cruise 用户,把源代码签出到 /home/cruise/src 目录。
    检查是否可以手工构建源树。
    向 meta-config.xml 添加适当的条目。
    运行 ./mkconfig。
    重启 CruiseControl,以便它能从 config.xml 读取新的项目条目。可以用 ps 命令找到运行 CruiseControl 的 JVM 的进程 ID,然后用 kill 命令杀死进程。也可以用 root 用户身份运行 svc -t /service/cruisecontrol,让 daemontools 杀死进程。不管采用哪种方法,supervise 都可以保证 CruiseControl 会被重启。
    可选地,更新 /home/cruise/force-build/${project-name} 的时间戳也可以让 CruiseControl 触发自动重新构建。

CruiseControl Web 应用程序

目前为止运行的 CruiseControl 安装把每个构建的结果用电子邮件消息发送给开发人员。但是开发过程可能包含不是这些消息收件人的人员 —— 例如,项目管理人员或测试人员。CruiseControl 包含一个简单的 Web 应用程序,可以让这些人员监视持续集成构建。