持續整合學習筆記-入門篇(7)成果管理自動化(一):版本號的管理
經過自動化持續整合工作之後,一般會產生兩類重要成果:
1、提供給使用者使用的軟體產品
2、軟體設計、開發時產生的文件
毋庸置疑,軟體產品本來就是我們工作的目標物。在實際工作中,尤其是在給企業做定製化的MIS系統時,很難說只給使用者一次性提供產品,往往需要不斷升級,從而向客戶提供多個版本的產品(其實商業軟體、開源軟體、網站等也是如此)。在配置管理中,版本號是管理軟體產品釋出、部署(上兩篇筆記已經探討了如何實現自動化部署的問題)、回溯等工作的關鍵線索。其實,在SCM中,版本號是一個極重要但又比較複雜的問題,幸好實際工作中我們不用涉及太深。
基於此,本文主要針對如何自動化地生成產品版本號進行了探討。只要版本號的自動生成原理搞清楚了,其它象分支的生成、主幹線與分支的合併、版本回溯等問題則就是簡單地輸入命令的事情了。
一、兩類版本號的區別與聯絡
在持續整合中,實際上會涉及到兩類版本號:
l 版本控制庫裡,由於原始碼不斷提交所產生的版本號。在SVN中,文件(原始碼等)版本號是按自然數增長,從1開始,到10、122、329……等
l 軟體Release時設定的版本號。我們常見的形式是1.0版、2.3.7版……等等。在本文中,由Maven生成Release版本號---實際就是將專案POM.xml中artifactId對應的快照方式(x.x.x- SNAPSHOT)的版本號轉化成release方式(x.x.x)的版本號
雖然版本號形式不同,但其背後都是同一套原始碼。所以,決定我們生成、管理版本號的關鍵因素就是:建立release
解決這個問題的思路其實也比較明確,就是在SVN\trunk中某個版本號的原始碼執行構建任務成功後,利用maven的外掛,將這個版本號的原始碼copy到SVN\Tags中的以release 版本號命名的子目錄下。見下面的對應關係示意表。
工作日期 |
SVN\trunk原始碼版本號(每天可能有N次提交,也就有N個版本號) |
release 版本號(假設每天進行一次構建、釋出) |
(釋出時在SVN中打個tag)SVN\Tags中的原始碼版本號 |
Day1 |
1 |
構建成功 |
存放目錄為SVN\tags\ release-1.1,對應的trunk |
……. |
|||
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中設定好的外掛、依賴的執行。
2、POM.xml中所設定的dependency必須是釋出版本, 不能使用SNAPSHOT版本
3、保證命令列形式下的SVN命令得以執行。實際上就是要事先安裝好支援命令列形式的SVN伺服器。如果只安裝了tortoiseSVN,那就慘了。
4、Maven Release在執行過程中,會修改POM.xml中scm的connection設定。如果release異常中止的話, 需要恢復原來的pom檔案,才能再次執行. 因此在試驗階段, 最好準備一個POM.xml的備份
5、如果想執行release:perform命令,即要讓Maven自動釋出生成後的jar,就先要設定好maven的遠端分發倉庫。
(二)、設定Jenkins job
在Jenkins中新建一個job。在“配置”中,設定好自定義空間、原始碼管理相應選項,並在“構建”的Goals下放入release:clean 和release:prepare兩條命令,然後執行立即構建。這樣,在命令列下需要人機互動的環節就能以預設選擇方式自動進行了。
我們可以對比一下變化:
Ø 構建前
POM的artifactId版本號為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版本號自動生成,方法其實與主幹線的一樣,區別僅僅在於:原始碼來源目錄不一樣。
何時進行分支操作,何時進行分支、主幹線的合併,是需要人工干涉的,這種事不應該實現自動化:因為機器無法判斷應該在什麼條件下去做這些事情。