使用 Subversion、Hudson 和 Eclipse 构建持续集成系统
来源: developerWorks
持续集成系统简介
持续集成系统是指持续地编译、测试、检查和部署源代码的系统。
Martin Fowler 对持续集成是这样定义的 :
持续集成是一种软件开发实践,团队开发成员经常集成它们的工作,通常每个成员每天可能会发生多次集成。每次集成都通过自动化的构建(包括编译、发布、自动化测试)来验证,从而尽快地发现集成错误。这个过程可以大大减少集成的问题,从而让团队能够更快的开发内聚的软件。
持续集成有以下几个特点和要求:
- 有统一的源代码库。开发人员基于同一个源代码库进行开发是进行持续集成的一个前提。为了让持续集成系统正确地发挥作用,需要一个源代码管理系统,比如 Subversion。
- 实现了软件构建和测试自动化。使用一些持续集成软件,如 Hudson,自动完成软件的构建和测试。
- 每次代码递交后都会在持续集成服务器上触发一次构建。在开发过程中,如果开发人员本地的编译环境存在差异,就可能会出现其中一个开发人员的修改在他本地验证通过,但提交到版本库后,另外一个开发人员下载到他自己的机器上却无法编译通过。为了避免出现这种情况,需要创建了专门的持续集成服务器,统一编译环境的配置,开发人员的每一次提交都会在持续集成服务器上进行集成和测试。这样就保证开发人员从版本库中获取到的版本完全可以在本地的机器上面可以顺利编译。
- 测试环境要和产品发布的实际环境一致。持续集成的目的就是为了快速集成并验证问题,然后发布。为了保证持续集成的产品最后可以顺利发布,持续集成的测试环境必须和产品实际的运行环境保持一致,这样用户才能拿到真正通过测试检验的产品。
持续集成有下列的好处和优点:
- 减少重复过程,提高工作效率。从代码提交到软件发布的过程包括代码构建、测试、部署等环节,每个环节对于开发工程师而言是费时费力而又没有产出的过程,并且每次代码的修改都会重复这个过程。持续集成系统可以将这些重复的动作都变成自动化的,无需太多人工干预,可以将项目成员从这种重复劳动中解放出来从而投入到其他更有价值的工作中去。
- 提高修复问题的质量,可以随时生成可交付的质量可靠的软件,减少项目风险。我们利用持续集成,可以经常对源码进行修改,并将这些修改及时和其他代码进行集成。一旦发现问题,会在第一时间由开发人员解决,问题会很快得到修复。这种一旦有问题出现,立即修复的模式,由于没有很多问题叠加在一起,修复问题会更加容易,修复的质量也更高。并且可以随时生成可交付的质量可靠的软件。持续集成一天中可以进行多次的集成并做相应的测试,有利于提前及时地发现缺陷,将问题在项目的前期解决,避免了将问题遗留到项目后期,导致不能及时交付软件的风险。
如果没有持续集成,这些问题可能要累积到交付前的集成测试的时候才发现,这时,很多问题交织在一起,使得修复问题更困难,而急于修复这些缺陷又有可能引入新的缺陷,使得修复的质量降低,有可能会导致延迟发布产品,最终可能导致项目失败。 - 增强项目的可见性,建立团队对开发产品的信心。持续集成可以提供一些数据,使我们对项目的进度趋势进行预测并进行有效的决策:首先,我们可以预测趋势。由于经常集成,我们可以看到一些趋势,如构建成功或失败、总体质量以及其它的项目信息。其次,我们可以有效决策。持续集成系统为项目构建状态和质量指标提供了及时的信息,通过其它一些工具还可以报告功能完成度和缺陷率。
由于持续集成可以增强项目的可见性,持续集成可以建立开发团队对开发产品的信心,因为我们可以清楚的知道每一次构建的结果,知道我们对软件的改动造成了哪些影响,结果怎么样。
目前,业界普遍使用的持续集成系统是整合使用 Subversion、Hudson 和 Eclipse。下面概要介绍这三个软件。
- Subversion 是一个自由,开源的版本控制系统。它可以记录每一次文件和目录的修改情况。这样就可以籍此将数据恢复到以前的版本,并可以查看数据的更改细节。
- Hudson 是一个普遍使用的开源的持续集成系统服务器。它很容易配置;具有强大的插件框架,很容易添加特性,可以方便地进行软件自动构建和测试。所以,受到软件开发者的欢迎。它支持 Ant,Maven 等编译工具,可以根据不同的任务采用不同的编译工具,完成构建所需环境配置并自动完成软件的构建。它默认支持 Subversion 这个版本控制软件。它还可以使用 findbugs 进行静态代码检查和执行单元测试脚本,还直接调用自主开发的自动化测试脚本,进行系统和功能测试,充分验证系统功能的完整性和准确性。
- Eclipse 是一个开放源代码的、基于 Java 的可扩展开发平台。它是一个框架和一组服务,用于通过插件组件构建开发环境。
业界普遍使用的方案是,恰当配置 Hudson 从源代码管理系统 Subversion 中读取源代码,之后 Hudson 对其进行持续集成。Eclipse 用来做为 Subversion 源代码管理系统的客户端,用于 程序员开发来使用。为了更好地整合 Subversion 和 Hudson 实现持续集成,通常配置 Hudson 使得一旦有新的 Subversion commit,立刻自动启动 Hudson build job。
在本文中,以 Subversion、Hudson 在 Linux 系统上的配置来举例,叙述构建持续集成系统的过程,并重点讲解如何解决其中会遇到的问题。
构建持续集成系统过程第 1 步:Subversion
构建持续集成系统的第一部分,主要包括 Subversion 的安装,并能通过 Eclipse 成功地访问 Subversion 管理的代码。以下叙述过程。
第一步, 安装 Subversion
从 http://subversion.apache.org/ 下载 Subversion,按照文档的要求在 Linux 上安装 Subversion。
安装完成后,我们可以在一个目录下面,例如 /var/lib/temp/monarch,创建一个 Subversion repository:
#svnadmin create /var/lib/temp/monarch
然后,我们可以在这个空的 repository 里,放置一个 workspace。例如,可以通过把一个从其它 workspace 生成的 dump 文件 load 进这个 repository:
#svnadmin load /var/lib/temp/monarch/ < ~/dumpfile
这样,在 /var/lib/temp/monarch/ 中,就有了那个做 dumpfile 的 workspace。
在这里用到的 dumpfile 文件事先由类似命令 svnadmin dump /var/lib/svn/monarch >dumpfile 从一个已经存在的 workspace dump 生成。
第二步,安装和配置 Subversion server
在 Subversion repository 就绪之后,我们需要一个 Subversion server 来服务这个 repository,使得外界的客户端可以访问这个 repository。
Subversion server 有多种选择,可以选择 svnserve,也可以选择 Apache HTTP server 来作为 Subversion server。为了能够通过 URL 访问 Subversion repository,在本文中,使用 Apache HTTP server 作为 Subversion server。
从 http://httpd.apache.org/ 下载 Apache httpd,并按照文档安装。安装完成后,可以通过执行 /usr/local/apache2/bin/apachectl start 启动 Apache。可以通过执行 /usr/local/apache2/bin/apachectl stop 停止 Apache。
Apache 的主要的配置文件位于 /usr/local/apache2/conf/httpd.conf。在这个文件中,<Location> tag 告诉 Apache 它服务的 Subversion repository 的路径,例如:
<Location /svn/monarch> DAV svn SVNPath /var/lib/svn/monarch
在这个例子中,它服务的 Subversion repository 位于 var/lib/svn/monarch。而访问这个 Subversion repository 的 URL 的后缀是 /svn/monarch。
第三步,在 Eclipse 里安装 Subversion repository plugin.
为了能在 Eclipse 的客户端中访问 Subversion repository,需要在 Eclipse 中安装 Subversion repository plugin。安装的过程如下:
在 Eclipse 的 Help 菜单中,点击 Install New Software…
出现如下的安装软件的窗口:
点击 Add,添加 Subversion repository plugin 的 URL:
在出现的列表中,选择“Subversive SVN Team Provider Plugin”:
然后,一直点击 Next,直至完成软件的安装。
第四步,使用 Eclipse Subversion repository plugin 导入 Subversion repository.
安装完 Subversion repository plugin 以后,可以用它导入 Subversion repository。
在 Eclipse 中,选择 Windows 菜单 → “Open Perspective” → “SVN Repository Exploring”
在“SVN Repositories”内点击右键,New → Repository Location
图 5. Eclipse “New Repository Location” 窗口
在 URL 中填入要导入的 Subversion Repository 的地址。在本文的 Apache HTTP 服务器配置的例子中,URL 形如 http://HOST IP/svn/monarch/trunk, 例如 http://9.37.119.115/svn/monarch/trunk。
然后,点击 Finish。此时,经常会出现提示权限错误的窗口。
下面来详细分析出现这个问题的原因和解决方法:
在通常情况下,一般一个新的 Subversion repository 刚刚建立的时候,这个 repository 目录下面的所有文件的 owner 是登录 Linux 创建这个 repository 的用户,比如 root。这时,通过 Eclipse 的 Subversion 插件来访问 Subversion repository 时,会发生权限错误。Eclipse 客户端通过 Apache httpd 进程,也就是 Subversion server 进程来访问 Subversion repository,而往往运行 Apache httpd 进程的用户没有访问这个 Subversion repository 的权限,因为这个 Subversion repository 是由另外一个用户,比如 root 建立的。
根据造成这个问题的原因,比较好的解决方法可以是把 repository 目录下面的所有文件的 owner/group 改为运行 Subversion server 进程的用户的 owner/group,在本文中,就是运行 Apache httpd 用户的 owner/group。
在这个例子中,我们可以专门创建一个用户 svn(属于 svn 用户组)来运行 Apache httpd 服务器进程。Eclipse 客户端通过这个服务器进程来访问 Subversion respository。既然服务器进程由 svn:svn 来运行,如果我们把 repository 目录下面的所有文件的 owner/group 通过运行 chown 命令变成 svn:svn,服务器进程就可以正常访问 Subversion repository。这样,Eclipse 通过 Subversion server 来访问 Subversion respositoy 就没有权限问题了。
构建持续集成系统过程第 2 步:Hudson
构建持续集成系统过程的第二部分,主要包括安装和配置 Hudson,并很好地整合 Hudson 与 Subversion,做到自动持续集成。
根据前面提到的持续集成系统的特点和要求之三:每次代码递交后都会在持续集成服务器上触发一次构建。我们需要配置系统使得一旦 Subversion repository 有新的代码 commit,立刻自动启动相应的 Hudson build job。这样,就可以做到自动地持续集成 (Automatic Continuous Integration)。
以下详述具体步骤:
第一步,安装 Hudson
从 http://www.hudson-ci.org/ 下载 Hudson。Hudson 的安装方式是把它部署在 Tomcat 上。在本文例子中,Hudson 安装在 /var/lib/hudson。Tomcat 安装在 /usr/local/apache-tomcat-7.0.11。
把 Hudson 部署在 Tomcat 上的方法是把下载的 Hudson.war 拷贝到 Tomcat 安装目录下的 webapps 子目录下面。部署完成后,可以通过启动或停止 Tomcat 来提供或停止 Hudson 服务。
可以通过执行 /usr/local/apache-tomcat-7.0.11/bin/startup.sh 启动 Tomcat。可以通过执行 /usr/local/apache-tomcat-7.0.11/bin/shutdown.sh 停止 Tomcat。
Tomcat 监听 8888 端口。所以,使用 http://HOST IP:8888/hudson/ 来访问 Hudson,例如 http://9.37.119.115:8888/hudson。
第二步,配置 Hudson Jobs
在 Hudson 的主页面上,点击“Manage Hudson”, 然后点击“Configure System”,您就可以做 Hudson 的整体配置。
之后,使用管理员帐号登录,可以点击“New Job”来新建 Job,点击“Configure”可以配置具体的 Job 的信息。
第三步,配置 Hudson 和 Subversion
为了使得一旦 Subversion repository 有新的代码 commit,立刻自动启动 Hudson build job,需要配置 Subversion 中的 post-commit hook。这个文件位于 /var/lib/svn/monarch/hooks 下面。这个目录下面有很多例子文件,如 post-commit.tmpl。我们先把 post-commit.tmpl 文件改名为 post-commit。
在 post-commit 文件中,我们需要打开以下的 URL:
HUDSON_URL/job/JOB_NAME/build?token=TOKEN_NAME 来远程触发 Hudson build job。
这里的 HUDSON_URL 是 Hudson 的 URL,形如:”http://9.37.119.115:8888/hudson”。
JOB_NAME 是想要触发的 Hudosn build job 的名字。TOKEN_NAME,可以在 Hudson Job 的 Configuration 中,“Build Triggers” —> “Trigger builds remotely” —-> “Authentication Token”中指定。在这里指定的 TOKEN_NAME,可以用来通过 URL 远程的触发 Hudson 任务。
如果我们使用 Python 来写 post-commit,可以先 import urllib,然后使用
urllib.urlopen(HUDSON_URL/job/$job_name/build?token=TOKEN_NAME) 来打开 Hudson build job 的 URL。这样,一旦 Subversion repository 有新的代码 commit,它会触发 Hudson build job
结束语
本文简介了持续集成系统,并叙述了通过 Subversion, Hudson 和 Eclipse 构建持续集成系统的过程。在叙述构建过程当中,重点讲解了如何解决其中会遇到的问题。