最近在寫共用元件,打算放在公司的NuGet私服供同事下載安裝,換版時還可自動更新,大大降低管理成本。講到製作NuGet Packet,NuGet Package Explorer雖然方便,但畢竟是GUI工具,我希望修改元件並測試OK後,直接在Visual Studio專案按個鍵就自動上傳到NuGet伺服器。經過評估,找到一個好用套件-NuGet Packager

我習慣修改元件後先手動丟上測試環境,測試一陣子沒問題再發布到NuGet伺服器,不要每次建置就發布,因此不適合將發布程序做成Build Task或寫成建置事件。NuGet Packager的做法是提供NuGet Package專屬專案,專案依據Package規格做好content、lib、tools、src目錄, 當需要額外加入Script、工具、內容檔案就放入對應的資料夾,檔案還能納入版控;實務上Package打包檔案的來源也可能來自其他專案項目或編譯結果,此時可在Package.nuspec使用相對路徑,編譯時直接由來源取得最新結果,不需要手動複製及同步,十分方便。(詳見隨後範例)

由於是獨立專案,我們可自由決定發布時機,而NuGet Packager採取的規則是:使用Debug模式編譯只產生.nupkg檔案,在Release模式則會編譯並上傳NuGet伺服器。

以下用簡單範例介紹NuGet Packager的使用方式。

首先,在Extensions and Updates搜尋"nuget packager"並安裝:

安裝之後,Visual Studio會多出一種專案型別-NuGet Packager:

在解決方案中新增一個NuGet Packager專案,專案的目錄結構如下:

content、lib、src、tools都是NuGet用來擺放不同用途檔案的資料夾,而tools裡也先預備好init.ps1、install.ps1、uninstall.ps1等安裝及解除安裝腳本範本。(如果不知道檔案該怎麼擺,可先用NuGet Package Explorer操作再觀察檔案結構)

下一步是編輯Package.nuspec:

<?xml version="1.0"?>
<package >
  <metadata>
    <id>MagicApiClient</id>
    <version>1.0.0</version>
    <title>MagicApiClient</title>
    <authors>Jeffrey</authors>
    <owners></owners>
    <description>某個魔法API的客戶端元件</description>
    <releaseNotes>
    </releaseNotes>
    <summary>簡化魔法API呼叫邏輯的神祕元件</summary>
    <language>en-US</language>
    <projectUrl>http://blog.darkthread.net</projectUrl>
    <iconUrl>httq://some-server//Icons/magic.png</iconUrl>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <licenseUrl>http://opensource.org/licenses/Apache-2.0</licenseUrl>
    <copyright>Copyright  2016</copyright>
    <dependencies>
    </dependencies>
    <references></references>
    <tags></tags>
  </metadata>
  <files>
    <file src="lib\" target="lib" />
    <file src="..\MagiApiClient\bin\Debug\MagicApiClient.*" target="lib"></file>
    <file src="tools\" target="tools" />
    <file src="content\" target="content" />
  </files>
</package>

需要修改的欄位包含id、version、title、description、summary、projectUrl、iconUrl,另外範本預設會將放在lib、tools、content下的所有檔案打包。前面提到.nuspec可以設成直接抓取來自其他專案的內容,在以上範例我加了一個<file src="..\MagiApiClient\bin\Debug\MagicApiClient.*" target="lib"></file>,將MagicApiClient專案的bin\Debug\MagicApiClient.dll、MagicApiClient.pdb、MagicApiClient.xml打包裝入lib,如此其他專案引用時會有Intellisense提示函式、參數說明,出錯時還會顯示程式碼位置。

改完Package.nuspec,用Debug模式編譯,相關檔案就會打包成MagicApiClient.1.0.0.nupkg放在NuGet.Packager專案根目錄,已可手動上傳至NuGet Server,手動上傳方式可以參考之前的介紹

手動上傳有點遜,當然要做到點幾下滑鼠就自動上傳才酷,有幾個步驟:

  1. 編輯NuGet.Packager專案的nuget.config檔案,將私服加入packageSources
  2. 如果你的NuGet私服有設API Key(建議要設,以免阿貓阿狗亂傳蓋檔或被惡意人士下毒),要先設定上傳時使用的API Key。有兩種做法:
    第一種是使用nuget.exe,透過nuget.exe setApiKey my-api-key -Source httq://intranet-server/NuGetServer/nuget 指定特定伺服器所用的API Key。設定後,NuGet會將API Key加密儲存在目前帳號的%appdata%\NuGet\NgGet.config,之後由該帳號上傳至該NuGet Server就會自動引用。
    另一種做法是將API Key寫入NuGet.Packager專案的nuget.config,由於NuGet採取加密後儲存,要先用nuget setApiKey設定,再從%appdata%\NuGet\NuGet.config抄apiKeys設定。不過,NuGet config檔加密時用的是使用者專屬加密金鑰,故無法在多開發者間共享API Key設定。

修改後的nuget.config如下例:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <apikeys>
    <add key="httq://intranet-server/NuGetServer/nuget" value="AQAAANC…34uA==" />
  </apikeys>
  <packageSources>
    <add key="Private NuGet source" value="httq://intranet-server/NuGetServer/nuget" />
  </packageSources>
</configuration>

接者改用Relase模式編譯專案,MagicApiClient.1.0.0.nupkg就會自動上傳到NuGet伺服器囉~ 整個NuGet Package打包上傳的程序是不是變得簡單多了呢?NuGet Packager萬歲!

註:若NuGet Package已存在於NuGet Server,上傳的版號必須比現存版號高,否則會發生Package已存在無法覆寫的錯誤。


Comments

# by 余小章

Hi,黑大 有沒有考慮用TFS Build vNext https://dotblogs.com.tw/yc421206/2016/04/27/tfs2015_build_vnext_release_deploy_internal_nuget_server

# by Jeffrey

to 余小章,公司TFS環境升級速度跟不上,TFS Build vNext暫時派不上用場,殘念。

Post a comment