Udostępnij za pośrednictwem


Buforuj pakiety NuGet

Azure DevOps Services | Azure DevOps Server 2022 | Azure DevOps Server 2020

Buforowanie potoków pomaga skrócić czas kompilacji, przechowując zależności do ponownego użycia w przyszłych uruchomieniach. Z tego artykułu dowiesz się, jak używać zadania Cache do buforowania i przywracania pakietów NuGet.

Uwaga

Buforowanie potoków nie jest obsługiwane w potokach wersji klasycznych.

Wymagania wstępne

produkt Wymagania
Azure DevOps projekt usługi Azure DevOps.
Uprawnienia: -
    — Aby udzielić dostępu do wszystkich potoków w projekcie, musisz być członkiem grupy Administratorzy Projektu .

Blokowanie zależności

Przed skonfigurowaniem zadania pamięci podręcznej należy zablokować zależności projektu i wygenerować plik package.lock.json. Unikatowy klucz cache jest tworzony na podstawie skrótu zawartości tego pliku blokującego, w celu zapewnienia spójności w kompilacjach.

Aby zablokować zależności projektu, dodaj właściwość RestorePackagesWithLockFile do pliku csproj i ustaw ją na wartość true. Po uruchomieniu nuget restoreprogram generuje plik packages.lock.json w katalogu głównym projektu. Upewnij się, że dodajesz plik packages.lock.json do swojego kodu źródłowego.

<PropertyGroup>
  <RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
</PropertyGroup>

Buforowanie pakietów NuGet

Aby buforować pakiety NuGet, zdefiniuj zmienną potoku wskazującą lokalizację pakietów na agencie, na którym działa potok.

W poniższym przykładzie zawartość packages.lock.json jest hashowana, aby wygenerować dynamiczny klucz pamięci podręcznej. Gwarantuje to, że za każdym razem, gdy plik ulegnie zmianie, zostanie utworzony nowy klucz pamięci podręcznej.

Zrzut ekranu przedstawiający sposób generowania klucza pamięci podręcznej w usłudze Azure Pipelines.

variables:
  NUGET_PACKAGES: $(Pipeline.Workspace)/.nuget/packages

- task: Cache@2
  displayName: Cache v2 task 
  inputs:
    key: 'nuget | "$(Agent.OS)" | **/packages.lock.json,!**/bin/**,!**/obj/**'
    restoreKeys: |
       nuget | "$(Agent.OS)"
       nuget
    path: '$(NUGET_PACKAGES)'
    cacheHitVar: 'CACHE_RESTORED'

Uwaga

Pamięci podręczne są niezmienne, po utworzeniu pamięci podręcznej nie można modyfikować jego zawartości.

Przywracanie pamięci podręcznej

Następujące zadanie zostanie uruchomione tylko wtedy, gdy zmienna CACHE_RESTORED jest false. Oznacza to, że jeśli wystąpi trafienie w pamięci podręcznej (pakiety są już dostępne w pamięci podręcznej), krok przywracania zostanie pominięty, co pozwala zaoszczędzić czas i zasoby. Jeśli pamięć podręczna nie zostanie znaleziona, polecenie przywracania zostanie uruchomione w celu pobrania niezbędnych zależności.

- task: NuGetCommand@2
  condition: ne(variables.CACHE_RESTORED, true)
  inputs:
    command: 'restore'
    restoreSolution: '**/*.sln'

Uwaga

Jeśli używasz systemu Ubuntu 24.04 lub nowszego, musisz użyć zadania NuGetAuthenticate z interfejsem wiersza polecenia platformy .NET zamiast zadania NuGetCommand@2. Aby uzyskać więcej informacji, zobacz Support for newer Ubuntu hosted images (Obsługa nowszych obrazów hostowanych w systemie Ubuntu).

Obsługa błędów "nie znalezionoproject.assets.json"

Jeśli wystąpi błąd "nie znalezionoproject.assets.json" podczas zadania kompilacji, usuń warunek condition: ne(variables.CACHE_RESTORED, true) z zadania przywracania. Dzięki temu polecenie przywracania zostanie uruchomione i wygeneruje plik project.assets.json. Zadanie przywracania nie będzie ponownie pobierać pakietów, które są już obecne w odpowiednim folderze.

Uwaga

Pipeline może zawierać wiele zadań buforowania, a zadania i prace w tym samym pipeline mogą uzyskiwać dostęp do tej samej pamięci podręcznej i ją współdzielić.

Porównanie wydajności

Buforowanie potoków znacznie skraca czas wymagany do przywrócenia zależności, co prowadzi do szybszej budowy. Poniższe porównanie ilustruje wpływ buforowania na czas wykonywania potoku dla dwóch różnych potoków:

  • Bez buforowania (po prawej): zadanie przywracania trwało około 41 sekund.

  • Z buforowaniem (po lewej): Dodaliśmy zadanie buforowania do drugiej sekwencji zadań i skonfigurowaliśmy zadanie przywracania do uruchomienia tylko wtedy, gdy wystąpi brak trafienia w pamięci podręcznej. Zadanie przywracania w tym przypadku zostało ukończone w ciągu zaledwie 8 sekund.

Zrzut ekranu przedstawiający wydajność potoku z buforowaniem i bez niego.

Poniżej znajduje się pełny YAML przepływ do odniesienia.

pool:
  vmImage: 'windows-latest'

variables:
  solution: '**/*.sln'
  buildPlatform: 'Any CPU'
  buildConfiguration: 'Release'
  NUGET_PACKAGES: $(Pipeline.Workspace)/.nuget/packages

steps:
- task: NuGetToolInstaller@1
  displayName: 'NuGet tool installer'

- task: Cache@2
  displayName: 'NuGet Cache'
  inputs:
    key: 'nuget | "$(Agent.OS)" | **/packages.lock.json,!**/bin/**,!**/obj/**'
    restoreKeys: |
       nuget | "$(Agent.OS)"
       nuget
    path: '$(NUGET_PACKAGES)'
    cacheHitVar: 'CACHE_RESTORED'

- task: NuGetCommand@2
  displayName: 'NuGet restore'
  condition: ne(variables.CACHE_RESTORED, true)
  inputs:
    command: 'restore'
    restoreSolution: '$(solution)'

- task: VSBuild@1
  displayName: 'Visual Studio Build'
  inputs:
    solution: '$(solution)'
    platform: '$(buildPlatform)'
    configuration: '$(buildConfiguration)'

Takie podejście dotyczy również projektów platformy .NET Core, pod warunkiem że projekt używa packages.lock.json do blokowania wersji pakietów. Możesz to włączyć, ustawiając RestorePackagesWithLockFile na True w pliku * Csproj* lub uruchamiając następujące polecenie: dotnet restore --use-lock-file.