Azure DevOps 在 Pipeline 使用外部套件來源

  • 300
  • 0

前言

現在開發上越來越依賴使用 NuGet 來管理套件,專案和團隊變大之後就會開始把一些共用的函示庫抽離並打包成 NuGet 套件,而這些套件屬於公司內部使用,所以就會需要有私有的 NuGet,這時候可以有兩種方案,一個是使用一個共用的資料夾或是 Azure DevOps 上的 Artifacts 來管理套件,這時候如果有設定 Azure DevOps 的 CI/CD 的話,就需要多一點設定才可以連接到這些非官方 NuGet 的外部套件來源,本文就來介紹如何設定以及需要注意的點。

實做

設定外部套件來源

要設定專案使用外部的套件來源,除了從 Visual Studio 設定上新增一個全域的套件來源之外,也可以在專案目錄底下新增一個 nuget.config 檔案來設定外部來源。

點選工作選單 → 工具 → 選項 → NuGet 套件管理員,就可以新增其它的外部套件來源。

但是有時候這個外部來源並非每個專案都會使用,所以可以透過在專案目錄 .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 套件時候看到我們設定的外部來源了。

我在專案裡面分別使用 Local 和 Artifacts 的套件。

主程式就單純呼叫 HelloWorld 方法。

new AnYunNuGet.AnYunLib().HelloWorld();
new AnYunLocalLib.AnYunLib().HelloWorld();

直接測試之後可以正確還原套件並執行。

到此就完成了我們專案的設定了,再來就是把專案推到 Azure DevOps 的 Repos 裡面並且設定後面的 Pipeline。整個目錄的檔案和結構大致如下,記得也要把 Local 的 NuGet 加入版控。

設定 Pipeline

原來想說是 .NET Core 應該很簡單的新增 .NET Core 的 Restore Task 來還原專案就可以了,很高興的設定好之後執行,就會發生錯誤了…

從錯誤訊息中可以發現 NuGet 在還原套件的時候目錄是錯誤的,並非在我們專案檔底下額外新增的目錄檔案。

解決路徑問題之後就會再遇到另一個問題就是 Artifact 會無法正確的存取。

所以我們會有兩個問題需要解決:

  1. Local NuGet 路徑問題
  2. Artifacts 授權驗證問題

Local NuGet 路徑問題

從錯誤訊息可以得知是路徑問題,那就用最直接的方式,把 NuGet 套件複製到執行的路徑。

新增 Command Line 的 Task,並取執行建立目錄的指令:mkdir $(Agent.BuildDirectory)\Nuget\.nuget\NuGet

接下來新增 Copy Files 的 Task 並且選擇要複製的目錄和前面我們所建立的目錄。

如果單純要解決 local 的路徑問題可以這樣設定並執行就可以在還原時候找到套件了,但是後面還有一個問題待處理,就會發現有更快的解決方案,這會在後面一起說明。

Artifacts 授權驗證問題

首先點選右上角的選單來產生 Token。

權限選擇 Packaging 下的 Read 權限即可。

建立完成之後先把 Token 記錄下來備用。

接下來新增 NuGet 這一個 Task,而非前面的 DotNet Restore 了,不然就會失敗,雖然可以設定的選項幾乎一樣,但是使用 DotNet Restore 就會失敗,這邊我卡了很久,想說都設定對,為什麼還是會驗證失敗…

選擇我們在專案目錄底下建立的 nuget.config,並且選擇授權的設定,如果沒有的話就點選旁邊的新增,來新增一個新的設定。

新增授權時候輸入 Artifact 位址和我們前面建立的 Token 儲存就完成了。

這樣就完成設定了,然後直接之後就可以正確執行了。

而這邊改用 NuGet 也可以直接解決前面 Local 套件來源的問題,就可以不需要用複製檔案的方來來暴力處理了。

結論

因為專案是 .NET Core 專案就很自然的選用相對應的 Task 來做還原,結果很多行為都不如預期的執行,花了不少時間比對和測試終於設定完成,原來只要改用 NuGet Task 來設定就好了,明明可以設定的參數和畫面都一樣但是使用 DotNet Restore 就會失敗,調整之後兩種外部套件的情境都可以解決,希望對有遇到相同情境的朋友會有幫助。

參考資料