級別: 中級
Mark Wilkinson, 顧問(wèn), Codehaus
2005 年 10 月 24 日
極限編程和敏捷方法建議開(kāi)發(fā)過(guò)程要包含持續集成和單元測試。支持這些實(shí)踐的一個(gè)實(shí)際方法是設置一個(gè)自動(dòng)系統,每次在源代碼發(fā)生變化時(shí),都自動(dòng)構建和測試源代碼的最新版本。這篇文章將介紹為 Java™ 項目建立基于 Linux™ 的構建服務(wù)器時(shí)涉及的實(shí)際問(wèn)題。
這篇文章介紹的是CruiseControl,這是一個(gè)開(kāi)放源碼軟件,可以用它對有多個(gè)開(kāi)發(fā)人員參與的軟件項目自動(dòng)進(jìn)行構建和單元測試。我將解釋為什么自動(dòng)化構建對于成功的開(kāi)發(fā)團隊是至關(guān)重要的,并一步步介紹運行 CruiseControl 的持續集成系統的配置、安裝和維護。
為什么要自動(dòng)進(jìn)行構建?
目前的一般實(shí)踐是使用版本控制系統,例如 CVS 或 Subversion(請參閱 參考資料)。當有多個(gè)開(kāi)發(fā)人員在同一個(gè)系統上工作時(shí),這類(lèi)協(xié)調就至關(guān)重要了。另一個(gè)正在流行起來(lái)的實(shí)踐是編寫(xiě)單元測試,并把它們作為構建過(guò)程的一部分來(lái)運行。例如,Maven 這個(gè)構建工具就把運行 JUnit 單元測試作為正常構建過(guò)程的一部分(請參閱 參考資料)。但是采用這些實(shí)踐僅僅是個(gè)開(kāi)始。它們構成了近幾年發(fā)展起來(lái)的許多輕量和實(shí)用軟件開(kāi)發(fā)方法的基礎。
| mozilla.org 上的持續集成 從 Mozilla 項目使用的開(kāi)發(fā)方法中,可以學(xué)到許多東西,這是以公開(kāi)方式進(jìn)行的最大的開(kāi)發(fā)項目之一。Mozilla 團隊過(guò)程的關(guān)鍵部分,就是保持樹(shù)的構建,而且他們還記錄下了他們采用的實(shí)踐。他們的一個(gè)重要工具就是 tinderbox 系統,它持續地在許多不同的平臺上構建和測試源樹(shù)(請參閱 參考資料)。 | |
當有許多開(kāi)發(fā)人員在同一個(gè)項目上工作時(shí),重要的就是要確保構版本控制系統中代碼的最新版本一直被構建。。這對于擁有封閉開(kāi)發(fā)團隊的項目來(lái)說(shuō)是個(gè)好的實(shí)踐;當開(kāi)發(fā)人員周期性地把自己的工作區與主干同步時(shí),一個(gè)不進(jìn)行構建的源樹(shù)會(huì )繼續進(jìn)行開(kāi)發(fā),直到能修正它為止。對于開(kāi)放源碼項目,保持主干可以工作是至關(guān)重要的。潛在的新開(kāi)發(fā)人員可以在任何時(shí)候檢出代碼,但是如果代碼不能構建,新開(kāi)發(fā)人員可能就被擋在了做貢獻的隊伍之外。
極限編程(XP)方法論主張 持續集成。開(kāi)發(fā)人員應當盡可能頻繁地把他們的代碼集成進(jìn)主干 —— 典型的是幾小時(shí)一次,同時(shí)還要確保所有單元測試都能通過(guò)。其他敏捷方法論也同意這個(gè)建議。
要采用持續集成和單元測試,需要團隊接受這些方法和實(shí)踐,但是這通常還不夠。目前的實(shí)踐依賴(lài)手工步驟 —— 集成代碼、運行測試、在合適的時(shí)間檢入代碼,這樣的實(shí)踐有可能造成錯誤。讓自動(dòng)系統來(lái)構建代碼、運行單元測試,可能是更可靠的解決方案。
配置構建服務(wù)器
這篇文章剩下的部分將介紹使用 CruiseControl 為 Java 項目配置構建服務(wù)器所涉及的步驟,CruiseControl 是一個(gè)管理自動(dòng)構建過(guò)程的軟件(請參閱 參考資料)。CruiseControl 需要一臺可靠的機器,擁有充足的剩余磁盤(pán)空間,但并不需要特別快。(需要的是定期構建,但是構建過(guò)程本身需要花 2分鐘還是 20 分鐘并不是問(wèn)題。)將要構建的服務(wù)器基于 Fedora Core 4,這是一個(gè)由 Red Hat 資助的社區開(kāi)發(fā)版的 Linux發(fā)行版(請參閱 參考資料),所以需要有一些 Unix 經(jīng)驗。這篇文章涉及的主要任務(wù)有:
- 系統的初始配置,以及設置一個(gè)運行 CruiseControl 的用戶(hù)帳戶(hù)
- 安裝 CruiseControl 并配置第一個(gè)構建
- 讓 CruiseControl 一直運行
- 簡(jiǎn)化 CruiseControl 配置
- 設置可選的基于瀏覽器的界面,用來(lái)監視 CruiseControl 構建
初始配置
第一件事是確保在系統上安裝了 Java 的基本開(kāi)發(fā)所需要的全部軟件。Fedora Core 4 包含基于 gcj(來(lái)自 GNU編譯器集合(gcc)項目的 Java 編譯器)的 Java 工具鏈,但是出于兼容性的原因,最好是安裝來(lái)自 IBM 或 Sun 的JDK。最干凈的方法是按照 jpackage.org 上的說(shuō)明(請參閱 參考資料),構建和安裝自己的 Java RPM。Fedora Core 4 自帶的 xerces-j2 包構建得不正確,造成 Xalan XSLT 實(shí)現不能工作。所以還需要從 Fedora 開(kāi)發(fā)倉庫安裝更新的 xerces-j2 包(請參閱 參考資料)。
還需要使用其他一些軟件:
- XMLStarlet,一個(gè)有用的命令行程序,用來(lái)管理 XML 文檔(請參閱 參考資料)。稍后 將用它來(lái)簡(jiǎn)化 CruiseControl 配置文件的維護。
- CVS 和 Subversion:需要安裝這些工具,以便從構建的源樹(shù)中下載更新。幸運的是,Fedora Core 4 中包含這兩個(gè)工具。
要執行這些步驟,必須以 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 ~]# |
還需要在服務(wù)器上創(chuàng )建一個(gè)新的用戶(hù)帳戶(hù),由它擁有運行 CruiseControl 時(shí)涉及的文件和進(jìn)程:
[root@fcvm ~]# useradd cruise [root@fcvm ~]# su - cruise [cruise@fcvm ~]$ pwd /home/cruise [cruise@fcvm ~]$ |
最后,因為將要構建的某些項目要使用 Maven 構建工具,所以需要下載、安裝它,并設置適當的環(huán)境變量(請參閱 參考資料)。(JAVA_HOME 應當設置為 /usr/lib/jvm/java。)我的習慣是把 Maven 和 CruiseControl 這樣的外部包放在叫作 pkg 的目錄中。在 Maven 的 Web 站點(diǎn)上有完整的安裝說(shuō)明,所以我在這里就不詳細介紹這個(gè)步驟了:
[cruise@fcvm ~]$ mkdir pkg [cruise@fcvm ~]$ cd pkg [cruise@fcvm pkg]$ [install Maven] |
安裝 CruiseControl
下一個(gè)工作是下載 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,因為發(fā)行包中包含一個(gè)預先構建好的 JAR 文件。
現在可以讓第一個(gè)自動(dòng)構建工作了。這里將采用 XStream 項目的源樹(shù)作為初始示例(請參閱 參考資料)。稍后您將會(huì )學(xué)習到如何添加來(lái)自本地和遠程源代碼倉庫的更多項目。CruiseControl 從自己的啟動(dòng)目錄中叫作 config.xml的文件中讀取要構建的項目的信息。在本文的安裝中,這個(gè)目錄是 /home/cruise。清單 1 顯示了一個(gè)簡(jiǎn)單的 config.xml文件的內容,可以從它開(kāi)始。要創(chuàng )建它,只要把清單 1 中的文本拷貝到一個(gè)新文件就可以了:
清單 1. 構建 XStream 的簡(jiǎn)單的 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è)項目的三部分主要信息:
- 如何構建項目,在
<schedule> 元素中指定: - 每 3,600 秒(即每小時(shí))構建項目一次。
- 用 Ant 進(jìn)行構建過(guò)程。
- 每進(jìn)行到第 5 次構建時(shí),清理構建制品(類(lèi)文件以及前面構建中的類(lèi)似內容)的源樹(shù)。
- 如何檢測什么時(shí)候 應當 構建項目,在
<modificationset> 元素中指定: - 用 Subversion(
svn)檢查源樹(shù)的本地工作拷貝是否過(guò)期。(如果源代碼沒(méi)有變化,就不需要構建。) - 檢測強制構建目錄中叫作 xstream 的文件的時(shí)間戳。這樣即使源樹(shù)沒(méi)有變化,也可以手動(dòng)強制進(jìn)行下一次安排的構建。(在這篇文章后面,我將多次談到可能需要這種手工覆蓋。)
- 對構建的結果要做什么,在
<listeners> 和 <log> 元素中指定: - 把構建過(guò)程的輸出放在 log/build/xstream 目錄中加了時(shí)間戳的文件中。
- 把構建的整體狀態(tài)寫(xiě)入這個(gè)目錄中的一個(gè)文件。
現在需要從 XStream 項目的 Subversion 倉庫中簽出 XStream 源樹(shù)。為了保持一致,請把所有源樹(shù)簽出為/home/cruise/src 的子目錄,并把 XStream 源樹(shù)放在 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 會(huì )拒絕啟動(dòng)。
現在構建工作可能沒(méi)有正常工作,也有可能遺漏了一些依賴(lài)項。所以這個(gè)時(shí)候,應當做一些手動(dòng)檢查,確保能夠成功構建 XStream 源樹(shù):
| 構建 XStream 有問(wèn)題? 有可能發(fā)現 XStream 構建失敗,報告 org.w3c.dom.TypeInfo 的 NoClassDefFoundError 錯誤。實(shí)際上,構建幾乎就成功了,但是 XStream 的 Ant 構建腳本用 <junitreport> 任務(wù)生成 JUnit 測試結果的 HTML 報告。這個(gè)工作使用 XSLT 轉換,所以觸發(fā)了前面我在 初始配置 一節中提到過(guò)的 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]$ |
而且,在添加新項目時(shí),需要找到用來(lái)構建源和清理其中制品的目標的名稱(chēng)。必須把這個(gè)信息放在 config.xml 文件中。
現在應當做好準備,可以讓 CruiseControl 自動(dòng)執行這個(gè)構建了。只要啟動(dòng) CruiseControl,然后坐下來(lái)等待就可以了:
[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 一直運行
現在是讓 CruiseControl 運行了,但是還不能讓它在沒(méi)人參與的情況下運行。它目前在一個(gè)終端窗口中運行,所以需要讓 cruise 用戶(hù)永遠登錄,才能保持它一直運行。終端還是控制程序的唯一方式:可以按下 Ctrl+C停止 CruiseControl,并再次運行程序重新啟動(dòng)它。除非使用虛擬網(wǎng)絡(luò )計算(VNC)會(huì )話(huà)或類(lèi)似的東西,否則就不能遠程地做上面這些事。如果CruiseControl(或者JVM)崩潰,就需要手動(dòng)地重啟它。而且當重新啟動(dòng)機器時(shí),也需要手動(dòng)地建立新會(huì )話(huà)、創(chuàng )建終端、再次啟動(dòng)程序,CruiseControl才能重啟。所以需要讓 CruiseControl 作為一個(gè)服務(wù)運行,或者用 Unix 的術(shù)語(yǔ)來(lái)說(shuō),作為一個(gè) 守護程序 運行。
讓程序在 Linux 下持續運行的方法有許多種。最常用的方法可能是把合適的腳本掛上 init 系統初始化進(jìn)程,在系統啟動(dòng)時(shí)啟動(dòng)程序。這些腳本可以啟動(dòng)和停止程序,但是不能在程序出現故障時(shí)自動(dòng)重啟程序。
我用的方法 I 是下載并安裝 Daniel J. Bernstein 的 daemontools(請參閱 參考資料)。這是一個(gè)小的程序包,負責啟動(dòng)一組服務(wù)并保持這些服務(wù)一直運行。要執行自己的 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]# |
要讓這個(gè)包能夠在 Fedora Core 4 上干凈地構建,必須對包的 C 源代碼稍做調整。請用文本編輯器,把 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]# |
現在可以完成安裝了:
[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 的守護進(jìn)程,它負責管理服務(wù)集合。每個(gè)服務(wù)都由 /service 目錄中的一個(gè)目錄代表,所以需要在這里為 CruiseControl 服務(wù)創(chuàng )建一個(gè)目錄。對于 /service 中的每個(gè)子目錄,svscan 都啟動(dòng)一個(gè)子進(jìn)程,運行 supervise 程序。
supervise 是負責管理 CruiseControl 這樣的獨立服務(wù)的程序。它創(chuàng )建子進(jìn)程,運行服務(wù)子目錄中的 run(例如 /service/cruisecontrol/run),從而啟動(dòng)服務(wù)。如果子進(jìn)程中止,supervise 會(huì )重新啟動(dòng)它。supervise 也可以向子進(jìn)程發(fā)送信號,停止或重新啟動(dòng)子進(jìn)程。
daemontools 還提供了兩個(gè)機制,負責處理它管理的服務(wù)的日志記錄。首先,叫作 readproctitle 的程序捕捉寫(xiě)入標準錯誤流(在 Java 世界中,是 System.err)的輸出并把輸出拷貝到一個(gè)小緩沖區中,這個(gè)小緩沖區是 ps 命令顯示的進(jìn)程標題的一部分:
[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]# |
在啟動(dòng)時(shí),緩沖區被初始化為包含點(diǎn)號,但是在出現錯誤時(shí)就被錯誤信息替代。這個(gè)機制對于少量信息(例如關(guān)鍵錯誤信息)來(lái)說(shuō)很好。但是緩沖區尺寸小造成它不適合更大數量的日志信息,而且記錄的信息不能保存到磁盤(pán)也使得難以分析一段時(shí)間內的性能。daemontools 提供了第二種機制 —— multilog 程序,它負責這種大量日志。第二種機制在命令行參數輸出的指令控制下,把自己標準輸入中的行寫(xiě)入日志文件。它包含對日志輪轉的控制,日志輪轉可以保持定量的日志信息,以使存儲空間不會(huì )耗盡。例如,multilog /home/cruise/log 這個(gè)簡(jiǎn)單的命令就可以把信息記錄到 /home/cruise/log 目錄中的文件,當日志文件的尺寸達到 99,999 個(gè)字節時(shí)就輪轉日志文件,并保持 10 個(gè)舊的日志文件。
multilog 也由 supervise 管理,就像其他服務(wù)一樣。在 svsccan 發(fā)現的每個(gè)目錄中,它都會(huì )查找叫作 log 的子目錄,并創(chuàng )建一個(gè) supervise 進(jìn)程來(lái)管理這個(gè)目錄下 run 腳本的執行。它還安排一個(gè)管道,把主服務(wù)的標準輸出作為日志進(jìn)程的標準輸入。
那么,要讓 daemontools 管理 CruiseControl,需要做什么呢?必須為這個(gè)服務(wù)和它的 multilog 伙伴創(chuàng )建目錄結構。還必須創(chuàng )建它們各自的 run 腳本,并為日志文件創(chuàng )建目錄。開(kāi)始時(shí),把服務(wù)目錄命名為 .cruisecontrol。前導點(diǎn)號會(huì )讓 svscan 忽略這個(gè)目錄,從而可以在第一次啟動(dòng)服務(wù)之前進(jìn)行設置:
[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 的目錄。要用這個(gè)目錄的內容設置 CruiseControl 的環(huán)境變量以及它要啟動(dòng)的其他進(jìn)程。在這里要確保 JAVA_HOME 有合適的值。在這里還要設置將要使用的構建工具需要的環(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 的內容 #!/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 |
這個(gè)腳本相當簡(jiǎn)單。它執行以下這些步驟:
- 保存服務(wù)目錄的名稱(chēng)(在這個(gè)示例中是 /service/cruisecontrol)留待后用。
- 把當前目錄變?yōu)?/home/cruise。
- 讓標準錯誤流寫(xiě)入到
multilog 進(jìn)程的管道,這個(gè)管道已經(jīng)連接到了標準輸出流。 - 啟動(dòng) JVM,運行 CruiseControl,以 cruise 這個(gè)用戶(hù)身份運行進(jìn)程,并根據 /service/cruisecontrol/env 目錄中創(chuàng )建的文件設置環(huán)境。
清單 3 演示了 /service/cruisecontrol/log/run 腳本,它更簡(jiǎn)單。它以 cruise 用戶(hù)的身份運行 multilog:
清單 3. /service/cruisecontrol/log/run 的內容 #!/bin/sh exec setuidgid cruise multilog /home/cruise/log/cruisecontrol |
請注意,必須使用 chmod 把兩個(gè)腳本變成可執行的。而且,這兩個(gè)腳本都要小心地使用 exec 外殼命令,這個(gè)命令用一個(gè)程序替代另一個(gè)程序,但是沒(méi)有創(chuàng )建新進(jìn)程。這一點(diǎn)很重要,因為 supervise 只能管理自己的直接子進(jìn)程。如果沒(méi)有使用 exec,那么 JVM 會(huì )作為執行 run 腳本的外殼的一個(gè)子進(jìn)程啟動(dòng)。如果向 supervise 發(fā)送了殺死其子進(jìn)程的信息,那么外殼會(huì )接收到信號并退出,但是 JVM 會(huì )繼續運行,從而變成孤兒。supervise 并不會(huì )知道這一點(diǎn),所以可能會(huì )接著(zhù)啟動(dòng)守護程序的第二個(gè)拷貝 —— 這并不是想要的結果。
在設置好服務(wù)目錄之后,可以把它改名,刪除前導點(diǎn)號。然后 svscan 就會(huì )自動(dòng)啟動(dòng) CruiseControl,它的輸出也會(huì )出現在日志文件中:
[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]# |
簡(jiǎn)化 CruiseControl 的配置
現在已經(jīng)讓 CruiseControl 自動(dòng)運行在一個(gè)很好的受控環(huán)境中。下面要做的就是向配置中添加自己的項目。正如所料,config.xml文件中的項目看起來(lái)非常相似,不同之處只是要用哪個(gè)工具來(lái)構建項目的細節??梢栽谖谋揪庉嬈髦杏每截愓迟N的方式手工維護 config.xml文件,但是一種更少出錯的技術(shù)是使用 XSLT 樣式表從更簡(jiǎn)單的 XML 文檔生成 config.xml文件。實(shí)現這個(gè)方案的文件集合已經(jīng)合成了一個(gè)可以下載的壓縮 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 ~]$ |
簡(jiǎn)化的配置文件名為 meta-config.xml。這個(gè)文件要用 meta-config.xsl 樣式表進(jìn)行變換,生成 CruiseControl 的 config.xml 文件。叫作 mkconfig 的簡(jiǎn)單腳本用早先安裝的 XMLStarlet 工具執行轉換操作。請運行 mkconfig 重新生成 CruiseControl 的 config.xml 文件。
構建監視
前面開(kāi)始的簡(jiǎn)單 CruiseControl配置對于讓第一個(gè)構建工作來(lái)說(shuō)足夠了,但是對于監視構建過(guò)程來(lái)說(shuō)還不夠。最常見(jiàn)的需求是把集成構建的結果通過(guò)電子郵件發(fā)送給相關(guān)開(kāi)發(fā)人員。meta-config.xsl 樣式表生成發(fā)送電子郵件消息的配置,但是要做到這一點(diǎn),它需要一些本地環(huán)境變量的信息。它必須知道的許多變量要從meta-config-params.xsl 文件讀??;在開(kāi)始之前應該根據實(shí)際情況修改這個(gè)文件。這個(gè)文件中的設置如下所示:
- home :構建進(jìn)程的主目錄。如果采用的是這篇文章中描述的目錄布局,那么默認設置就可以了。
- cruisecontrol-home :CruiseControl 發(fā)行包解壓后所在的目錄。同樣,默認設置應當就可以了。
- ant-home :Ant 的安裝目錄。要使用 Fedora Core 4 自帶的 Ant,應當把這個(gè)值設為 /usr。
- maven-home :Maven 的安裝目錄(如果需要用它的話(huà))。默認值假設把 Maven 解壓縮到 /home/cruise/pkg 目錄。
- return-address :CruiseControl 構建電子郵件的返回電子郵件地址。
- return-name :構建電子郵件返回地址的名稱(chēng)。
- developers-address :除了上次成功構建之后進(jìn)行過(guò)提交的開(kāi)發(fā)人員之外,應當總是得到構建電子郵件拷貝的一個(gè)電子郵件地址。
對于構建成功或失敗時(shí)應當給誰(shuí)發(fā)送電子郵件,CruiseControl 在這方面相當靈活。在這里使用的配置將向最后一次構建之后向版本控制系統中提交變更的每個(gè)開(kāi)發(fā)人員發(fā)送電子郵件。持續集成構建可能還包含在其他地方開(kāi)發(fā)的開(kāi)放源碼項目(我將把它們稱(chēng)作 遠程項目),這時(shí),當遠程項目的開(kāi)發(fā)人員弄糟了什么事的時(shí)候,可能并不想讓構建系統向他們發(fā)送電子郵件。在這種情況下,可以向一個(gè)地址發(fā)送郵件,這個(gè)地址通常是一個(gè)郵件列表,如果團隊成員經(jīng)常想知道構建的狀態(tài),可以訂閱這個(gè)郵件列表。這可以讓團隊負責人盡早發(fā)現構建發(fā)生了損壞。
清單 4 顯示了 meta-config.xml 文件的語(yǔ)法:
清單 4. meta-config.xml 的語(yǔ)法 <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> |
配置文件基本上是個(gè) <project> 元素列表。每個(gè)項目都有一個(gè) name 屬性??蛇x的 interval 屬性覆蓋了 CruiseControl 默認的 5 分鐘的構建間隔時(shí)間??梢蕴岣哌h程項目的構建間隔,以減輕它們的版本控制倉庫的負擔。
利用 <svn/> 或 <cvs/> 空元素,每個(gè)項目必須指定自己用來(lái)更新源樹(shù)的版本控制工具。項目還必須指定要使用的構建工具,或者是 <ant/> 或者是 <maven/>。項目還必須包含兩個(gè)元素,說(shuō)明要使用哪個(gè)目標(或哪個(gè) Maven 的目標)清理和構建源樹(shù)。對于 Maven,典型的值可能是 <clean>clean</clean> 和 <build>jar:install-snapshot</build>。對于 Ant,可能需要檢查 build.xml 文件來(lái)找到目標的名稱(chēng)。
假設項目的源在 /home/cruise/src 目錄下,根據項目命名,那么 name 屬性為 my-project 的項目的源應當在 /home/cruise/src/my-project 中。有些項目擁有大型源樹(shù),擁有可以單獨構建的子目錄;為了處理這種情況,<project> 元素可以包含可選的 <srcdir> 元素,由它指定 /home/cruise/src 目錄的特定子目錄。例如:
<project name="my-utils"> <srcdir>big-project/my-utils</srcdir> ... |
CruiseControl 默認的行為是向上次構建之后簽入變更的每個(gè)人發(fā)送電子郵件。如果是從遠程版本控制倉庫中拉出源代碼,請添加 <remote-project/> 元素,這可以使電子郵件發(fā)送到 meta-config.xsl 文件中指定的 developers-address 地址。
項目間的依賴(lài)關(guān)系
CruiseControl并不知道項目之間的依賴(lài)關(guān)系??赡苡幸粋€(gè)項目生成的 JAR 文件包含的工具類(lèi)集合是其他許多項目依賴(lài)的,但是除非向 CruiseControl解釋這個(gè)關(guān)系,否則它對這個(gè)關(guān)系將毫不知情??梢詫ぞ哳?lèi)的項目進(jìn)行修改,從而造成它被重新構建,但是依賴(lài)它的項目不會(huì )針對工具類(lèi)的新版本重新被構建和測試。這可能會(huì )降低集成測試的價(jià)值,所以出現了對這一問(wèn)題的一些解決方案。
CruiseControl 為這個(gè)目的提供的主要工具是 <filesystem> 元素??梢园堰@個(gè)元素包含在某個(gè)項目的 <modificationset> 小節中,這樣只要文件系統的某些區域發(fā)生了修改,項目就會(huì )被重新構建。清單 1 中初始的 config.xml 文件就采用這種方式,在強制構建目錄中的文件發(fā)生修改時(shí),觸發(fā)重新構建。所有的項目都會(huì )在文件系統的某個(gè)位置創(chuàng )建或更新制品。(例如,作為工具類(lèi)項目的構建結果,會(huì )更新自己產(chǎn)生的 JAR 文件。)可以在 <filesystem> 元素中用這些位置,觸發(fā)依賴(lài)這些制品的項目進(jìn)行構建。
Ant 在項目構建的方式方面有很高的靈活性,所以不可能確定地指出項目重新構建時(shí)會(huì )更新文件系統的哪個(gè)區域。在這里可以采用的唯一方法就是檢查每個(gè)文件的 build.xml 文件,找出它把構建的制品放在哪兒。然后才能把合適的 <filesystem> 元素添加到依賴(lài)這些制品的項目中。簡(jiǎn)化的 meta-config.xml 文件支持一個(gè) <modificationset> 元素,里面可以包含任何 CruiseControl 元素。它們會(huì )被拷貝到 config.xml 文件中。例如,依賴(lài) XStream 的項目可能包含以下內容:
<project name="my-project"> [...] <modificationset> <filesystem folder="/home/cruise/src/xstream/xstream-SNAPSHOT.jar"/> </modificationset> </project> |
Maven 在每個(gè)項目上放了一個(gè)公共構建過(guò)程,所以在 Maven 項目間指定依賴(lài)性時(shí),可以提供一些公共規則。項目可以對 Maven 倉庫中由指定群組創(chuàng )建的制品指定依賴(lài)。更準確地說(shuō),包含 <repo-dependency>classworlds</repo-dependency> 可以讓項目在 /home/cruise/.maven/repository/classworlds 下的文件發(fā)生變化時(shí),重新進(jìn)行構建。假設 classworlds 構建是在本地 Maven 倉庫中安裝了制作好的 JAR 文件,那么任何包含這個(gè)元素的項目都會(huì )自動(dòng)重新構建。
項目也可以指定對其他項目的構建輸出的依賴(lài)。包含 <srcdir-dependency>classworlds</srcdir-dependency> 可以讓項目在 ${srcdir}/target 下的文件發(fā)生變化時(shí)重新進(jìn)行構建,其中 ${srcdir} 是命名項目的源目錄。
向構建添加項目
下面是向持續集成構建添加新項目的步驟:
- 作為 cruise 用戶(hù),把源代碼簽出到 /home/cruise/src 目錄。
- 檢查是否可以手工構建源樹(shù)。
- 向 meta-config.xml 添加適當的條目。
- 運行
./mkconfig。 - 重啟 CruiseControl,以便它能從 config.xml 讀取新的項目條目??梢杂?
ps 命令找到運行 CruiseControl 的 JVM 的進(jìn)程 ID,然后用 kill 命令殺死進(jìn)程。也可以用 root 用戶(hù)身份運行 svc -t /service/cruisecontrol,讓 daemontools 殺死進(jìn)程。不管采用哪種方法,supervise 都可以保證 CruiseControl 會(huì )被重啟。 - 可選地,更新 /home/cruise/force-build/${project-name} 的時(shí)間戳也可以讓 CruiseControl 觸發(fā)自動(dòng)重新構建。
CruiseControl Web 應用程序
目前為止運行的 CruiseControl 安裝把每個(gè)構建的結果用電子郵件消息發(fā)送給開(kāi)發(fā)人員。但是開(kāi)發(fā)過(guò)程可能包含不是這些消息收件人的人員 ——例如,項目管理人員或測試人員。CruiseControl 包含一個(gè)簡(jiǎn)單的 Web 應用程序,可以讓這些人員監視持續集成構建。
CruiseControl Web 應用程序在 Apache Tomcat 應用程序服務(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)的一個(gè)實(shí)現??梢杂?JPackage 中(請參閱 參考資料)的 RPM 規范文件構建自己的 JTA RPM,但是最簡(jiǎn)單的選擇就是安裝來(lái)自 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 ~]# |
使用默認的 Tomcat 安裝,CruiseControl Web 應用程序會(huì )找不到合適的 JAXP TransformerFactory 實(shí)現,所以需要向選定的類(lèi)目錄添加默認 JAXP XML 轉換器:
[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 應用程序可以繪制重要的構建統計圖,例如成功構建與失敗構建的比例。畫(huà)圖的庫要使用 Java AWT,所以需要確保 JVM 運行在 headless 模式。要做到這一點(diǎn),請編輯 /etc/tomcat5/tomcat5.conf 文件,并插入下面這一行:JAVA_OPTS="-Djava.awt.headless=true",位置大約在第 10 行。
現在,在 /etc/tomcat5/Catalina/localhost 下創(chuàng )建一個(gè)叫作 cruisecontrol.xml 的文件,把 CruiseControl Web 應用程序添加到 Tomcat 的配置。清單 5 顯示了這個(gè)文件的內容:
清單 5. /etc/tomcat5/Catalina/localhost/cruisecontrol.xml 的內容 <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 )建的文件中應該單獨占一行。
還需要為 CruiseControl Web 應用程序創(chuàng )建一個(gè)保存頁(yè)面緩存的目錄:
[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]# |
現在可以啟動(dòng) Tomcat,并把它設置成在系統啟動(dòng)時(shí)重啟。啟動(dòng)腳本目前會(huì )生成一些警告信息,但是可以忽略它們:
[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 ~]# |
現在應當能夠用瀏覽器在 http://localhost:8080/cruisecontrol/ 上訪(fǎng)問(wèn) CruiseControl Web 應用程序了。圖 1 顯示了將會(huì )看到的輸出的示例:
圖 1. CruiseControl Web 應用程序安全問(wèn)題
在我總結之前,我要指出兩個(gè)配置和運行自己的持續集成服務(wù)器所涉及的安全性問(wèn)題。首先,我沒(méi)有解決構建服務(wù)器的訪(fǎng)問(wèn)安全問(wèn)題。您應當參考其他信息來(lái)源以確保您的系統安全,或者在提供適當保護的內部網(wǎng)絡(luò )上運行它。
其次,對于要在持續集成服務(wù)器上構建的外部項目的開(kāi)發(fā)人員,您要考慮對他們要信任到什么程度。項目的構建過(guò)程和單元測試可以訪(fǎng)問(wèn)服務(wù)器的資源,包括服務(wù)器連接的網(wǎng)絡(luò )。自動(dòng)構建過(guò)程意味著(zhù)提交給遠程版本控制倉庫的變更會(huì )在沒(méi)有人為干預的情況下,自動(dòng)下載到構建服務(wù)器并在上面執行。這就把構建服務(wù)器置于提交給源樹(shù)的 bug和惡意代碼的風(fēng)險之下。您可能想限制在構建服務(wù)器上構建的外部項目,或者做些工作來(lái)保護系統和網(wǎng)絡(luò )不受正在構建的項目的影響。
結束語(yǔ)
這篇文章介紹了運行 CruiseControl 的持續集成服務(wù)器的設置步驟。您安裝了 CruiseControl并學(xué)習了保持服務(wù)器一直運行需要做的工作,還了解了持續集成服務(wù)器的日常管理工作。而且還把配置的重要元素提取到更簡(jiǎn)單的 XML文檔中,包括版本控制和構建工具的選擇以及用來(lái)構建每個(gè)項目的目標。
現在您學(xué)會(huì )了如何指定項目之間的依賴(lài)性。對于 Maven 項目來(lái)說(shuō)指定比較容易,因為它們擁有一致的構建過(guò)程,生成的制品也有共享的倉庫。Ant 則把這些機制留給每個(gè)項目,但是如果許多 Ant 項目都有公共的構建過(guò)程,那么可以用生成的 <filesystem> 元素對配置進(jìn)行擴展,模擬這些項目之間的依賴(lài)性。CruiseControl 還有其他許多控制,可以用來(lái)增強持續集成過(guò)程??梢酝ㄟ^(guò)我介紹的 XSLT 樣式表輕松地利用它們。
我快速介紹了運行 CruiseControl Web 應用程序需要的步驟,但是您可以提高自己安裝的安全性和可靠性。更安全的配置可以使用 Apache 的 httpd 處理請求并把它們交給 Tomcat。讓 daemontools 管理 Tomcat JVM(就像配置它來(lái)管理 CruiseControl 本身那樣)可能更可靠。除此之外,還應當考慮構建服務(wù)器和構建服務(wù)器所在網(wǎng)絡(luò )的安全需求,并嘗試 Linux 提供的一些安全工具。
這篇文章的目的是通過(guò)采取持續集成方式,讓開(kāi)發(fā)過(guò)程更敏捷并提高軟件的質(zhì)量。創(chuàng )建構建服務(wù)器是具體而實(shí)用的一步,采用敏捷開(kāi)發(fā)方法的更多實(shí)踐還會(huì )得到進(jìn)一步提高。我鼓勵您閱讀關(guān)于這些方法的更多內容(請參閱 參考資料)并用它們的想法來(lái)提高和調整開(kāi)發(fā)過(guò)程。
下載
| 描述 | 名字 | 大小 | 下載方法 |
| Sample tools | j-simple-cc.tar.gz | 2 KB | FTP |
參考資料
學(xué)習獲得產(chǎn)品和技術(shù) - CruiseControl:在 CruiseControl 項目的 Web 站點(diǎn)找到它的下載和文檔。
- CVS 和 Subversion:把源代碼置于版本控制之下。
- JUnit:JUnit 是 Java 編程流行的單元測試框架。
- Maven:Apache Maven 項目提供的構建系統集成了許多最佳實(shí)踐,包括 JUnit。
- Fedora Core 4:這個(gè) Linux 發(fā)行版是這篇文章描述的構建服務(wù)器的基礎。
- JPackage:JPackage 項目源自對 Java 項目進(jìn)行 RPM 打包,Fedora 項目采用了這一技術(shù)。項目不能把 Sun JDK 作為 RPM 重新進(jìn)行發(fā)布,但是您可能找到自行構建 RPM 的指南和 RPM 規范文件。
- Fedora Core development repository:在這里可以獲得更新的 Xerces 包。只需對 xerces-j2-2.6.2-4jpp_8fc 包做最小的更新;xerces-j2-2.6.2-5jpp_2fc 是從倉庫中可以得到的最新版本。
- XMLStarlet:這個(gè)命令行程序支持在 XML 文檔上執行有用的操作。
- daemontools:D. J. Bernstein 的 daemontools 可以讓 CruiseControl 一直運行。
討論關(guān)于作者
|
| | | Mark Wilkinson 是位獨立顧問(wèn),專(zhuān)攻軟件架構、設計和開(kāi)發(fā)過(guò)程。他曾經(jīng)領(lǐng)導多個(gè)小型的程序員團隊,為不同的客戶(hù)構建創(chuàng )造性的解決方案。Mark 開(kāi)發(fā)了一個(gè)實(shí)用的技術(shù)來(lái)管理開(kāi)發(fā)過(guò)程,這個(gè)技術(shù)嚴重地依賴(lài)自動(dòng)操作和 CruiseControl 這樣的工具。他還為 Codehaus 上的多個(gè)項目工作。Mark 擁有英國約克大學(xué)的計算機科學(xué)博士學(xué)位。 |