級別: 中級
Mark Wilkinson, 顧問, Codehaus
2005 年 10 月 24 日
極限編程和敏捷方法建議開發(fā)過程要包含持續(xù)集成和單元測試。支持這些實踐的一個實際方法是設(shè)置一個自動系統(tǒng),每次在源代碼發(fā)生變化時,都自動構(gòu)建和測試源代碼的最新版本。這篇文章將介紹為 Java™ 項目建立基于 Linux™ 的構(gòu)建服務(wù)器時涉及的實際問題。
這篇文章介紹的是CruiseControl,這是一個開放源碼軟件,可以用它對有多個開發(fā)人員參與的軟件項目自動進(jìn)行構(gòu)建和單元測試。我將解釋為什么自動化構(gòu)建對于成功的開發(fā)團(tuán)隊是至關(guān)重要的,并一步步介紹運行 CruiseControl 的持續(xù)集成系統(tǒng)的配置、安裝和維護(hù)。
為什么要自動進(jìn)行構(gòu)建?
目前的一般實踐是使用版本控制系統(tǒng),例如 CVS 或 Subversion(請參閱 參考資料)。當(dāng)有多個開發(fā)人員在同一個系統(tǒng)上工作時,這類協(xié)調(diào)就至關(guān)重要了。另一個正在流行起來的實踐是編寫單元測試,并把它們作為構(gòu)建過程的一部分來運行。例如,Maven 這個構(gòu)建工具就把運行 JUnit 單元測試作為正常構(gòu)建過程的一部分(請參閱 參考資料)。但是采用這些實踐僅僅是個開始。它們構(gòu)成了近幾年發(fā)展起來的許多輕量和實用軟件開發(fā)方法的基礎(chǔ)。
| mozilla.org 上的持續(xù)集成 從 Mozilla 項目使用的開發(fā)方法中,可以學(xué)到許多東西,這是以公開方式進(jìn)行的最大的開發(fā)項目之一。Mozilla 團(tuán)隊過程的關(guān)鍵部分,就是保持樹的構(gòu)建,而且他們還記錄下了他們采用的實踐。他們的一個重要工具就是 tinderbox 系統(tǒng),它持續(xù)地在許多不同的平臺上構(gòu)建和測試源樹(請參閱 參考資料)。 | |
當(dāng)有許多開發(fā)人員在同一個項目上工作時,重要的就是要確保構(gòu)版本控制系統(tǒng)中代碼的最新版本一直被構(gòu)建。。這對于擁有封閉開發(fā)團(tuán)隊的項目來說是個好的實踐;當(dāng)開發(fā)人員周期性地把自己的工作區(qū)與主干同步時,一個不進(jìn)行構(gòu)建的源樹會繼續(xù)進(jìn)行開發(fā),直到能修正它為止。對于開放源碼項目,保持主干可以工作是至關(guān)重要的。潛在的新開發(fā)人員可以在任何時候檢出代碼,但是如果代碼不能構(gòu)建,新開發(fā)人員可能就被擋在了做貢獻(xiàn)的隊伍之外。
極限編程(XP)方法論主張 持續(xù)集成。開發(fā)人員應(yīng)當(dāng)盡可能頻繁地把他們的代碼集成進(jìn)主干 —— 典型的是幾小時一次,同時還要確保所有單元測試都能通過。其他敏捷方法論也同意這個建議。
要采用持續(xù)集成和單元測試,需要團(tuán)隊接受這些方法和實踐,但是這通常還不夠。目前的實踐依賴手工步驟 —— 集成代碼、運行測試、在合適的時間檢入代碼,這樣的實踐有可能造成錯誤。讓自動系統(tǒng)來構(gòu)建代碼、運行單元測試,可能是更可靠的解決方案。
配置構(gòu)建服務(wù)器
這篇文章剩下的部分將介紹使用 CruiseControl 為 Java 項目配置構(gòu)建服務(wù)器所涉及的步驟,CruiseControl 是一個管理自動構(gòu)建過程的軟件(請參閱 參考資料)。CruiseControl 需要一臺可靠的機(jī)器,擁有充足的剩余磁盤空間,但并不需要特別快。(需要的是定期構(gòu)建,但是構(gòu)建過程本身需要花 2分鐘還是 20 分鐘并不是問題。)將要構(gòu)建的服務(wù)器基于 Fedora Core 4,這是一個由 Red Hat 資助的社區(qū)開發(fā)版的 Linux發(fā)行版(請參閱 參考資料),所以需要有一些 Unix 經(jīng)驗。這篇文章涉及的主要任務(wù)有:
- 系統(tǒng)的初始配置,以及設(shè)置一個運行 CruiseControl 的用戶帳戶
- 安裝 CruiseControl 并配置第一個構(gòu)建
- 讓 CruiseControl 一直運行
- 簡化 CruiseControl 配置
- 設(shè)置可選的基于瀏覽器的界面,用來監(jiān)視 CruiseControl 構(gòu)建
初始配置
第一件事是確保在系統(tǒng)上安裝了 Java 的基本開發(fā)所需要的全部軟件。Fedora Core 4 包含基于 gcj(來自 GNU編譯器集合(gcc)項目的 Java 編譯器)的 Java 工具鏈,但是出于兼容性的原因,最好是安裝來自 IBM 或 Sun 的JDK。最干凈的方法是按照 jpackage.org 上的說明(請參閱 參考資料),構(gòu)建和安裝自己的 Java RPM。Fedora Core 4 自帶的 xerces-j2 包構(gòu)建得不正確,造成 Xalan XSLT 實現(xiàn)不能工作。所以還需要從 Fedora 開發(fā)倉庫安裝更新的 xerces-j2 包(請參閱 參考資料)。
還需要使用其他一些軟件:
- XMLStarlet,一個有用的命令行程序,用來管理 XML 文檔(請參閱 參考資料)。稍后 將用它來簡化 CruiseControl 配置文件的維護(hù)。
- CVS 和 Subversion:需要安裝這些工具,以便從構(gòu)建的源樹中下載更新。幸運的是,F(xiàn)edora Core 4 中包含這兩個工具。
要執(zhí)行這些步驟,必須以 root 登錄。首先,下面是系統(tǒng)上應(yīng)當(dāng)有的 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 ~]# |
還需要在服務(wù)器上創(chuàng)建一個新的用戶帳戶,由它擁有運行 CruiseControl 時涉及的文件和進(jìn)程:
[root@fcvm ~]# useradd cruise [root@fcvm ~]# su - cruise [cruise@fcvm ~]$ pwd /home/cruise [cruise@fcvm ~]$ |
最后,因為將要構(gòu)建的某些項目要使用 Maven 構(gòu)建工具,所以需要下載、安裝它,并設(shè)置適當(dāng)?shù)沫h(huán)境變量(請參閱 參考資料)。(JAVA_HOME
應(yīng)當(dāng)設(shè)置為 /usr/lib/jvm/java。)我的習(xí)慣是把 Maven 和 CruiseControl 這樣的外部包放在叫作 pkg 的目錄中。在 Maven 的 Web 站點上有完整的安裝說明,所以我在這里就不詳細(xì)介紹這個步驟了:
[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]$ |
不需要構(gòu)建 CruiseControl,因為發(fā)行包中包含一個預(yù)先構(gòu)建好的 JAR 文件。
現(xiàn)在可以讓第一個自動構(gòu)建工作了。這里將采用 XStream 項目的源樹作為初始示例(請參閱 參考資料)。稍后您將會學(xué)習(xí)到如何添加來自本地和遠(yuǎn)程源代碼倉庫的更多項目。CruiseControl 從自己的啟動目錄中叫作 config.xml的文件中讀取要構(gòu)建的項目的信息。在本文的安裝中,這個目錄是 /home/cruise。清單 1 顯示了一個簡單的 config.xml文件的內(nèi)容,可以從它開始。要創(chuàng)建它,只要把清單 1 中的文本拷貝到一個新文件就可以了:
清單 1. 構(gòu)建 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 提供了關(guān)于要構(gòu)建的每個項目的三部分主要信息:
- 如何構(gòu)建項目,在
<schedule>
元素中指定: - 每 3,600 秒(即每小時)構(gòu)建項目一次。
- 用 Ant 進(jìn)行構(gòu)建過程。
- 每進(jìn)行到第 5 次構(gòu)建時,清理構(gòu)建制品(類文件以及前面構(gòu)建中的類似內(nèi)容)的源樹。
- 如何檢測什么時候 應(yīng)當(dāng) 構(gòu)建項目,在
<modificationset>
元素中指定: - 用 Subversion(
svn
)檢查源樹的本地工作拷貝是否過期。(如果源代碼沒有變化,就不需要構(gòu)建。) - 檢測強(qiáng)制構(gòu)建目錄中叫作 xstream 的文件的時間戳。這樣即使源樹沒有變化,也可以手動強(qiáng)制進(jìn)行下一次安排的構(gòu)建。(在這篇文章后面,我將多次談到可能需要這種手工覆蓋。)
- 對構(gòu)建的結(jié)果要做什么,在
<listeners>
和 <log>
元素中指定: - 把構(gòu)建過程的輸出放在 log/build/xstream 目錄中加了時間戳的文件中。
- 把構(gòu)建的整體狀態(tài)寫入這個目錄中的一個文件。
現(xiàn)在需要從 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]$ |
然后,設(shè)置強(qiáng)制構(gòu)建子目錄:
[cruise@fcvm src]$ cd .. [cruise@fcvm ~]$ mkdir force-build [cruise@fcvm ~]$ touch force-build/xstream [cruise@fcvm ~]$ |
最后這一步是必需的,因為如果 config.xml 文件的 <filesystem>
元素中指定的文件不存在,CruiseControl 會拒絕啟動。
現(xiàn)在構(gòu)建工作可能沒有正常工作,也有可能遺漏了一些依賴項。所以這個時候,應(yīng)當(dāng)做一些手動檢查,確保能夠成功構(gòu)建 XStream 源樹:
| 構(gòu)建 XStream 有問題? 有可能發(fā)現(xiàn) XStream 構(gòu)建失敗,報告 org.w3c.dom.TypeInfo 的 NoClassDefFoundError 錯誤。實際上,構(gòu)建幾乎就成功了,但是 XStream 的 Ant 構(gòu)建腳本用 <junitreport> 任務(wù)生成 JUnit 測試結(jié)果的 HTML 報告。這個工作使用 XSLT 轉(zhuǎn)換,所以觸發(fā)了前面我在 初始配置 一節(jié)中提到過的 xerces-j2 包中的 bug。 | |
[cruise@fcvm ~]$ cd src/xstream [cruise@fcvm xstream]$ ant library Buildfile: build.xml compile: [mkdir] Created dir: /home/cruise/src/xstream/build/java [echo] Java version used for compile: 1.4.2_08 [javac] Compiling 150 source files to /home/cruise/src/xstream/bui ld/java [...] library: BUILD SUCCESSFUL Total time: 1 minute 44 seconds [cruise@fcvm xstream]$ |
而且,在添加新項目時,需要找到用來構(gòu)建源和清理其中制品的目標(biāo)的名稱。必須把這個信息放在 config.xml 文件中。
現(xiàn)在應(yīng)當(dāng)做好準(zhǔn)備,可以讓 CruiseControl 自動執(zhí)行這個構(gòu)建了。只要啟動 CruiseControl,然后坐下來等待就可以了:
[cruise@fcvm xstream]$ cd [cruise@fcvm ~]$ java -jar pkg/cruisecontrol-2.2.1/main/dist/cruisecontrol.jar [cc]Aug-24 20:09:31 Main - CruiseControl Version 2.2.1 [cc]Aug-24 20:09:32 trolController- projectName = [xstream] [cc]Aug-24 20:09:32 trolController- No previously serialized project f ound: /home/cruise/xstream [cc]Aug-24 20:09:32 Project - Project xstream: reading settings from config file [/home/cruise/config.xml] [cc]Aug-24 20:09:32 BuildQueue - BuildQueue started [cc]Aug-24 20:09:32 Project - Project xstream starting [cc]Aug-24 20:09:32 Project - Project xstream: idle [cc]Aug-24 20:09:32 Project - Project xstream started [cc]Aug-24 20:09:32 Project - Project xstream: next build in 1 hours [cc]Aug-24 20:09:32 Project - Project xstream: waiting for next time to build [cc]Aug-24 21:09:33 Project - Project xstream: in build queue [cc]Aug-24 21:09:33 BuildQueue - now adding to the thread queue: xs tream [cc]Aug-24 21:09:33 Project - Project xstream: reading settings from config file [/home/cruise/config.xml] [cc]Aug-24 21:09:33 Project - Project xstream: bootstrapping [cc]Aug-24 21:09:33 Project - Project xstream: checking for mod ifications [cc]Aug-24 21:09:59 Project - Project xstream: No modifications found, build not necessary. [cc]Aug-24 21:09:59 Project - Project xstream: Building anyway, since build was explicitly forced. [cc]Aug-24 21:09:59 Project - Project xstream: now building Buildfile: build.xml [cc]Aug-24 21:11:29 Project - Project xstream: merging accumula ted log files [cc]Aug-24 21:11:30 Project - Project xstream: build successful [cc]Aug-24 21:11:30 Project - Project xstream: publishing build results [cc]Aug-24 21:11:30 Project - Project xstream: idle [cc]Aug-24 21:11:30 Project - Project xstream: next build in 1 hours [cc]Aug-24 21:11:30 Project - Project xstream: waiting for next time to build [stop CruiseControl using Ctrl-C] [cruise@fcvm ~]$ |
讓 CruiseControl 一直運行
現(xiàn)在是讓 CruiseControl 運行了,但是還不能讓它在沒人參與的情況下運行。它目前在一個終端窗口中運行,所以需要讓 cruise 用戶永遠(yuǎn)登錄,才能保持它一直運行。終端還是控制程序的唯一方式:可以按下 Ctrl+C停止 CruiseControl,并再次運行程序重新啟動它。除非使用虛擬網(wǎng)絡(luò)計算(VNC)會話或類似的東西,否則就不能遠(yuǎn)程地做上面這些事。如果CruiseControl(或者JVM)崩潰,就需要手動地重啟它。而且當(dāng)重新啟動機(jī)器時,也需要手動地建立新會話、創(chuàng)建終端、再次啟動程序,CruiseControl才能重啟。所以需要讓 CruiseControl 作為一個服務(wù)運行,或者用 Unix 的術(shù)語來說,作為一個 守護(hù)程序 運行。
讓程序在 Linux 下持續(xù)運行的方法有許多種。最常用的方法可能是把合適的腳本掛上 init
系統(tǒng)初始化進(jìn)程,在系統(tǒng)啟動時啟動程序。這些腳本可以啟動和停止程序,但是不能在程序出現(xiàn)故障時自動重啟程序。
我用的方法 I 是下載并安裝 Daniel J. Bernstein 的 daemontools
(請參閱 參考資料)。這是一個小的程序包,負(fù)責(zé)啟動一組服務(wù)并保持這些服務(wù)一直運行。要執(zhí)行自己的 daemontools
安裝,需要登錄為 root:
[root@fcvm ~]# mkdir -p /package [root@fcvm ~]# chmod 1755 /package [root@fcvm ~]# cd /package [root@fcvm package]# wget -q http://cr.yp.to/ daemontools/daemontools-0.76.tar.gz [root@fcvm package]# gunzip daemontools-0.76.tar.gz [root@fcvm package]# tar -xpf daemontools-0.76.tar [root@fcvm package]# rm daemontools-0.76.tar rm: remove regular file ‘daemontools-0.76.tar‘? y [root@fcvm package]# |
要讓這個包能夠在 Fedora Core 4 上干凈地構(gòu)建,必須對包的 C 源代碼稍做調(diào)整。請用文本編輯器,把 src/error.h 的第 6 行從 extern int errno;
改成 #include <errno.h>
。下面是使用 ed
的處理方法:
[root@fcvm package]# cd admin/daemontools-0.76 [root@fcvm daemontools-0.76]# ed src/error.h 595 6 extern int errno; c #include <errno.h> . wq 596 [root@fcvm daemontools-0.76]# |
現(xiàn)在可以完成安裝了:
[root@fcvm daemontools-0.76]# package/install Linking ./src/* into ./compile... Compiling everything in ./compile... [...] Creating /service... Adding svscanboot to inittab... init should start svscan now. [root@fcvm daemontools-0.76]# ps -ef | grep svs root 21160 1 0 16:09 ? 00:00:00 /bin/sh /command/svsca nboot root 21162 21160 0 16:09 ? 00:00:00 svscan /service root 21173 20051 0 16:10 pts/1 00:00:00 grep svs [root@fcvm daemontools-0.76]# |
daemontools
提供了叫作 svscan
的守護(hù)進(jìn)程,它負(fù)責(zé)管理服務(wù)集合。每個服務(wù)都由 /service 目錄中的一個目錄代表,所以需要在這里為 CruiseControl 服務(wù)創(chuàng)建一個目錄。對于 /service 中的每個子目錄,svscan
都啟動一個子進(jìn)程,運行 supervise
程序。
supervise
是負(fù)責(zé)管理 CruiseControl 這樣的獨立服務(wù)的程序。它創(chuàng)建子進(jìn)程,運行服務(wù)子目錄中的 run
(例如 /service/cruisecontrol/run),從而啟動服務(wù)。如果子進(jìn)程中止,supervise
會重新啟動它。supervise
也可以向子進(jìn)程發(fā)送信號,停止或重新啟動子進(jìn)程。
daemontools
還提供了兩個機(jī)制,負(fù)責(zé)處理它管理的服務(wù)的日志記錄。首先,叫作 readproctitle
的程序捕捉寫入標(biāo)準(zhǔn)錯誤流(在 Java 世界中,是 System.err
)的輸出并把輸出拷貝到一個小緩沖區(qū)中,這個小緩沖區(qū)是 ps
命令顯示的進(jìn)程標(biāo)題的一部分:
[root@fcvm daemontools-0.76]# ps -ef | grep proctitle root 25040 25037 0 20:58 ? 00:00:00 readproctitle service errors: .............................................................. ...................................................................... ...................................................................... ...................................................................... ...................................................................... .......................................................... root 25047 24006 0 20:59 pts/1 00:00:00 grep proctitle [root@fcvm daemontools-0.76]# |
在啟動時,緩沖區(qū)被初始化為包含點號,但是在出現(xiàn)錯誤時就被錯誤信息替代。這個機(jī)制對于少量信息(例如關(guān)鍵錯誤信息)來說很好。但是緩沖區(qū)尺寸小造成它不適合更大數(shù)量的日志信息,而且記錄的信息不能保存到磁盤也使得難以分析一段時間內(nèi)的性能。daemontools
提供了第二種機(jī)制 —— multilog
程序,它負(fù)責(zé)這種大量日志。第二種機(jī)制在命令行參數(shù)輸出的指令控制下,把自己標(biāo)準(zhǔn)輸入中的行寫入日志文件。它包含對日志輪轉(zhuǎn)的控制,日志輪轉(zhuǎn)可以保持定量的日志信息,以使存儲空間不會耗盡。例如,multilog /home/cruise/log
這個簡單的命令就可以把信息記錄到 /home/cruise/log 目錄中的文件,當(dāng)日志文件的尺寸達(dá)到 99,999 個字節(jié)時就輪轉(zhuǎn)日志文件,并保持 10 個舊的日志文件。
multilog
也由 supervise
管理,就像其他服務(wù)一樣。在 svsccan
發(fā)現(xiàn)的每個目錄中,它都會查找叫作 log 的子目錄,并創(chuàng)建一個 supervise
進(jìn)程來管理這個目錄下 run
腳本的執(zhí)行。它還安排一個管道,把主服務(wù)的標(biāo)準(zhǔn)輸出作為日志進(jìn)程的標(biāo)準(zhǔn)輸入。
那么,要讓 daemontools
管理 CruiseControl,需要做什么呢?必須為這個服務(wù)和它的 multilog
伙伴創(chuàng)建目錄結(jié)構(gòu)。還必須創(chuàng)建它們各自的 run
腳本,并為日志文件創(chuàng)建目錄。開始時,把服務(wù)目錄命名為 .cruisecontrol。前導(dǎo)點號會讓 svscan
忽略這個目錄,從而可以在第一次啟動服務(wù)之前進(jìn)行設(shè)置:
[cruise@fcvm ~]$ mkdir -p log/cruisecontrol [cruise@fcvm ~]$ su - Password: [enter root password] [root@fcvm ~]# cd /service [root@fcvm service]# mkdir .cruisecontrol [root@fcvm service]# cd .cruisecontrol [root@fcvm .cruisecontrol]# mkdir log [root@fcvm .cruisecontrol]# |
然后,創(chuàng)建叫作 env 的目錄。要用這個目錄的內(nèi)容設(shè)置 CruiseControl 的環(huán)境變量以及它要啟動的其他進(jìn)程。在這里要確保 JAVA_HOME
有合適的值。在這里還要設(shè)置將要使用的構(gòu)建工具需要的環(huán)境變量,例如 MAVEN_HOME
。
[root@fcvm .cruisecontrol]# mkdir env [root@fcvm .cruisecontrol]# cd env [root@fcvm env]# echo /usr/lib/jvm/java >JAVA_HOME [root@fcvm env]# echo /home/cruise/pkg/maven-1.0.2 >MAVEN_HOME [root@fcvm env]# ls JAVA_HOME MAVEN_HOME [root@fcvm env]# cd .. [root@fcvm .cruisecontrol]# |
清單 2 顯示了 /service/cruisecontrol/run 腳本:
清單 2. /service/cruisecontrol/run 的內(nèi)容 #!/bin/sh svc=`pwd` cd /home/cruise exec 2>&1 exec setuidgid cruise envdir ${svc}/env java -jar pkg/cruisecontrol-2.2.1/main/dist/cruisecontrol.jar |
這個腳本相當(dāng)簡單。它執(zhí)行以下這些步驟:
- 保存服務(wù)目錄的名稱(在這個示例中是 /service/cruisecontrol)留待后用。
- 把當(dāng)前目錄變?yōu)?/home/cruise。
- 讓標(biāo)準(zhǔn)錯誤流寫入到
multilog
進(jìn)程的管道,這個管道已經(jīng)連接到了標(biāo)準(zhǔn)輸出流。 - 啟動 JVM,運行 CruiseControl,以 cruise 這個用戶身份運行進(jìn)程,并根據(jù) /service/cruisecontrol/env 目錄中創(chuàng)建的文件設(shè)置環(huán)境。
清單 3 演示了 /service/cruisecontrol/log/run 腳本,它更簡單。它以 cruise 用戶的身份運行 multilog
:
清單 3. /service/cruisecontrol/log/run 的內(nèi)容 #!/bin/sh exec setuidgid cruise multilog /home/cruise/log/cruisecontrol |
請注意,必須使用 chmod
把兩個腳本變成可執(zhí)行的。而且,這兩個腳本都要小心地使用 exec
外殼命令,這個命令用一個程序替代另一個程序,但是沒有創(chuàng)建新進(jìn)程。這一點很重要,因為 supervise
只能管理自己的直接子進(jìn)程。如果沒有使用 exec
,那么 JVM 會作為執(zhí)行 run 腳本的外殼的一個子進(jìn)程啟動。如果向 supervise
發(fā)送了殺死其子進(jìn)程的信息,那么外殼會接收到信號并退出,但是 JVM 會繼續(xù)運行,從而變成孤兒。supervise
并不會知道這一點,所以可能會接著啟動守護(hù)程序的第二個拷貝 —— 這并不是想要的結(jié)果。
在設(shè)置好服務(wù)目錄之后,可以把它改名,刪除前導(dǎo)點號。然后 svscan
就會自動啟動 CruiseControl,它的輸出也會出現(xiàn)在日志文件中:
[root@fcvm .cruisecontrol]# cd .. [root@fcvm service]# mv .cruisecontrol cruisecontrol [root@fcvm service]# cat /home/cruise/log/cruisecontrol/current [cc]Aug-24 21:45:45 Main - CruiseControl Version 2.2.1 [cc]Aug-24 21:45:46 trolController- projectName = [xstream] [cc]Aug-24 21:45:46 Project - Project xstream: reading settings from config file [/home/cruise/config.xml] [cc]Aug-24 21:45:47 BuildQueue - BuildQueue started [cc]Aug-24 21:45:47 Project - Project xstream starting [cc]Aug-24 21:45:47 Project - Project xstream: idle [cc]Aug-24 21:45:47 Project - Project xstream started [cc]Aug-24 21:45:47 Project - Project xstream: next build in 1 hours [cc]Aug-24 21:45:47 Project - Project xstream: waiting for next time to build [root@fcvm service]# |
簡化 CruiseControl 的配置
現(xiàn)在已經(jīng)讓 CruiseControl 自動運行在一個很好的受控環(huán)境中。下面要做的就是向配置中添加自己的項目。正如所料,config.xml文件中的項目看起來非常相似,不同之處只是要用哪個工具來構(gòu)建項目的細(xì)節(jié)??梢栽谖谋揪庉嬈髦杏每截愓迟N的方式手工維護(hù) config.xml文件,但是一種更少出錯的技術(shù)是使用 XSLT 樣式表從更簡單的 XML 文檔生成 config.xml文件。實現(xiàn)這個方案的文件集合已經(jīng)合成了一個可以下載的壓縮 tar 文件(請參閱 下載)。請解壓縮這些文件到 /home/cruise 目錄:
[cruise@fcvm ~]$ ls config.xml force-build pkg xstream.ser cruisecontrol.log log src [cruise@fcvm ~]$ tar xvzf [...]/simple-cc.tar.gz meta-config-params.xsl meta-config.xsl meta-config.xml mkconfig [cruise@fcvm ~]$ ls config.xml meta-config-params.xsl pkg cruisecontrol.log meta-config.xml src force-build meta-config.xsl xstream.ser log mkconfig [cruise@fcvm ~]$ |
簡化的配置文件名為 meta-config.xml。這個文件要用 meta-config.xsl 樣式表進(jìn)行變換,生成 CruiseControl 的 config.xml 文件。叫作 mkconfig
的簡單腳本用早先安裝的 XMLStarlet 工具執(zhí)行轉(zhuǎn)換操作。請運行 mkconfig
重新生成 CruiseControl 的 config.xml 文件。
構(gòu)建監(jiān)視
前面開始的簡單 CruiseControl配置對于讓第一個構(gòu)建工作來說足夠了,但是對于監(jiān)視構(gòu)建過程來說還不夠。最常見的需求是把集成構(gòu)建的結(jié)果通過電子郵件發(fā)送給相關(guān)開發(fā)人員。meta-config.xsl 樣式表生成發(fā)送電子郵件消息的配置,但是要做到這一點,它需要一些本地環(huán)境變量的信息。它必須知道的許多變量要從meta-config-params.xsl 文件讀??;在開始之前應(yīng)該根據(jù)實際情況修改這個文件。這個文件中的設(shè)置如下所示:
- home :構(gòu)建進(jìn)程的主目錄。如果采用的是這篇文章中描述的目錄布局,那么默認(rèn)設(shè)置就可以了。
- cruisecontrol-home :CruiseControl 發(fā)行包解壓后所在的目錄。同樣,默認(rèn)設(shè)置應(yīng)當(dāng)就可以了。
- ant-home :Ant 的安裝目錄。要使用 Fedora Core 4 自帶的 Ant,應(yīng)當(dāng)把這個值設(shè)為 /usr。
- maven-home :Maven 的安裝目錄(如果需要用它的話)。默認(rèn)值假設(shè)把 Maven 解壓縮到 /home/cruise/pkg 目錄。
- return-address :CruiseControl 構(gòu)建電子郵件的返回電子郵件地址。
- return-name :構(gòu)建電子郵件返回地址的名稱。
- developers-address :除了上次成功構(gòu)建之后進(jìn)行過提交的開發(fā)人員之外,應(yīng)當(dāng)總是得到構(gòu)建電子郵件拷貝的一個電子郵件地址。
對于構(gòu)建成功或失敗時應(yīng)當(dāng)給誰發(fā)送電子郵件,CruiseControl 在這方面相當(dāng)靈活。在這里使用的配置將向最后一次構(gòu)建之后向版本控制系統(tǒng)中提交變更的每個開發(fā)人員發(fā)送電子郵件。持續(xù)集成構(gòu)建可能還包含在其他地方開發(fā)的開放源碼項目(我將把它們稱作 遠(yuǎn)程項目),這時,當(dāng)遠(yuǎn)程項目的開發(fā)人員弄糟了什么事的時候,可能并不想讓構(gòu)建系統(tǒng)向他們發(fā)送電子郵件。在這種情況下,可以向一個地址發(fā)送郵件,這個地址通常是一個郵件列表,如果團(tuán)隊成員經(jīng)常想知道構(gòu)建的狀態(tài),可以訂閱這個郵件列表。這可以讓團(tuán)隊負(fù)責(zé)人盡早發(fā)現(xiàn)構(gòu)建發(fā)生了損壞。
清單 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 默認(rèn)的 5 分鐘的構(gòu)建間隔時間??梢蕴岣哌h(yuǎn)程項目的構(gòu)建間隔,以減輕它們的版本控制倉庫的負(fù)擔(dān)。
利用 <svn/>
或 <cvs/>
空元素,每個項目必須指定自己用來更新源樹的版本控制工具。項目還必須指定要使用的構(gòu)建工具,或者是 <ant/>
或者是 <maven/>
。項目還必須包含兩個元素,說明要使用哪個目標(biāo)(或哪個 Maven 的目標(biāo))清理和構(gòu)建源樹。對于 Maven,典型的值可能是 <clean>clean</clean>
和 <build>jar:install-snapshot</build>
。對于 Ant,可能需要檢查 build.xml 文件來找到目標(biāo)的名稱。
假設(shè)項目的源在 /home/cruise/src 目錄下,根據(jù)項目命名,那么 name
屬性為 my-project
的項目的源應(yīng)當(dāng)在 /home/cruise/src/my-project 中。有些項目擁有大型源樹,擁有可以單獨構(gòu)建的子目錄;為了處理這種情況,<project>
元素可以包含可選的 <srcdir>
元素,由它指定 /home/cruise/src 目錄的特定子目錄。例如:
<project name="my-utils"> <srcdir>big-project/my-utils</srcdir> ... |
CruiseControl 默認(rèn)的行為是向上次構(gòu)建之后簽入變更的每個人發(fā)送電子郵件。如果是從遠(yuǎn)程版本控制倉庫中拉出源代碼,請?zhí)砑?<remote-project/>
元素,這可以使電子郵件發(fā)送到 meta-config.xsl 文件中指定的 developers-address
地址。
項目間的依賴關(guān)系
CruiseControl并不知道項目之間的依賴關(guān)系??赡苡幸粋€項目生成的 JAR 文件包含的工具類集合是其他許多項目依賴的,但是除非向 CruiseControl解釋這個關(guān)系,否則它對這個關(guān)系將毫不知情??梢詫ぞ哳惖捻椖窟M(jìn)行修改,從而造成它被重新構(gòu)建,但是依賴它的項目不會針對工具類的新版本重新被構(gòu)建和測試。這可能會降低集成測試的價值,所以出現(xiàn)了對這一問題的一些解決方案。
CruiseControl 為這個目的提供的主要工具是 <filesystem>
元素。可以把這個元素包含在某個項目的 <modificationset>
小節(jié)中,這樣只要文件系統(tǒng)的某些區(qū)域發(fā)生了修改,項目就會被重新構(gòu)建。清單 1 中初始的 config.xml 文件就采用這種方式,在強(qiáng)制構(gòu)建目錄中的文件發(fā)生修改時,觸發(fā)重新構(gòu)建。所有的項目都會在文件系統(tǒng)的某個位置創(chuàng)建或更新制品。(例如,作為工具類項目的構(gòu)建結(jié)果,會更新自己產(chǎn)生的 JAR 文件。)可以在 <filesystem>
元素中用這些位置,觸發(fā)依賴這些制品的項目進(jìn)行構(gòu)建。
Ant 在項目構(gòu)建的方式方面有很高的靈活性,所以不可能確定地指出項目重新構(gòu)建時會更新文件系統(tǒng)的哪個區(qū)域。在這里可以采用的唯一方法就是檢查每個文件的 build.xml 文件,找出它把構(gòu)建的制品放在哪兒。然后才能把合適的 <filesystem>
元素添加到依賴這些制品的項目中。簡化的 meta-config.xml 文件支持一個 <modificationset>
元素,里面可以包含任何 CruiseControl 元素。它們會被拷貝到 config.xml 文件中。例如,依賴 XStream 的項目可能包含以下內(nèi)容:
<project name="my-project"> [...] <modificationset> <filesystem folder="/home/cruise/src/xstream/xstream-SNAPSHOT.jar"/> </modificationset> </project> |
Maven 在每個項目上放了一個公共構(gòu)建過程,所以在 Maven 項目間指定依賴性時,可以提供一些公共規(guī)則。項目可以對 Maven 倉庫中由指定群組創(chuàng)建的制品指定依賴。更準(zhǔn)確地說,包含 <repo-dependency>classworlds</repo-dependency>
可以讓項目在 /home/cruise/.maven/repository/classworlds 下的文件發(fā)生變化時,重新進(jìn)行構(gòu)建。假設(shè) classworlds
構(gòu)建是在本地 Maven 倉庫中安裝了制作好的 JAR 文件,那么任何包含這個元素的項目都會自動重新構(gòu)建。
項目也可以指定對其他項目的構(gòu)建輸出的依賴。包含 <srcdir-dependency>classworlds</srcdir-dependency>
可以讓項目在 ${srcdir}/target 下的文件發(fā)生變化時重新進(jìn)行構(gòu)建,其中 ${srcdir} 是命名項目的源目錄。
向構(gòu)建添加項目
下面是向持續(xù)集成構(gòu)建添加新項目的步驟:
- 作為 cruise 用戶,把源代碼簽出到 /home/cruise/src 目錄。
- 檢查是否可以手工構(gòu)建源樹。
- 向 meta-config.xml 添加適當(dāng)?shù)臈l目。
- 運行
./mkconfig
。 - 重啟 CruiseControl,以便它能從 config.xml 讀取新的項目條目??梢杂?
ps
命令找到運行 CruiseControl 的 JVM 的進(jìn)程 ID,然后用 kill
命令殺死進(jìn)程。也可以用 root 用戶身份運行 svc -t /service/cruisecontrol
,讓 daemontools
殺死進(jìn)程。不管采用哪種方法,supervise
都可以保證 CruiseControl 會被重啟。 - 可選地,更新 /home/cruise/force-build/${project-name} 的時間戳也可以讓 CruiseControl 觸發(fā)自動重新構(gòu)建。
CruiseControl Web 應(yīng)用程序
目前為止運行的 CruiseControl 安裝把每個構(gòu)建的結(jié)果用電子郵件消息發(fā)送給開發(fā)人員。但是開發(fā)過程可能包含不是這些消息收件人的人員 ——例如,項目管理人員或測試人員。CruiseControl 包含一個簡單的 Web 應(yīng)用程序,可以讓這些人員監(jiān)視持續(xù)集成構(gòu)建。
CruiseControl Web 應(yīng)用程序在 Apache Tomcat 應(yīng)用程序服務(wù)器中運行,使用的是包含在 Fedora Core 4 發(fā)行版中的拷貝。需要安裝 tomcat5
和 tomcat5-admin-webapps
包:
[root@fcvm ~]# yum install tomcat5 tomcat5-admin-webapps [...] Installed: tomcat5.i386 0:5.0.30-5jpp_6fc tomcat5-admin-webapps.i386 0:5.0.30-5jpp_6fc Dependency Installed: tomcat5-jasper.i386 0:5.0.30-5jpp_6fc Complete! [root@fcvm ~]# |
還需要安裝 Java 事務(wù) API(JTA)的一個實現(xiàn)。可以用 JPackage 中(請參閱 參考資料)的 RPM 規(guī)范文件構(gòu)建自己的 JTA RPM,但是最簡單的選擇就是安裝來自 Fedora 倉庫的 geronimo-specs
和 geronimo-specs-compat
:
[root@fcvm ~]# rpm -Uvh http://download.fedora.redhat.com/ pub/fedora/linux/core/development/i386/Fedora/RPMS/ geronimo-specs-1.0-0.M2.2jpp_4fc.i386.rpm Preparing... ################################### [100%] 1:geronimo-specs ################################### [100%] [root@fcvm ~]# rpm -Uvh http://download.fedora.redhat.com/ pub/fedora/linux/core/development/i386/Fedora/RPMS/ geronimo-specs-compat-1.0-0.M2.2jpp_4fc.i386.rpm Preparing... ################################### [100%] 1:geronimo-specs-compat ################################### [100%] [root@fcvm ~]# |
使用默認(rèn)的 Tomcat 安裝,CruiseControl Web 應(yīng)用程序會找不到合適的 JAXP TransformerFactory
實現(xiàn),所以需要向選定的類目錄添加默認(rèn) JAXP XML 轉(zhuǎn)換器:
[root@fcvm ~]# cd /usr/share/tomcat5/common/endorsed [root@fcvm endorsed]# ln -s /usr/share/java/jaxp_transform_impl.jar \[jaxp_transform_impl\].jar [root@fcvm endorsed]# ls -l total 12 lrwxrwxrwx 1 root root 36 Sep 19 01:33 [jaxp_parser_impl].jar -> /usr /share/java/jaxp_parser_impl.jar lrwxrwxrwx 1 root root 39 Sep 19 01:47 [jaxp_transform_impl].jar -> / usr/share/java/jaxp_transform_impl.jar lrwxrwxrwx 1 root root 36 Sep 19 01:33 [xml-commons-apis].jar -> /usr /share/java/xml-commons-apis.jar [root@fcvm endorsed]# |
CruiseControl Web 應(yīng)用程序可以繪制重要的構(gòu)建統(tǒng)計圖,例如成功構(gòu)建與失敗構(gòu)建的比例。畫圖的庫要使用 Java AWT,所以需要確保 JVM 運行在 headless 模式。要做到這一點,請編輯 /etc/tomcat5/tomcat5.conf 文件,并插入下面這一行:JAVA_OPTS="-Djava.awt.headless=true"
,位置大約在第 10 行。
現(xiàn)在,在 /etc/tomcat5/Catalina/localhost 下創(chuàng)建一個叫作 cruisecontrol.xml 的文件,把 CruiseControl Web 應(yīng)用程序添加到 Tomcat 的配置。清單 5 顯示了這個文件的內(nèi)容:
清單 5. /etc/tomcat5/Catalina/localhost/cruisecontrol.xml 的內(nèi)容 <Context path="/cruisecontrol" docBase="/home/cruise/pkg/cruisecontrol-2.2.1/reporting/jsp/d ist/cruisecontrol.war"> <Parameter name="logDir" value="/home/cruise/log/build" override="false"/> <Parameter name="cacheRoot" value="/var/cache/tomcat5/cruisecontrol" override="false"/> </Context> |
請注意,清單 5 中的第二行出于顯示的原因進(jìn)行了回繞。docBase
屬性在創(chuàng)建的文件中應(yīng)該單獨占一行。
還需要為 CruiseControl Web 應(yīng)用程序創(chuàng)建一個保存頁面緩存的目錄:
[root@fcvm ~]# cd /var/cache/tomcat5 [root@fcvm tomcat5]# mkdir cruisecontrol [root@fcvm tomcat5]# chgrp tomcat cruisecontrol [root@fcvm tomcat5]# chmod g+w cruisecontrol [root@fcvm tomcat5]# ls -l total 24 drwxrwxr-x 2 root tomcat 4096 Sep 16 09:32 cruisecontrol drwxrwxr-x 2 root tomcat 4096 May 10 11:57 temp drwxrwxr-x 3 root tomcat 4096 Sep 15 22:53 work [root@fcvm tomcat5]# |
現(xiàn)在可以啟動 Tomcat,并把它設(shè)置成在系統(tǒng)啟動時重啟。啟動腳本目前會生成一些警告信息,但是可以忽略它們:
[root@fcvm ~]# service tomcat5 start Starting tomcat5: find: warning: you have specified the -mindepth opti on after a non-option argument -type, but options are not positional ( -mindepth affects tests specified before it as well as those specified after it). Please specify options before other arguments. find: warning: you have specified the -maxdepth option after a non-opt ion argument -type, but options are not positional (-maxdepth affects tests specified before it as well as those specified after it). Pleas e specify options before other arguments. Using CATALINA_BASE: /usr/share/tomcat5 Using CATALINA_HOME: /usr/share/tomcat5 Using CATALINA_TMPDIR: /usr/share/tomcat5/temp Using JAVA_HOME: /usr/lib/jvm/java [ OK ] [root@fcvm ~]# chkconfig tomcat5 on [root@fcvm ~]# chkconfig --list tomcat5 tomcat5 0:off 1:off 2:on 3:on 4:on 5:on 6:off [root@fcvm ~]# |
現(xiàn)在應(yīng)當(dāng)能夠用瀏覽器在 http://localhost:8080/cruisecontrol/ 上訪問 CruiseControl Web 應(yīng)用程序了。圖 1 顯示了將會看到的輸出的示例:
圖 1. CruiseControl Web 應(yīng)用程序安全問題
在我總結(jié)之前,我要指出兩個配置和運行自己的持續(xù)集成服務(wù)器所涉及的安全性問題。首先,我沒有解決構(gòu)建服務(wù)器的訪問安全問題。您應(yīng)當(dāng)參考其他信息來源以確保您的系統(tǒng)安全,或者在提供適當(dāng)保護(hù)的內(nèi)部網(wǎng)絡(luò)上運行它。
其次,對于要在持續(xù)集成服務(wù)器上構(gòu)建的外部項目的開發(fā)人員,您要考慮對他們要信任到什么程度。項目的構(gòu)建過程和單元測試可以訪問服務(wù)器的資源,包括服務(wù)器連接的網(wǎng)絡(luò)。自動構(gòu)建過程意味著提交給遠(yuǎn)程版本控制倉庫的變更會在沒有人為干預(yù)的情況下,自動下載到構(gòu)建服務(wù)器并在上面執(zhí)行。這就把構(gòu)建服務(wù)器置于提交給源樹的 bug和惡意代碼的風(fēng)險之下。您可能想限制在構(gòu)建服務(wù)器上構(gòu)建的外部項目,或者做些工作來保護(hù)系統(tǒng)和網(wǎng)絡(luò)不受正在構(gòu)建的項目的影響。
結(jié)束語
這篇文章介紹了運行 CruiseControl 的持續(xù)集成服務(wù)器的設(shè)置步驟。您安裝了 CruiseControl并學(xué)習(xí)了保持服務(wù)器一直運行需要做的工作,還了解了持續(xù)集成服務(wù)器的日常管理工作。而且還把配置的重要元素提取到更簡單的 XML文檔中,包括版本控制和構(gòu)建工具的選擇以及用來構(gòu)建每個項目的目標(biāo)。
現(xiàn)在您學(xué)會了如何指定項目之間的依賴性。對于 Maven 項目來說指定比較容易,因為它們擁有一致的構(gòu)建過程,生成的制品也有共享的倉庫。Ant 則把這些機(jī)制留給每個項目,但是如果許多 Ant 項目都有公共的構(gòu)建過程,那么可以用生成的 <filesystem>
元素對配置進(jìn)行擴(kuò)展,模擬這些項目之間的依賴性。CruiseControl 還有其他許多控制,可以用來增強(qiáng)持續(xù)集成過程??梢酝ㄟ^我介紹的 XSLT 樣式表輕松地利用它們。
我快速介紹了運行 CruiseControl Web 應(yīng)用程序需要的步驟,但是您可以提高自己安裝的安全性和可靠性。更安全的配置可以使用 Apache 的 httpd
處理請求并把它們交給 Tomcat。讓 daemontools
管理 Tomcat JVM(就像配置它來管理 CruiseControl 本身那樣)可能更可靠。除此之外,還應(yīng)當(dāng)考慮構(gòu)建服務(wù)器和構(gòu)建服務(wù)器所在網(wǎng)絡(luò)的安全需求,并嘗試 Linux 提供的一些安全工具。
這篇文章的目的是通過采取持續(xù)集成方式,讓開發(fā)過程更敏捷并提高軟件的質(zhì)量。創(chuàng)建構(gòu)建服務(wù)器是具體而實用的一步,采用敏捷開發(fā)方法的更多實踐還會得到進(jìn)一步提高。我鼓勵您閱讀關(guān)于這些方法的更多內(nèi)容(請參閱 參考資料)并用它們的想法來提高和調(diào)整開發(fā)過程。
下載
描述 | 名字 | 大小 | 下載方法 |
Sample tools | j-simple-cc.tar.gz | 2 KB | FTP |
參考資料
學(xué)習(xí)獲得產(chǎn)品和技術(shù) - CruiseControl:在 CruiseControl 項目的 Web 站點找到它的下載和文檔。
- CVS 和 Subversion:把源代碼置于版本控制之下。
- JUnit:JUnit 是 Java 編程流行的單元測試框架。
- Maven:Apache Maven 項目提供的構(gòu)建系統(tǒng)集成了許多最佳實踐,包括 JUnit。
- Fedora Core 4:這個 Linux 發(fā)行版是這篇文章描述的構(gòu)建服務(wù)器的基礎(chǔ)。
- JPackage:JPackage 項目源自對 Java 項目進(jìn)行 RPM 打包,F(xiàn)edora 項目采用了這一技術(shù)。項目不能把 Sun JDK 作為 RPM 重新進(jìn)行發(fā)布,但是您可能找到自行構(gòu)建 RPM 的指南和 RPM 規(guī)范文件。
- Fedora Core development repository:在這里可以獲得更新的 Xerces 包。只需對 xerces-j2-2.6.2-4jpp_8fc 包做最小的更新;xerces-j2-2.6.2-5jpp_2fc 是從倉庫中可以得到的最新版本。
- XMLStarlet:這個命令行程序支持在 XML 文檔上執(zhí)行有用的操作。
- daemontools:D. J. Bernstein 的 daemontools 可以讓 CruiseControl 一直運行。
討論關(guān)于作者
|
| | Mark Wilkinson 是位獨立顧問,專攻軟件架構(gòu)、設(shè)計和開發(fā)過程。他曾經(jīng)領(lǐng)導(dǎo)多個小型的程序員團(tuán)隊,為不同的客戶構(gòu)建創(chuàng)造性的解決方案。Mark 開發(fā)了一個實用的技術(shù)來管理開發(fā)過程,這個技術(shù)嚴(yán)重地依賴自動操作和 CruiseControl 這樣的工具。他還為 Codehaus 上的多個項目工作。Mark 擁有英國約克大學(xué)的計算機(jī)科學(xué)博士學(xué)位。 |