這是一個逼不得已的做法,為了要讓 .NET Framework 專案總是使用最新的 NuGet 套件,讓每次部屬都用最新的套件功能,試出了這樣的處理方式。

如果是 .NET Core 專案

如果你是開發 .NET Core 的專案,要達成每次建置都使用最新版的 NuGet 套件是很簡單的,你可以直接在 .csproj 專案中,透過以下方式來修改 PackageReference 來限制還原套件時,所安裝的版本,甚至你可以直接在 Version 屬性中設定 * 來還原最新的套件版本:

<!-- 僅接受 6.1 版以前的版本 -->
<PackageReference Include="ExamplePackage" Version="6.1" />

<!-- 下面這兩種方式都是只接受 6.x.y 版本 -->
<PackageReference Include="ExamplePackage" Version="6.*" />
<PackageReference Include="ExamplePackage" Version="[6,7)" />

<!-- 接受比 4.1.3 還新的版本,但不包含 4.1.3 -->
<PackageReference Include="ExamplePackage" Version="(4.1.3,)" />

<!-- 接受比 5.x 還舊的版本,此方法可避免使用到重大變更的版本,但不建議這樣寫,因為無法確定你最就可以用到哪一個版本 -->
<PackageReference Include="ExamplePackage" Version="(,5.0)" />

<!-- 接受 1.x 或 2.x 的版本 -->
<PackageReference Include="ExamplePackage" Version="[1,3)" />

<!-- 接受 1.3.2 至 1.4.x 的版本 -->
<PackageReference Include="ExamplePackage" Version="[1.3.2,1.5)" />

<!-- 使用最新的套件版本 -->
<PackageReference Include="ExamplePackage" Version="*" />

版本限制所使用的運算符號意思:

  • [ 大於等於
  • ] 小於等於
  • ( 大於
  • ) 小於

相關資訊可以參考官方文件的套件版本控制

.NET Framework 專案

傳統的 .NET Framework 專案,其 NuGet 套件會被記錄在兩個地方,一個是 packages.config 檔案中,另一個是 .csproj 專案檔內,前者是給 nuget.ext 使用,用於下載並還原套件,後者專案檔裡面所設定的,則是該專案會參考的套件 dll 相關資訊。

當你打開 packages.config 的時候,你會看到像是下面這樣的套件清單,裡面標註了套件名成、版本及目標框架,如果將 version 屬性設定成 *,想說應該可以抓到最新的套件,但這樣的作法會讓 Visual Studio (2019 版本) 還原套件時,因為找不到版本號,就跟你抱怨了。

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="Dapper" version="1.50.4" targetFramework="net48" />
</packages>

Visual Studio 在解析版本的時候會使用語意化版本的規定,使用 主版號.次版號.修訂號 這樣的方式來解析版號,語意化版本詳參考這裡 https://semver.org/lang/zh-TW/

而如果想從專案檔下手,你會發現 HintPath 這個屬性你根本無法動態改變,因為每個套件的路徑會直接相依版本號和支援的框架版本,這個情況下,我們完全無法自動化調整。

<ItemGroup>
  <Reference Include="Dapper, Version=1.50.4.0, Culture=neutral, processorArchitecture=MSIL">
    <HintPath>..\packages\Dapper.1.50.4\lib\net451\Dapper.dll</HintPath>
  </Reference>
</ItemGroup>

看到這裡就很想把整個專案翻掉,改用 .NET Core 的方式來滿足需求。

.NET Framework 專案 + DevOps

其實 NuGet 有一個 update 指令,可以讓你用下指令的方式來將指定的套件升級,而且可以直接升級到最新版,指令如下:

nuget update "MyProject.sln" -Id "MyNuGetPackage"

NuGet update 指令的相關資訊可以參考官方文件的update 命令 (NuGet CLI)

有了指令來將傳統的 .NET Framework 專案升級 NuGet 套件版本,這時只要在 DevOps 中持續整合 (CI) 的任務上,在每次建置任務前,執行一次上述的指令,就可以先將指定的套件更新到最新版了。

後記

雖然眼前的問題是解決的,但這個做法其實並不完美,因為這個做法會在 CI 的過程中更動到原本 check in 進版控的程式碼,.csprojpackages.config 都會被更動到,而且開發人員在自己電腦本機上所 check out 下來最新的程式碼,會和 CI 上所建置的程式碼有些不同,這樣個過程是會讓人覺得怪怪的。

如果你有更優秀的作法,也請你留言給我,讓我心裡有這”怪怪的”疙瘩,謝謝。


參考資料:


Poy Chang

Trial and Error