背景:
在項目中, 通常會拆分成核心庫(Core)和應用(App)兩個部分。核心庫由專人維護, 不同的App是不同的團隊,但都引用了核心庫。當核心庫需要升級更新時,有的應用會更新,有的不會——可能是沒必要,可能是應用本身更新、部署限制條件多。因此,會造成多版本並存的情況。
使用NuGet來做多版本的管理和分發是一件普遍接收的事情。Visual Studio 可以直接將csproj項目制作成一個NuGet包, 但是只能包含這個項目本身編譯的dll;如果當前項目還引用了其他的csproj項目,這些引用並沒有能包含在Nuget包中。
因此,下面我將要解決兩個問題:
1) 多個項目生成一個Nuget包
2) 自動遞增Nuget包的版本問題
技巧:
一,將多個csproj項目生成一個nuget包。
我的思路是這樣的,為了減少操作上的麻煩, 我建了一個空的項目Z, 然后這個項目引用了所有其他需要打入包中的類庫項目A, B, C…, 當Z項目Build的時候, 就會自動編譯A, B, C項目,並且將類庫生成到bin目錄中。
其次, 使用*.nuspec文件,來描述包中的內容。
<?xml version="1.0" encoding="utf-8"?> <package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd"> <metadata> <id>MyPack.Foundation</id> <version>1.0.11</version> <authors> MyPack </authors> <owners> MyPack </owners> <requireLicenseAcceptance>false</requireLicenseAcceptance> <description>[RedPI類庫] RedPI.Foundation, 微服務開發框架</description> <dependencies> <group targetFramework=".NETStandard2.0"> <dependency id="AutoMapper" version="10.0.0" /> <dependency id="Jaeger" version="0.3.7" /> </group> </dependencies> </metadata> <files> <file src=".\netstandard2.0\Company.*.dll" target="lib\netstandard2.0" /> <file src=".\netstandard2.0\Company.*.pdb" target="lib\netstandard2.0" /> </files> </package>
Nuspec文件上面描述了包的版本、作者等信息,下面描述了包的內容。具體格式不在此贅述,感興趣的看官可以自行查閱官網。在這里我重點說明下dependency和file。
Dependency是說整個nuget包的依賴,也就是包中所有lib庫項目的依賴項的合集。這個很好找, 我的做法就是打開每個csproj文件, 把里面的PackageReference內容拿出來,換下格式就好—— 既有依賴的包名稱, 也有版本號。
<ItemGroup> <PackageReference Include="Newtonsoft.Json" Version="12.0.3" /> <PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" /> </ItemGroup>
File是包的內容文件,使用相對路徑,支持使用“*”匹配多個文件。建議項目的類庫使用相同的名稱前綴, 這樣一行描述就夠用了。 而且未來如果有新的類庫加入, 不需要更新此處。
然后就可以使用Nuget.exe命令進行打包了:
nuget pack %nuspec% -version %VER% -Symbols -OutputDirectory %rootPath%
其中%nuspec% 就是我們剛才提到的nuspec文件,
%VER% 是包的版本號,這個接下來我們看看怎么做自動遞增
%rootPath% 是本地包文件存放的位置。
二,自動遞增包的版本號
這個有兩種做法,一是先查后增, 二是在CI(持續集成)里搭配BuildNumber實現。后者是我們現在項目中的做法,也比較容易實現。接下來我主要介紹下“先查后增”的做法。
一般項目組要發布自己的Nuget包的話, 都會先搭建自己的Nuget服務器。如果使用Azure Devops Server的話,可以使用其中的Artifact作為自建包源;或者使用Nuget.Server包快速搭建一個自己的asp.net的Nuget服務器。然后可以使用nuget.exe list 指令進行版本查詢。具體的過程腳本描述如下:
$addr = 'http://[your nuget server address]/nuget'
$pack = 'jquery' # package name , eg. jquery
#$pack = $(pack)
$currentVer = nuget list $pack -source $addr
# $currentVer = nuget list packageid:$pack -source nuget.org
# # $currentVer = 'jquery 3.5.1.5'
write-host "Current Version:$currentVer"
$matchs=$currentVer| select-string -AllMatches "[\w.]+ ([\d+.]+)(\d)[-pre]?"
# $matchs.Matches[0].Groups[1].Captures[0].Value
# $matchs.Matches[0].Groups[2].Captures[0].Value
$p = $matchs.Matches[0].Groups[1].Captures[0].Value
$n = 1+ $matchs.Matches[0].Groups[2].Captures[0].Value
$newVer = "$p$n"
其中使用了正則匹配來找到版本號的最小段,然后遞增即可。
補充一點, 在將包發布到服務器上之前,可以先在本地試試效果,也即將nupkg文件復制到local的目錄中, 該目錄可以作為nuget源進行引用。
最后, 使用nuget.exe push 將包發布到服務器上
nuget push $nupkg -ApiKey {pwd} -Source $addr
總結:
包的使用在項目團隊中很重要, 如果版本管理不好,容易招惹眾怒,要考慮的事情還是挺多的。上面主要介紹了兩個技巧,一個是將多個項目打成一個包,另一個是自動獲取並遞增版本號,希望能對各位看官有所幫助。