程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Rational >> 基於CruiseControl和Rational統一變更管理實現的軟件開發中的自動化持續構建

基於CruiseControl和Rational統一變更管理實現的軟件開發中的自動化持續構建

編輯:Rational

基於CruiseControl和Rational統一變更管理實現的軟件開發中的自動化持續構建

簡介:本文介紹了持續構建工具 CruiseControl 和 IBM Rational 統一變更管理集成的解決方案。通 過本文中的解決方案,可以盡早的發現和規避代碼中存在的風險,遵守統一的流程及時獲取可發布的軟件 ,確保敏捷開發的速度和質量。

統一變更管理系統中持續集成的必要性

使用 IBM Rational ClearCase 和 IBM Rational ClearQuest 實現的統一變更管理軟件將配置管理和 變更管理緊密結合起來,尤其針對大中型項目,實現軟件開發生命周期的流程控制和管理。在這個過程中 ,面向變更所做的代碼在開發流上被不斷的檢入和交付到集成流。可能在交付前,開發人員已經在個人開 發流上對代碼進行過編譯和單元測試。然而由於在交付過程中可能發生的代碼沖突和歸並,或者由於構建 環境改變,導致集成流上的構建和測試失敗。為了盡早發現和規避交付後產生的風險,加快構建和發布的 速度,代碼需要不斷被集成,所以持續集成構建工具是必不可少的。同時為了減少在構建過程中人工干預 所帶來的錯誤,對所有發布遵守統一的構建流程,我們希望進程構建工具盡可能做到自動化。

CruiseControl 正是這樣一個提供了自動化的可持續集成和構建流程管理的工具。CruiseControl 是 基於 Ant 技術實現的,它實現的 plug-ins 提供了對不同的源代碼管理工具和構建工具的集成,並且實 現了構建結果 email 通知和構建 artifacts 統一 web 界面管理。此外,CruiseControl 是 Java 語言 實現的開放源碼,所以用戶可以通過修改代碼或者安插腳本實現構建過程個性化。

本文主要介紹了 CruiseControl 和基於 IBM Rational ClearCase 和 ClearQuest 實現的統一變更管 理的集成方案,通過個性化的腳本將 CruiseControl 融入軟件生命周期管理,實現整個開發流程的自動 化。

兩種構建模式 -- 單元構建和每日構建

基於 IBM Rational ClearCase 和 ClearQuest 實現的統一變更管理主要應用於大中型團隊項目。為 了盡早發現交付中代碼歸並產生的問題,頻繁的交付和集成是關鍵。對於大中型項目,如果每人每天都進 行一次交付,為了盡可能快速發現問題並且縮小問題范圍,集成構建工具需要盡快對每次交付進行集成構 建。然而,一般的項目可能需要幾個小時完成構建。為了縮短構建時間同時盡可能發現問題,這裡引入了 單元構建和每日構建的概念。

單元構建

為了達到盡早發現問題的目的,我們設計了單元構建。單元構建是基於前一次成功構建,僅對修改的 源代碼進行編譯和單元測試的構建過程。 CruiseControl 提供的與 ClearCase 集成的功能可以監控 UCM 項目的集成流,當基於變更請求的代碼被交付到集成流,新的元素版本在流上被創建,CruiseControl 這 時啟動單元構建程序。這個構建可以采用增量編譯,目的在於迅速發現被交付的代碼與集成流上的代碼歸 並後是否存在錯誤。當然有些問題只有在完全編譯中才能被發現,但是考慮到這種問題如果不是經常發生 ,而且為了達到短時間完成單元構建,然後可以對其他被交付的代碼進行檢查的目的,我們可以將完全構 建發生的問題留到每日構建中解決。此外,為了盡早發現集成的代碼中存在的問題,也可以在構建腳本中 加入基本的自動測試腳本。腳本中的任何測試用例的執行失敗都會直接導致單元構建失敗。

圖 1. 持續集成中單元構建的典型流程

每日構建

不管是使用敏捷開發還是瀑布開發模式的項目,最好每天至少完成一次完全構建。和單元構建相比, 每天進行的完全構建產生可以用來測試和發布的 artifacts,並且在統一變更管理系統中創建和維護基線 ,記錄當前構建是否成功。通過基線,開發人員可以回溯項目的歷史版本重新建構歷史發布,也可以重構 失敗構建的代碼環境來分析和解決問題。和單元構建一樣,在構建 artifacts 產生後,也可以在構建腳 本中加入基本的自動測試。如果自動測試中的任何測試用例執行失敗,那麼每日構建也標記為失敗。由於 每日構建是完全構建,並且調用的測試用例可能也比單元構建多,所以需要較長時間完成。為了不占用白 天的服務器資源,我們可以設定在晚上的某一時間啟動每日構建。

圖 2. 每日持續集成構建的典型流程

在 CruiseControl 中實現與 UCM 集成的持續集成構建

通過配置 CruiseControl 安裝目錄下的文件 config.xml,可以實現項目的持續集成構建。上一章節 介紹了單元構建和集成構建的典型構建流程,在這一章節我們詳細介紹如果在 CruiseControl 中通過配 置 XML 元素和屬性實現這兩種流程。

在 CruiseContrl 與 UCM 集成環境實現單元構建

首先設置監控任務,透過事先創建的集成視圖監控集成流上是否有新的交付版本,決定是否啟動單元 構建。在下面的示例代碼中 schedule 任務每 120 秒檢查一次,查找集成流上是否有新的版本,然後運 行單元構建腳本 cc-build-unit.xml。在所有新的版本創建後等待 300 秒啟動單元構建,這樣做的目的 是防止單元構建在交付的途中(部分代碼被檢入的時候)就被啟動。

清單 1. 配置監控任務

<!-- Defines where cruise looks for changes, to  decide whether to run the build -->
<modificationset quietperiod="300">
  <ucm stream="TestProject_Integration"
  viewPath="C:/TestProject_int_view/Test.CompVOB"
  contributors="true"/>
</modificationset>

<!-- Configures the actual build loop, how often and which build file/target  -->
<schedule interval="120">
  <ant antscript="C:/Program Files/CruiseControl/apache-ant-1.7.0/bin/ant.bat"
  buildfile="cc-build-unit.xml"
  target="build">
  <property name="cc.viewroot" value="C:/TestProject_int_view"/>
  <property name="cc.stream" value="TestProject_Integration"/>
  </ant>
</schedule>

接下來的任務是在文件 cc-build-unit.xml 中配置的。首先更新構建用的集成視圖,裝入集成流上最 新的代碼版本。

清單 2. 更新構建區域源代碼

<target name="update-view" description="update  ClearCase snapshot view">
<ca:ccexec failonerror="true">
  <arg value="update"/>
  <arg value="-force"/>
<arg value="-overwrite"/>
<arg value="${cc.viewroot}"/>
  </ca:ccexec>
  </target>

代碼更新後啟動項目的構建腳本,對剛才交付的代碼進行增量編譯和測試

清單 3. 啟動構建腳本

<ant antfile="build-unit.xml" dir="${cc.viewroot}/source"  target="all"/>

編譯和測試結束後,腳本 cc-build-unit.xml 的任務也都完成。單元構建通過 config.xml 中的 <log> 任務將編譯和測試產生的日志文件合並到 CruiseControl 為本次構建產生的日志文件,通 過 web 控制台發布。

清單 4. 合並單元構建腳本的日志文件和 CruiseControl 的日志文件

<log  logdir="logs/${project.name}">
  <merge dir="C:/TestProject_int_view/logs" />
  <merge dir="C:/TestProject_int_view/test_results" />
</log>

此外,為了將構建結果及時通知給交付代碼的開發人員以及其他項目相關人員,可以通過 email 的方 式,將構建結果和日志內嵌到 email 中通知項目組成員。這裡 <failure> 子元素定制在構建失敗 後,除了進行代碼交付的可發人員,其他人是否收到 email 通知。

清單 5. 通過 email 通知構建結果

<!-- Publishers are run *after* a build  completes -->
<publishers>
<plugin name="htmlemail"
  buildresultsurl="http://build-server:8080/cruisecontrol/buildresults/${project.name}"
  mailhost="mail-server"
  returnaddress="CruiseControl@build-server "
  returnname="CruiseControl"
  subjectprefix="[CruiseControl]"
  xsldir="webapps/cruisecontrol/xsl"
  css="webapps/cruisecontrol/css/cruisecontrol.css"
  skipusers="false">
  <map alias="lilywang" address="[email protected]" />
  <failure address="lilywang" reportWhenFixed="true" />
  </plugin>
</publishers>

在 CruiseContrl 與 UCM 集成環境實現每日構建

與上一章節介紹的單元構建不同,每日構建是每天定時啟動的。如果在規定的啟動時間之前集成流上 有代碼交付,CruiseControl 啟動構建。下面的設置在晚上 9 點啟動任務,如果有新的版本在集成流 TestProject_Integration 上創建,CruiseControl 執行每日構建腳本 cc-build-nightly.xml。

清單 6. 配置定時啟動任務

<!-- Defines where cruise looks for changes,  to decide whether to run the build -->
  <modificationset quietperiod="180">
  <ucm stream="TestProject_Integration"
  viewPath="C:/TestProject_int_view/Test.CompVOB"
  contributors="true"/>
</modificationset>

<!-- Configures the actual build loop, how often and which build file/target  -->
<schedule>
  <ant antscript="C:/Program Files/CruiseControl/apache-ant-1.7.0/bin/ant.bat"
  buildfile="cc-build-nightly.xml"
  target="build"
  time="2100">
<property name="cc.viewtag" value="TestProject_int_view"/>
<property name="cc.viewroot" value="C:/TestProject_int_view"/>
  <property name="cc.stream" value="TestProject_Integration"/>
  </ant>
</schedule>

接下來的構建任務是在 cc-build-nightly.xml 中完成的。每日構建中產生的 artifacts 可以用來發 布給測試團隊和客戶,所以在執行構建的時候需要更嚴格。為了確保構建區域代碼的穩定和干淨,我們需 要在腳本中給集成流加鎖,清空構建區域的所有文件,重新裝載集成流上的最新代碼到構建區域。

清單 7. 清空和裝載構建區域源代碼

<target name="lock-stream"  description="Lock integration stream before build">
<ca:ccexec failonerror="false">
<arg value="lock"/>
<arg value="-nc"/>
<arg line="-nusers build-user"/>
<arg value="stream:${cc.stream}"/>
</ca:ccexec>
</target>

<target name="update-view" description="update ClearCase snapshot view">
<delete includeEmptyDirs="true" verbose="true" failonerror="false">
  <fileset dir="${cc.viewroot}/Test.CompVOB " includes="**/*"/>
  </delete>
<ca:ccexec failonerror="true">
<arg value="update"/>
<arg value="-force"/>
<arg value="-overwrite"/>
<arg value="${cc.viewroot}"/>
</ca:ccexec>
</target>

這之後和單元構建一樣,執行清單 3 中的構建腳本進行完全編譯和自動測試。結束後返回到 config.xml,和清單 4 一樣,將編譯和測試產生的日志文件合並到 CruiseControl 日志文件,通過 web 控制台發布。

不管 cc-build-nightly.xml 執行的編譯和測試是否成功,都需要在集成流上創建基線。通過基線可 以重建構建的代碼環境,便於以後對成功的構建進行重構,或者對失敗的構建進行調試。這個任務在 config.xml 的 <publisher> 任務中完成。

清單 8. 創建構建成功後的基線

<publishers>
  <onsuccess>
<antpublisher antscript="C:/Program Files/CruiseControl/apache-ant- 1.7.0/bin/ant.bat"
  buildfile="cc-build-nightly.xml"
  target="make-success-baseline">
  <property name="cc.stream" value="TestProject_Integration"/>
<property name="cc.viewtag" value="TestProject_int_view"/>
  </antpublisher>
  </onsuccess>
</publishers>

在 cc-build-nightly.xml 中加入 make-success-baseline 任務:

清單 9. 加入 make-success-baseline 任務

<target name="make-success-baseline"  description="Create successful baseline">
<ca:ccexec failonerror="true">
<arg value="mkbl"/>
<arg value="-nc"/>
<arg value="-identical"/>
<arg line="-view ${cc.viewtag}"/>
<arg value="${label}"/>
</ca:ccexec>
</target>

這裡我們假設 ClearCase 項目使用的 projectname_basename_date 格式的基線模板,所以上面的創 建基線操作只需要輸入 basename 部分就夠了。

對於構建成功後創建的基線,我們用 ${label} 作為基線的 basename。這個變量是 CruiseControl 提供的對成功構建的標識,默認的第一次成功構建的標識是 build.1,項目每次構建成功後”.”後面的 數字依次加 1。也可以通過 <labelincrementer> 修改構建標識的格式。在這裡生成的基線名稱是 TestProject_build.1_20090724。

如果構建失敗,我們可以使用不同的 basename 創建失敗的基線。

清單 10. 創建構建失敗後的基線

<publishers>
  <onfailure>
<antpublisher antscript="C:/Program Files/CruiseControl/apache-ant- 1.7.0/bin/ant.bat"
  buildfile="cc-build-nightly.xml"
  target="make-failed-baseline">
  <property name="cc.stream" value="TestProject_Integration"/>
<property name="cc.viewtag" value="TestProject_int_view"/>
  </antpublisher>
  </onfailure>
</publishers>

在 cc-build-nightly.xml 中加入 make-failed-baseline 目標:

清單 11. 加入 make-failed-baseline 目標

<target name=" make-failed-baseline"  description="Create failure baseline">
<ca:ccexec failonerror="true">
<arg value="mkbl"/>
<arg value="-nc"/>
<arg line="-view ${cc.viewtag}"/>
<arg value="FAIL"/>
</ca:ccexec>
</target>

CruiseControl 為每個產品的每個構建創建單獨的目錄,用於發布構建產生的 aritfacts。測試人員 通過 web 控制台可以下載 build artifacts 用於測試,發布經理可以將這些 artifacts 打包給客戶。 在構建成功後,使用 <artifactspublisher> 將構建產生的 aritifacts 拷貝到 CruiseControl 提供的發布目錄。

清單 12. 發布構建產生的 artifacts

<publishers>
  <onsuccess>
  <artifactspublisher
  dir="C:/TestProject_int_view/artifacts"
  dest="artifacts/${project.name}" />
  </onsuccess>
</publishers>

此外,在構建開始集成流被加鎖,現在構建結束,我們還要對集成流解鎖。這個工作也在 config.xml 的 <publisher> 部分中完成。

清單 13. 對集成流解鎖

<publishers>
<antpublisher antscript="C:/Program Files/CruiseControl/apache-ant- 1.7.0/bin/ant.bat"
  buildfile="cc-build-nightly.xml"
  target="unlock-stream">
  <property name="cc.stream" value=""TestProject_Integration"/>
  </antpublisher>
</publishers>

在 cc-build-nightly.xml 中加入 unlock-stream 目標:

清單 14. 加入 unlock-stream 目標

<target name="unlock-stream"  description="Unlock integration stream before build">
<ca:ccexec failonerror="false">
<arg value="unlock"/>
<arg value="-nc"/>
<arg value="stream:${cc.stream}"/>
</ca:ccexec>
  </target>

最後,和單元構建一樣,在 config.xml 通過 email 的形式可以快速通知相關開發人員構建結果。這 個部分通過在 <publisher> 中直接調用清單 5 種定義的 <htmlemail> 實現。

通過 CruiseControl 和 UCM 集成的功能進行進一步優化

ClearCase 和 ClearQuest 本身都提供對 Perl 腳本語言的支持,CruiseControl 是基於 Ant 實現的 ,通過 Ant 也很容易可以執行構建服務器上和隨 ClearCase 安裝的 ccperl 編譯器,通過調用 Perl 腳 本,可以在 CruiseControl 中完成任何對 UCM 系統的操作。下面舉兩個具體的例子。

在單元構建產生構建目標加速構建

前面的章節提到在單元構建中采用了增量編譯和自動測試。為近一步縮短時間加速構建完成,我們可 以根據構建中修改的代碼所屬的模塊進行部分模塊編譯,然後選擇相關測試用例進行測試。

為達到這一目的,首先構建腳本和自動測試腳本需要支持模塊化編譯和測試,這裡我們對腳本編寫不 作具體的討論。我們需要解決的是如何在 CruiseControl 中得到本次構建中哪些代碼被修改,從而產生 構建目標。

首先在 cc-build-unit.xml 更新構建區域源代碼(清單 2)後,啟動構建之前,插入下面的代碼調用 Perl 腳本生成構建目標。

清單 15. 生成構建目標

<exec executable="ccperl.exe"  failonerror="false">
<arg line="getBuildTargetFromCC.pl ${cc.stream} ${cc.viewroot}  ${ucmlastbuild}"/>
  </exec>

這裡 ucmlastbuild 變量是 CruiseControl 提供的,代表前一次成功構建的發生時間,格式是 dd- MMMM-yyyy.HH:mm:ss。根據這個時間,我們可以在腳本 getBuildTargetFromCC.pl 中利用 ClearCase lshistory 命令得到本次構建中哪些文件被修改,產生構建目標。

清單 16. 產生本次構建所有修改文件列表

my $full_list = `cleartool lshist - branch $cc.stream -r -nco -fmt
    "%o~#~%n\\n" -since $ucmlastbuild $cc.viewroot/test.CompVOB`;

my @lines = split(/\n/, $full_list);
foreach my $line (@lines)
{
my ($type, $version) = split(/~#~/, $line);

// Not consider  operation like mkbranch, rmbranch or rmver
if ($type ne "mkbranch" && $type ne "rmbranch" && $type ne  "rmver")
  {
push @change_list, $version;
}
  }
  ...

構建成功後在 ClearQuest 數據庫中記錄構建信息

統一變更管理系統中,ClearQuest 數據庫中維護變更請求的詳細信息。通過 CruiseControl 對 Perl 腳本的調用,可以自動更新某一變更請求是在哪個構建中修復的。

假設在 ClearQuest schema 中為變更請求加入 FixedInBuild 屬性。我們可以通過 ClearQuest 提供 的 Perl API 將 CruiseControl 產生的構建標識加入到被交付的變更請求的 FixedInBuild 屬性。

首先在 cc-build-nightly.xml 的目標 make-success-baseline 創建基線(清單 8)成功後加入下面 的代碼 :

清單 17. 在 ClearQuest 數據庫中記錄構建信息

<exec executable="ccperl.exe"  failonerror="false">
<arg line="add_build_to_cq.pl ${cc.stream} ${cc.viewroot} ${label}"/>
</exec>

在 add_build_to_cq.pl 中通過 ClearCase diffbl 命令比較本次構建和前一次構建創建的基線的區 別,得到本次構建包含的被交付變更請求,然後將構建標識 ${label} 更新到變更請求的 FixedInBuild 屬性。

清單 18. 更新變更請求的 FixedInBuild 屬性

// Get the baseline created by  CruiseControl, which is the latest baseline 
// on integration stream
my $baseline = `cleartool desc -fmt "%[latest_bls]p" stream:$cc.stream`;

// Get activities contained in the baseline, the list is same as the  ChangeRequests
// delivered in the build
my $activities = `cleartool diffbl -activities -predecessor $baseline;
@activities = split(/\n/,$activities);

// Add build label (build.1) to CR’s FixedInBuild field
my $session = CQSession::Build();
foreach my $CR (@activityset)
{
my $CR_entity = $session->GetEntityById("ChangeRequest", $CR);
$session->EditEntity($CR_entity, "Modify");
$CR_entity->SetFieldValue("FixedInBuild", $label);
$CR_entity ->Validate();
$CR_entity ->Commit();
}

上面只是介紹了兩個典型應用,通過 CruiseControl 對腳本的調用,可以將構建的很多相關信息加入 到 UCM 系統,通過對變更請求生命周期的管理實現開發流程的自動,避免人工干預帶來的錯誤。同時對 基於同一代碼庫的不同項目提供統一的構建流程管理,加速發布速度。

總結

本文介紹了通過對腳本的開發,將持續集成工具 CruiseControl 和統一變更管理系統 ClearCase/ClearQuest 相結合,創建一個有效的持續集成環境的全過程。通過在軟件開發生命周期管理 中加入自動構建和發布以及信息反饋,為實現敏捷開發提供基礎,確保敏捷開發的速度和質量。在現實環 境中,讀者可以結合自己的配置管理系統和項目需要,對配置文件和腳本進行定制,實現滿足項目需求的 持續集成系統。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved