使用 GitVersion 在編譯或持續構建時自動使用語義版本號(Semantic Versioning)

使用 GitVersion 在編譯或持續構建時自動使用語義版本號(Semantic Versioning)

發佈於 2018-04-12 13:45 更新於 2018-09-01 00:11

我們在之前談過 語義版本號(Semantic Versioning),在項目中應用語義版本號能夠幫助庫的開發者在發佈包時表明更多的語義信息。這是趨勢,從微軟的博客 Versioning NuGet packages in a continuous delivery world 三部曲中可以看出,從 NuGet 4.3.0 以及 Visual Studio 2017 15.3 以上版本開始支持語義版本號 2.0 也能看出。

本文將從持續集成的角度來說語義版本號,告訴大家如何自動生成包含語義的版本號,並在發佈庫時採用。


This post is written in multiple languages. Please select yours:

中文 English

安裝 GitVersionTask

微軟工程師在博客 Versioning NuGet packages in a continuous delivery world: part 3 – Microsoft DevOps Blog 中推薦的語義版本號生成工具是 GitVersion。從實際尋找來看,這似乎也是唯一一個能夠讓 NuGet 包支持語義版本號的工具。

NuGet.org 上爲我們的庫項目安裝 GitVersionTask 即可開始我們的語義版本號。

請特別注意

  1. 目前只有 GitVersionTask 4.0 以上的版本(目前都是 beta)才支持 .NET Core 那樣新格式的 csproj。
  2. 目前即便是最新測試版的 GitVersionTask 也不支持使用基於 .NET Core 的 dotnet build 編譯,原因和解決方案我已經提交給 GitTools 團隊了(詳見:dotnet build command always fails with GitVersionTask 4.0.0-beta · Issue #1399 · GitTools/GitVersion),臨時方案是使用 .NET Framework 版本的 msbuild

配置 GitVersion

特別吐槽一下 GitVersion 的官方文檔,把功能堆積得很多很強大,卻忽視了面向新手的入門教程。

GitVersion 的配置文件名爲 GitVersion.yml,要求放到倉庫的根目錄下。官方文檔對於配置文件的解釋非常抽象,看完也不知道值應該寫成什麼樣,也不知道每個值代表什麼意義。於是我基本上是通過閱讀它的源碼來了解配置文件的實際含義的。

經過一番折騰,我把配置文件改成了下面這樣。

next-version: 1.0
mode: ContinuousDelivery
increment: Inherit
tag-prefix: '[vV]'
source-branches: ['master', 'develop', 'hotfix']
ignore:
  sha: []
  commits-before: 2018-01-01T00:00:00
branches:
  master:
    regex: master$
    mode: ContinuousDelivery
    tag: ''
    increment: Patch
    prevent-increment-of-merged-branch-version: true
    track-merge-target: false
    tracks-release-branches: false
    is-release-branch: true
  release:
    regex: r(elease$|(eleases)?[-/])
    mode: ContinuousDelivery
    tag: beta
    increment: Patch
    prevent-increment-of-merged-branch-version: true
    track-merge-target: false
    tracks-release-branches: false
    is-release-branch: true
  feature:
    regex: f(eatures)?[-/]
    mode: ContinuousDeployment
    tag: alpha
    increment: Minor
    prevent-increment-of-merged-branch-version: false
    track-merge-target: false
    tracks-release-branches: false
    is-release-branch: false

▲ 別看這配置文件寫得這麼長,但其實官方的默認配置文件更長!

好了不開玩笑了,這配置文件分兩部分來看:1. branches 之前;2. branches 之後。

寫在 branches 之前的爲全局配置,寫在 branches 之後的是按分支分類的配置;它們的配置鍵值其實都是一樣的。分支裏的配置優先級高於全局配置。也就是說,如果編譯打包的分支名能被 regex 正則表達式匹配上,那麼就使用匹配的分支配置,否則使用全局配置。

舉例,假設我們現在的版本庫是這樣的:

分支名稱匹配 regex

那麼當我們在 release 分支的 f 提交上編譯,使用的配置將是 release 分支的配置。

由於我將 release 分支的正則表達式寫成了 r(elease$|(eleases)?[-/])(注意,我們不需要加行首標記 ^,因爲 GitVersionTask 裏會爲我們在最前面加一個),所以類似這樣的分支名也是使用 release 分支的配置:

  • r/1.2.0
  • releases/1.2.0
  • release

但是,這樣的分支名將採用默認的全局配置(因爲不符合正則表達式):

  • r
  • releases

以上配置中我只列舉了三組分支,但其實在 一個成功的 Git 分支流模型 中,還有 hotfix develop 這樣更多的分支。如果你的項目足夠大,建議自己參考其他分支寫出這兩個分支的配置出來。

預發佈標籤 tag

我們的 release 配置中,會爲版本號加一個 beta 預發佈標籤,所以可能打出 2.0.0-beta 這樣的包出來,或者 2.0.0-beta+3。但在全局配置下,默認打出的包會加一個以分支名命名的預發佈標籤;像這樣 2.0.0-r(在 r 分支),或者 2.0.0-temp-walterlv-custombranch(在 temp/walterlv/custombranch 分支)。

繼續看以上的配置,在 f/blogfeatures/new 分支上將採用 alpha 預發佈標籤。

我們在 master 分支的配置上

版本號遞增規則 increment

increment 這一項的可選值有 MajorMinorPatchNoneInherit 五種。

  • Major 如果此前在 Git 倉庫此分支前有一個 1.2.0 的 Tag,那麼現在將打出 2.0.0 的包來(無論此分支當前距離那個 Tag 有多少個提交,都只加 1)
  • Minor 如果此前在 Git 倉庫此分支前有一個 1.2.0 的 Tag,那麼現在將打出 1.3.0 的包來(無論此分支當前距離那個 Tag 有多少個提交,都只加 1)
  • Patch 如果此前在 Git 倉庫此分支前有一個 1.2.0 的 Tag,那麼現在將打出 1.2.1 的包來(無論此分支當前距離那個 Tag 有多少個提交,都只加 1)
  • None 如果此前在 Git 倉庫此分支前有一個 1.2.0 的 Tag,那麼現在將打出 1.2.0 的包來
  • Inherit 如果此分支上沒有發現能夠確認版本號的線索(例如一個 Tag),那麼將自動尋找此分支的來源分支,繼承來源分支的版本號遞增規則。注意我在全局配置中加了一個 source-branches 配置,用於指定如果要自動尋找來源分支,請去這個集合中指定的分支名稱裏找。

下圖是 release 分支上打包的版本號。

版本號遞增的方式 mode

mode 可選的值有三種:

  • continuous-delivery 持續交付,臨近產品發佈時使用,詳細信息可閱讀Continous delivery - GitVersion
  • continuous-deployment 持續部署,日常使用,詳細信息可閱讀Continuous deployment - GitVersion
  • Mainline 傳統的(官方文檔沒有說明,代碼中沒有註釋,但閱讀代碼發現其策略是從上一個 Tag 遞增版本號)

語義版本號使用教程

在瞭解了以上的配置之後,使用 GitVersionTask 纔不會顯得版本號的規則詭異。

我們從簡單的使用開始,逐步向難演進。學習規則爲:單個 master 分支 -> Git 分支流與預發佈版本

單個 master 分支

如果我們只在 master 上開發,那麼上手就非常容易了。

如果我們剛開始接觸 GitVersionTask,那麼我們在上一個發佈包的提交上新建一個標籤(Tag),命名爲 v1.2.0,那麼此標籤之後的版本號打包將自動變爲 1.2.1。Git 提交每次增多,那麼構建號將加 1。下圖中的版本號是 1.2.1+3。(注意:加號是語義版本號 2.0 的新特性,重申需要 NuGet 4.3.0 以及 Visual Studio 2017 15.3 以上版本。)

Git 分支流與預發佈版本

當使用 Git 分支流時,版本號的遞增方式其實與前面配置章節和單個 master 章節講的時一致的。如下圖。

但是,我們需要學習如何充分利用這樣的分支流,以便讓語義版本號充分發揮它的作用。

假設:我們最近發佈了 1.1.0 正式版。

  1. 如果我們正在爲庫添加新功能,則新建一個 feature 分支,一直開發,直到認爲開發完畢(功能實現完成,單元測試全綠)
  2. 如果此時有打包需求臨時內測,則直接在 feature 分支打包,這樣能打出 1.2.0-alpha 的包(後面的 + 取決於相對於此前發佈多了多少個提交)
  3. 如果內測差不多了,則合併到 develop 分支確認這個內側包
  4. 如果準備發佈這個功能了,那麼從 develop 分到 release 分支
  5. 這時如果有打包需求,則應該在打包之前新建一個標籤(Tag)v1.2-beta,這樣能打出 1.2beta 包(而不是 1.1 的)
  6. 如果在此 beta 的基礎上出現持續打包,那麼需要持續新建標籤(因爲自動新建的標籤只會增加一次 Patch 號)
  7. 如果確認可正式發佈,則 release 合併到 master,新建 v1.2 標籤

參考資料

本文會經常更新,請閱讀原文: https://walterlv.com/post/automatically-semantic-versioning-using-git-version-task.html ,以避免陳舊錯誤知識的誤導,同時有更好的閱讀體驗。

本作品採用 知識共享署名-非商業性使用-相同方式共享 4.0 國際許可協議 進行許可。歡迎轉載、使用、重新發布,但務必保留文章署名 呂毅 (包含鏈接: https://walterlv.com ),不得用於商業目的,基於本文修改後的作品務必以相同的許可發佈。如有任何疑問,請 與我聯繫 ([email protected])

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章