1. 程式人生 > >持續整合學習筆記-入門篇(7)成果管理自動化(一):版本號的管理

持續整合學習筆記-入門篇(7)成果管理自動化(一):版本號的管理

經過自動化持續整合工作之後,一般會產生兩類重要成果:

1、提供給使用者使用的軟體產品

2、軟體設計、開發時產生的文件

毋庸置疑,軟體產品本來就是我們工作的目標物。在實際工作中,尤其是在給企業做定製化的MIS系統時,很難說只給使用者一次性提供產品,往往需要不斷升級,從而向客戶提供多個版本的產品(其實商業軟體、開源軟體、網站等也是如此)。在配置管理中,版本號是管理軟體產品釋出、部署(上兩篇筆記已經探討了如何實現自動化部署的問題)、回溯等工作的關鍵線索。其實,在SCM中,版本號是一個極重要但又比較複雜的問題,幸好實際工作中我們不用涉及太深。

基於此,本文主要針對如何自動化地生成產品版本號進行了探討。只要版本號的自動生成原理搞清楚了,其它象分支的生成、主幹線與分支的合併、版本回溯等問題則就是簡單地輸入命令的事情了。

一、兩類版本號的區別與聯絡

在持續整合中,實際上會涉及到兩類版本號:

l  版本控制庫裡,由於原始碼不斷提交所產生的版本號。在SVN中,文件(原始碼等)版本號是按自然數增長,從1開始,到10122329……

l  軟體Release時設定的版本號。我們常見的形式是1.0版、2.3.7……等等。在本文中,由Maven生成Release版本號---實際就是將專案POM.xmlartifactId對應的快照方式(x.x.x- SNAPSHOT)的版本號轉化成release方式(x.x.x)的版本號

雖然版本號形式不同,但其背後都是同一套原始碼。所以,決定我們生成、管理版本號的關鍵因素就是:建立release

版本號與SVN倉庫文件版本號之間的對應關係。

解決這個問題的思路其實也比較明確,就是在SVN\trunk中某個版本號的原始碼執行構建任務成功後,利用maven的外掛,將這個版本號的原始碼copySVN\Tags中的以release 版本號命名的子目錄下。見下面的對應關係示意表。

工作日期

SVN\trunk原始碼版本號(每天可能有N次提交,也就有N個版本號)

release 版本號(假設每天進行一次構建、釋出)

(釋出時在SVN中打個tagSVN\Tags中的原始碼版本號

Day1

1

構建成功

存放目錄為SVN\tags\ release-1.1,對應的trunk

下原始碼版本號為32

…….

32

1.1

Day2

33

構建成功

存放目錄為SVN\tags\ release-1.2,對應的trunk下原始碼版本號為54

……

54

1.2

Day3

55

構建不成功,無release版本釋出

無內容

……

82

Day4

83

構建成功

存放目錄為SVN\tags\ release-1.3,對應的trunk下原始碼版本號為106

……

106

1.3

但上述材料講的是如何通過命令列實現,期間還要經過人機互動操作才能生成Release版本號。對於筆者來說,是想把版本號的生成納入到日常性的持續整合工作中(比如每日生成一個釋出版),這顯然就需要版本號的自動化生成,於是,就該Jenkins登場了。

二、版本號的自動生成

版本號的自動生成主要依靠一個maven外掛,就是上面提到的maven-release-plugin

相應的操作步驟如下:

   1、在pom.xml中設定maven-release-plugin

   2、建立一個Jenkins job,並進行設定

   3、執行構建任務

(一)、設定maven-release-plugin

以學習筆記(5)中提到的DEMO為例,在pom.xml中設定兩部分內容:SCM設定和外掛configuration設定。這些設定和命令列執行方式下沒有區別。注意,目前版本號為0.1.1-SNAPSHOT。具體設定內容和說明如下:

<groupId>DEMO</groupId>

<artifactId>DEMO</artifactId>

<!--貌似SNAPSHOT必須要大寫字母-->

<version>0.1.1-SNAPSHOT</version>

<packaging>jar</packaging>

<!--必須明確設定SCM,否則maven-release-plugin找不到SVN原始碼倉庫-->

<scm>

 <connection>scm:svn:file:///C:/DEMO/trunk</connection>

 <developerConnection>scm:svn:file:///C:/DEMO/trunk</developerConnection>

</scm>

……

<build>

……

<plugins>

……

<!-- 設定maven-release-plugin -->

<plugin>   

  <groupId>org.apache.maven.plugins</groupId> 

  <artifactId>maven-release-plugin</artifactId> 

  <version>2.3.2</version> 

  <configuration> 

<!--tags目錄位置。如果是https:,則格式為https://192.168.1.100:8443/svn/myapp/tags/-->

<tagBase> file:///C:/DEMO/tags</tagBase>

   </configuration> 

</plugin>

……

</plugins>

……

</build>

可以看到,設定本身不算複雜。但要想順利地執行,一定要保證幾個關鍵前提條件。其實,筆者多次試驗均未成功,最後發現原因就是違反了以下的某個前提條件:

1、確保所有程式碼都提交到SVN倉庫,本地沒有未提交程式碼。如果本地有更新過的檔案,但沒有提交到SVN倉庫,執行release外掛就會報錯。

這個前提很重要。建議:設立一個空的資料夾作為CI工作空間,裡面只放入pom.xml;而這個pom.xml也需要提交至SVN\trunk目錄下,以保證pom.xml也在SVN管轄範圍內。再進行release的構建時,就會嚴格的符合CI工作空間沒有未提交程式碼的條件了。這種情況下,也不影響其它POM.xml中設定好的外掛、依賴的執行。

2POM.xml中所設定的dependency必須是釋出版本, 不能使用SNAPSHOT版本

3、保證命令列形式下的SVN命令得以執行。實際上就是要事先安裝好支援命令列形式的SVN伺服器。如果只安裝了tortoiseSVN,那就慘了。

4Maven Release在執行過程中,會修改POM.xmlscmconnection設定。如果release異常中止的話, 需要恢復原來的pom檔案,才能再次執行. 因此在試驗階段, 最好準備一個POM.xml的備份

5、如果想執行release:perform命令,即要讓Maven自動釋出生成後的jar,就先要設定好maven的遠端分發倉庫。

(二)、設定Jenkins job

Jenkins中新建一個job。在“配置”中,設定好自定義空間、原始碼管理相應選項,並在“構建”的Goals下放入release:clean release:prepare兩條命令,然後執行立即構建。這樣,在命令列下需要人機互動的環節就能以預設選擇方式自動進行了。

我們可以對比一下變化:

Ø  構建前

Ÿ   POMartifactId版本號為0.1.1-SNAPSHOT

Ø  構建後

Ÿ   本地以及SVN\trunk目錄下的pom.xml中,artifactId版本號變為0.1.2-SNAPSHOT

Ÿ   SVN\tags目錄下生成一個DEMO-0.1.1的目錄,其中包含了原始碼以及pom.xml

二、分支的版本號管理

要想進行分支的版本號管理,首先要生成一個分支。因為這裡我們主要關注release版本,所以使用mvn命令(如何用SVN命令進行分支管理,請見《學習筆記(4)》中推薦的教程)。比如說從主幹線版本1.1.0分出支線,可以通過下面的命令列執行:

mvn release:branch -DbranchName=1.1.1 -DupdateBranchVersions=true -DupdateWorkingCopyVersions=false

此時,在SVN\branches下,會生成一個1.1.1-SNAPSHOT 的目錄,而SVN\branches下的pom.xml中,artifactId版本號會自動變為1.1.1-SNAPSHOT

然後,要想實現分支的release版本號自動生成,方法其實與主幹線的一樣,區別僅僅在於:原始碼來源目錄不一樣。

何時進行分支操作,何時進行分支、主幹線的合併,是需要人工干涉的,這種事不應該實現自動化:因為機器無法判斷應該在什麼條件下去做這些事情。