在 .NET Core / .NET 5 專案打包 Nuget Package 並自動跳版號

.NET Core 的專案範本在處理版號跟以往有點小差異,雖然很簡單但實作的過程還是卡了一下,為了下一次的順利還是紀錄一下吧

開發環境

  • Rider 2020.3.2 / VS 2019
  • .NET Core 3.1
  • .NET 5
  • Azure DevOps Server 2019

 

由 .NET Core 的專案範本打包 nuget

預設就已經可以將專案直接打包成 nuget

Rider 的設定畫面如下:

 

VS 2019 的設定畫面如下:

 

附帶一提,在 Rider 的目標平台可以多選,也就是說你可以用這個專案範本產生出你想要的目標版本

 

對專案檔按 F4 也可以直接編輯,而且還有 Intellisense

真心覺得這個做的比 VS IDE 還要好

 

符號檔

預設沒有產生符號表,需手動加入 IncludeSymbols,設定 SymbolPackageFormat 則產生新版符號表 .snupkg,若沒有設定則產生舊版 .symbols.nupkg

<PropertyGroup>
    <IncludeSymbols>true</IncludeSymbols>
    <SymbolPackageFormat>snupkg</SymbolPackageFormat>
</PropertyGroup>

 

注意:內嵌符號檔缺點是它們會讓使用 SDK 樣式專案編譯的 .NET 程式庫套件大小增加約 30%。 如果套件大小是個問題,您應該改為將符號發佈在符號套件中。

 

更多符號檔的設定,請參考以下連結:

https://docs.microsoft.com/zh-tw/dotnet/standard/library-guidance/nuget#symbol-packages

 

有哪些版號?

在 .csproj 所看到的屬性跟編譯好的不太一樣我在 => 描述的就是組件建置出來之後的所對應的欄

PackageVersion:Nuget 的版號

InformationalVersion:對應到檔案本身的 ProductVersion 還有 Assembly 的 AssemblyInformationalVersion

FileVersion:對應到檔案本身的 FileVersion 還有 Assembly 的 AssemblyFileVersion

AssemblyVersion:Assembly 版號

 

Assembly 用 ILSpy 打開就可以看到 Assembly 的版號,如下圖

 

設定如下:

<Project Sdk="Microsoft.NET.Sdk">

    <PropertyGroup>
        <TargetFramework>net5.0</TargetFramework>
        <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
        <PackageVersion>1.0.0.1</PackageVersion>
        <AssemblyVersion>1.0.0.1</AssemblyVersion>
        <FileVersion>1.0.0.1</FileVersion>
        <OutputPath>bin</OutputPath>
        <DocumentationFile>bin\ClassLibrary1.xml</DocumentationFile>
        <IncludeSymbols>true</IncludeSymbols>

    </PropertyGroup>

</Project>

 

使用 Version 取代所有版號

只要 Version 一個,就可以完成所有版號設定

<Version>1.0.0.1</Version>

 

自動跳號

Azure DevOps Server Build Pipeline

這裡提供兩種換版號的方法,作法跟上一篇一樣,使用 Assembly Info [VSTS][TFS] 讓組件、檔案、Nuget 版本跳號一致

首先要安裝 Assembly Info

https://marketplace.visualstudio.com/items?itemName=bleddynrichards.Assembly-Info-Task

 

新增 Assembly Info (.Net Core $ .Net Standard) Task,針對每一個版號設定替換方式,這會需要 .csproj 的檔案設定

 

另外一種方法

用 Version 變數處理,這裡不需要 Assembly Info  Task 了,也不需要 .csproj 裡面的設定,新增一個 Version 的變數

 

Build.BuildNumber 使用日期來跳號

$(Year:yyyy).$(Month).$(DayOfMonth).$(Hours)$(Date:mm)

 

MsBuild 產生版號

以往 .NET Framework 專案可以透過 * 來跳板,,詳情參考黑大文章

關於AssemblyVersion的一點小事

 

.NET Framework 還可以透過 Deterministic = false 調整自動跳號,詳情參考黑大文章

<Deterministic>false</Deterministic>
 

.NET 組件版號無法設成 1.0.* 自動跳號

 

不過在 .NET Core 仍僅支援 AssemblyVersion

 

萬一無法使用 CI Server 建置版號,也可以透過 Msbuild 屬性函數,詳細使用手冊如下

https://docs.microsoft.com/zh-tw/visualstudio/msbuild/property-functions?view=vs-2019

 

設定如下:

<Project Sdk="Microsoft.NET.Sdk">

    <PropertyGroup>
        <TargetFramework>net5.0</TargetFramework>
        <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
        <OutputPath>bin</OutputPath>
        <DocumentationFile>bin\ClassLibrary1.xml</DocumentationFile>
        <IncludeSymbols>true</IncludeSymbols>
        <Company>實驗室</Company>
        <AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
        <Major>1</Major>
        <Minor>1</Minor>
        <Build>$([System.DateTime]::op_Subtraction($([System.DateTime]::get_Now().get_Date()),$([System.DateTime]::new(2000,1,1))).get_TotalDays())</Build>
        <Revision>$([MSBuild]::Divide($([System.DateTime]::get_Now().get_TimeOfDay().get_TotalSeconds()), 2).ToString('F0'))</Revision>
        <Version>$(Major).$(Minor).$(Build).$(Revision)</Version>
        <Copyright>© $(Company) $([System.DateTime]::Now.ToString(`yyyy`))</Copyright>
        <Authors>余小章</Authors>

    </PropertyGroup>

</Project>

 

上面的 Major、Minor、Build、Revision 是我自己定義的屬性,參考好友 Kevin Yan  的文章 https://blog.kevinyang.net/2020/11/02/how-to-auto-version/

Build = 以2000/01/01起算的天數。

Revision = 以凌晨00:00:00起算的秒數除以2。

由建置的日期與時間決定,最後的效果就之前的 1.0.* 一樣

若有謬誤,煩請告知,新手發帖請多包涵


Microsoft MVP Award 2010~2017 C# 第四季
Microsoft MVP Award 2018~2022 .NET

Image result for microsoft+mvp+logo