前言
現在開發上越來越依賴使用 NuGet 來管理套件,專案和團隊變大之後就會開始把一些共用的函示庫抽離並打包成 NuGet 套件,而這些套件屬於公司內部使用,所以就會需要有私有的 NuGet,這時候可以有兩種方案,一個是使用一個共用的資料夾或是 Azure DevOps 上的 Artifacts 來管理套件,這時候如果有設定 Azure DevOps 的 CI/CD 的話,就需要多一點設定才可以連接到這些非官方 NuGet 的外部套件來源,本文就來介紹如何設定以及需要注意的點。
實做
設定外部套件來源
要設定專案使用外部的套件來源,除了從 Visual Studio 設定上新增一個全域的套件來源之外,也可以在專案目錄底下新增一個 nuget.config 檔案來設定外部來源。
點選工作選單 → 工具 → 選項 → NuGet 套件管理員,就可以新增其它的外部套件來源。
![](https://dotblogsfile.blob.core.windows.net/user/anyun/aa88c483-e6bd-44bc-a773-24a9d0ef8e49/1660393678.png.png)
但是有時候這個外部來源並非每個專案都會使用,所以可以透過在專案目錄 .sln 或 .csproj 檔案同一層目錄下新增 nuget.config 檔案,或是透過底下指令來新增。
dotnet new nugetconfig
預設檔案的內容如下,其中 <clear />
會把全域的設定清除,只使用檔案設定的套件來源。這時候再去打開設定內的 NuGet 套件來源就會只顯示我們設定的套件來源了。
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<!--To inherit the global NuGet package sources remove the <clear/> line below -->
<clear />
<add key="nuget" value="https://api.nuget.org/v3/index.json" />
</packageSources>
</configuration>
接下來修改檔案加上後面範例會用到的兩個外部來源,一個是本機目錄來源,就單純設定好路徑即可,一個是 Artifacts。這邊範例是我在專案目錄底下新增 .nuget/NuGet 目錄並且把打包好的 NuGet 套件放在裡面。
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<!--To inherit the global NuGet package sources remove the <clear/> line below -->
<clear />
<add key="nuget" value="https://api.nuget.org/v3/index.json" />
<add key="Local" value=".\.nuget\NuGet" />
<add key="MyNuGet" value="https://pkgs.dev.azure.com/{org}/{project}/_packaging/{packagename}/nuget/v3/index.json" />
</packageSources>
</configuration>
重新打開專案檔案就可以在新增 NuGet 套件時候看到我們設定的外部來源了。
![](https://dotblogsfile.blob.core.windows.net/user/anyun/aa88c483-e6bd-44bc-a773-24a9d0ef8e49/1660394549.png.png)
我在專案裡面分別使用 Local 和 Artifacts 的套件。
![](https://dotblogsfile.blob.core.windows.net/user/anyun/aa88c483-e6bd-44bc-a773-24a9d0ef8e49/1660394613.png.png)
主程式就單純呼叫 HelloWorld 方法。
new AnYunNuGet.AnYunLib().HelloWorld();
new AnYunLocalLib.AnYunLib().HelloWorld();
直接測試之後可以正確還原套件並執行。
![](https://dotblogsfile.blob.core.windows.net/user/anyun/aa88c483-e6bd-44bc-a773-24a9d0ef8e49/1660394737.png.png)
到此就完成了我們專案的設定了,再來就是把專案推到 Azure DevOps 的 Repos 裡面並且設定後面的 Pipeline。整個目錄的檔案和結構大致如下,記得也要把 Local 的 NuGet 加入版控。
![](https://dotblogsfile.blob.core.windows.net/user/anyun/aa88c483-e6bd-44bc-a773-24a9d0ef8e49/1660395831.png.png)
設定 Pipeline
原來想說是 .NET Core 應該很簡單的新增 .NET Core 的 Restore Task 來還原專案就可以了,很高興的設定好之後執行,就會發生錯誤了…
![](https://dotblogsfile.blob.core.windows.net/user/anyun/aa88c483-e6bd-44bc-a773-24a9d0ef8e49/1660395976.png.png)
從錯誤訊息中可以發現 NuGet 在還原套件的時候目錄是錯誤的,並非在我們專案檔底下額外新增的目錄檔案。
![](https://dotblogsfile.blob.core.windows.net/user/anyun/aa88c483-e6bd-44bc-a773-24a9d0ef8e49/1660395726.png.png)
解決路徑問題之後就會再遇到另一個問題就是 Artifact 會無法正確的存取。
![](https://dotblogsfile.blob.core.windows.net/user/anyun/aa88c483-e6bd-44bc-a773-24a9d0ef8e49/1660396197.png.png)
所以我們會有兩個問題需要解決:
- Local NuGet 路徑問題
- Artifacts 授權驗證問題
Local NuGet 路徑問題
從錯誤訊息可以得知是路徑問題,那就用最直接的方式,把 NuGet 套件複製到執行的路徑。
新增 Command Line 的 Task,並取執行建立目錄的指令:mkdir $(Agent.BuildDirectory)\Nuget\.nuget\NuGet
![](https://dotblogsfile.blob.core.windows.net/user/anyun/aa88c483-e6bd-44bc-a773-24a9d0ef8e49/1660396856.png.png)
接下來新增 Copy Files 的 Task 並且選擇要複製的目錄和前面我們所建立的目錄。
![](https://dotblogsfile.blob.core.windows.net/user/anyun/aa88c483-e6bd-44bc-a773-24a9d0ef8e49/1660396961.png.png)
如果單純要解決 local 的路徑問題可以這樣設定並執行就可以在還原時候找到套件了,但是後面還有一個問題待處理,就會發現有更快的解決方案,這會在後面一起說明。
Artifacts 授權驗證問題
首先點選右上角的選單來產生 Token。
![](https://dotblogsfile.blob.core.windows.net/user/anyun/aa88c483-e6bd-44bc-a773-24a9d0ef8e49/1660397228.png.png)
權限選擇 Packaging 下的 Read 權限即可。
![](https://dotblogsfile.blob.core.windows.net/user/anyun/aa88c483-e6bd-44bc-a773-24a9d0ef8e49/1660397362.png.png)
建立完成之後先把 Token 記錄下來備用。
![](https://dotblogsfile.blob.core.windows.net/user/anyun/aa88c483-e6bd-44bc-a773-24a9d0ef8e49/1660397410.png.png)
接下來新增 NuGet 這一個 Task,而非前面的 DotNet Restore 了,不然就會失敗,雖然可以設定的選項幾乎一樣,但是使用 DotNet Restore 就會失敗,這邊我卡了很久,想說都設定對,為什麼還是會驗證失敗…
![](https://dotblogsfile.blob.core.windows.net/user/anyun/aa88c483-e6bd-44bc-a773-24a9d0ef8e49/1660397547.png.png)
選擇我們在專案目錄底下建立的 nuget.config,並且選擇授權的設定,如果沒有的話就點選旁邊的新增,來新增一個新的設定。
![](https://dotblogsfile.blob.core.windows.net/user/anyun/aa88c483-e6bd-44bc-a773-24a9d0ef8e49/1660397759.png.png)
新增授權時候輸入 Artifact 位址和我們前面建立的 Token 儲存就完成了。
![](https://dotblogsfile.blob.core.windows.net/user/anyun/aa88c483-e6bd-44bc-a773-24a9d0ef8e49/1660397947.png.png)
這樣就完成設定了,然後直接之後就可以正確執行了。
![](https://dotblogsfile.blob.core.windows.net/user/anyun/aa88c483-e6bd-44bc-a773-24a9d0ef8e49/1660398341.png.png)
而這邊改用 NuGet 也可以直接解決前面 Local 套件來源的問題,就可以不需要用複製檔案的方來來暴力處理了。
結論
因為專案是 .NET Core 專案就很自然的選用相對應的 Task 來做還原,結果很多行為都不如預期的執行,花了不少時間比對和測試終於設定完成,原來只要改用 NuGet Task 來設定就好了,明明可以設定的參數和畫面都一樣但是使用 DotNet Restore 就會失敗,調整之後兩種外部套件的情境都可以解決,希望對有遇到相同情境的朋友會有幫助。