Azure-devops-docs: Missing nuget example

Created on 25 Jul 2019  Â·  11Comments  Â·  Source: MicrosoftDocs/azure-devops-docs

would also be helpfull with a nuget example


Document Details

⚠ Do not edit this section. It is required for docs.microsoft.com ➟ GitHub issue linking.

Pri1 devops-cictech devopprod doc-enhancement stale-issue

Most helpful comment

Thanks for the tip, was not aware of this, looks like an easy option to add to projects

https://devblogs.microsoft.com/nuget/enable-repeatable-package-restores-using-a-lock-file/

Would be great to have a version of the task that is package ecosystem aware eg a select box with ‘npm,nuget,yarn,custom’ with some logic in each option like ‘use lock file’ or ‘use package references in solution file’ etc?

All 11 comments

Not really practical without wildcard support in keys (need to list all packages.config / csproj files), I guess they are waiting for if before adding the Nuget example.

Presumably this will require https://github.com/NuGet/Home/wiki/Centrally-managing-NuGet-packages to be available, since there isn't currently in-box support for a single 'package.lock' analog, similar to yarn and npm.

However, one could probably come pretty close if relying on the Microsoft.Build.CentralPackageVersions nuget package. Once you set up a solution with a Packages.props file, that file could act as the key, with the version numbers centrally managed. It's not a perfect translation, since transitive dependency versions aren't required to be mentioned, but I _think_ it would get the job done in a CI scenario.

I sketched out what the tasks would presumably look like, but I haven't been able to test because this update isn't yet deployed on my tenant of choice.

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

steps:
- task: CacheBeta@0
  inputs:
    key: |
      nuget
      $(Build.SourcesDirectory)/Package.props
    path: $(NUGET_PACKAGES)
  displayName: Cache nuget packages

- task: NuGetCommand@2
  displayName: 'NuGet restore **/*.sln'
  inputs:
    restoreSolution: '**/*.sln'

Note that this requires usage of <PackageReference> in all projects, since this restores packages to the global cache at $(NUGET_PACKAGES)

Why couldn't you cache the entire C:\Users\[username]\.nuget\packages directory?

The existing document's guidance recommends caching directories within the $(Pipeline.Workspace), so I incorporated that into my example. If pipeline caching can work in any directory, I suppose caching a user directory would work, but some downsides that come to mind:

  1. It's definitely not cross platform, so wouldn't work on a Linux agent (if you changed my example to restore using the dotnet cli, for instance)
  2. It would require that you know the user principle that will be used to execute the jobs, and that this is the same for all agents, and won't change.

Given that, setting the directory using the already-available environment variable certainly seems more robust.

@RehanSaeed. Because once created, cache contents are immutable (See above). You need a method to determine whether to rebuild the cache.

One option (short of using centralized versions), is to generate a string containing all the distinct PackageReference and/or packages.config entries in sorted order and use a hash as the cache key,

I see that a Nuget example has been added now, but I feel it's misleading. packages.lock.json is only available at the _project level_ right now. This might work for single-project solutions, but I doubt this is the norm for .Net applications.

To generate the key I wrote a powershell script to grab all of the NuGet package references from a solution (below) and run this powershell script in the pipeline before the cache task. It's working using the sample above with NUGET_PACKAGES variable set to $(Pipeline.Workspace)/.nuget/packages

==================== Yaml pipeline
- task: CacheBeta@0
displayName: 'Restore cache'
inputs:
key: 'scripts/packages.txt'
path: '$(NUGET_PACKAGES)'

==================== Create-Solution-Nuget-Packages-Hash.ps1
param
(
[string] $solutionPath=$(throw "The solution path is required"),
[string] $outputFilePath="$PSScriptRoot/packages.txt"
)

if(!(Test-Path $solutionPath)) {
Throw [System.IO.FileNotFoundException] "No solution file was found at $solutionPath"
}

Set-Location -Path (get-item $solutionPath).Directory
$projectList = Get-Content $solutionPath | where { $_ -Match ".csproj" } | where { $_ -match "Project.+, ""(.+)""," } | foreach { $matches[1] } | % { Get-Content $_ }
$nugetPackageList = [System.Collections.Generic.List[string]]::new()

foreach($i in $($projectList -split "rn")){
if($i -match " $nugetPackageList.Add($i)
}
}

$nugetPackageList = $nugetPackageList | Sort-Object -Unique

Write-Host "NuGet packages:"
Write-Host "=============="
Write-Host $nugetPackageList
Write-Host "=============="

Set-Content -Path "$outputFilePath" -Value $nugetPackageList -Force

Write-Host "Wrote list of NuGet packages to $outputFilePath"

In case it's not obvious the sample for powershell yaml is below but in reality I use the Agent.TempDirectory

- task: PowerShell@2
  inputs:
    filePath: 'scripts/Create-Solution-Nuget-Packages-Hash.ps1'
    arguments: '-solutionPath "Test.sln" -outputFilePath "scripts/packages.txt"'
    failOnStderr: true
    pwsh: true

@dammejed @alanwales Comparing to the Maven example, would this not work?

- task: CacheBeta@0
  inputs:
    key: nuget | **/packages.lock.json
    path: $(NUGET_PACKAGES)
  displayName: Cache NuGet packages

Thanks for the tip, was not aware of this, looks like an easy option to add to projects

https://devblogs.microsoft.com/nuget/enable-repeatable-package-restores-using-a-lock-file/

Would be great to have a version of the task that is package ecosystem aware eg a select box with ‘npm,nuget,yarn,custom’ with some logic in each option like ‘use lock file’ or ‘use package references in solution file’ etc?

This issue hasn't been updated in more than 180 days, so we've closed it. If you feel the issue is still relevant and needs fixed, please reopen it and we'll take another look. We appreciate your feedback and apologize for any inconvenience.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

cijujoseph picture cijujoseph  Â·  3Comments

dtamai picture dtamai  Â·  3Comments

robinmanuelthiel picture robinmanuelthiel  Â·  3Comments

atrauzzi picture atrauzzi  Â·  3Comments

adnanebrahimi picture adnanebrahimi  Â·  3Comments