持續整合系統簡介
持續整合系統是指持續地編譯、測試、檢查和部署原始碼的系統。
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:
1 |
#svnadmin create /var/lib/temp/monarch |
然後,我們可以在這個空的 repository 裡,放置一個 workspace。例如,可以通過把一個從其它 workspace 生成的 dump 檔案 load 進這個 repository:
1 |
#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 的路徑,例如:
1 2 3 |
<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 構建持續整合系統的過程。在敘述構建過程當中,重點講解了如何解決其中會遇到的問題。