Search code examples
.netazure-devopsazure-pipelinesnugetazure-pipelines-yaml

Cache@2 Azure DevOps pipeline task fails


I'm trying to use the Cache@2 task to cache my nuget packages. Following the documentation, I've setup the following tasks:

variables:
  nugetPackages: $(Pipeline.Workspace)/.nuget/packages
  
stages:
  - stage: CI
    displayName: 'Continuous Integration'
    jobs:
      - job: 'CI'
        pool:
          vmImage: ubuntu-latest
        steps:
          - task: NuGetToolInstaller@1
            displayName: 'NuGet tool installer'

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

      - task: DotNetCoreCLI@2
        displayName: 'Restore Packages'
        inputs:
          command: 'restore'
          feedsToUse: 'select'
          vstsFeed: '<DevOpsArtifactFeedId>'
          projects: 'Solution.sln'

But in the Post-job task, it fails with:

tar: /home/vsts/work/1/.nuget/packages: Cannot open: No such file or directory

It seems that the nugetPackages path may be incorrect, but I'm not sure what it should be. Although looking at the nuget restore task, I can see log entries such as:

Installed System.Text.Json 7.0.0 from https://api.nuget.org/v3/index.json to /home/vsts/.nuget/packages/system.text.json/7.0.0

Which doesn't have the /work/1/ paths. I tried using $(Agent.HomeDirectory) instead of $(Pipeline.Workspace) but that didn't work either.

If I hard code the nugetPackages variable to '/home/vsts/.nuget/packages' then it works - but this feels dirty and I'd rather use an appropriate DevOps variable in case the path name changes


Solution

  • I agree with @Zdeněk Jelínek's comment to change the variable name nugetPackages to $(NUGET_PACKAGES). Also you need to change the restore task from DotNetCoreCLI@2 to NuGetCommand@2.

    According to the pipeline caching document, the NUGET_PACKAGES is an environment variable.

    If you use PackageReferences to manage NuGet dependencies directly within your project file and have a packages.lock.json file, you can enable caching by setting the NUGET_PACKAGES environment variable to a path under $(UserProfile) and caching this directory.

    When I tested the same yaml as yours in my pipeline, I can reproduce the same error in the Post-job task.

    enter image description here

    Then I changed to use the official document sample, the Post-job task works.

    However, when I only change the variable name nugetPackages to $(NUGET_PACKAGES) in your yaml, the pipeline still doesn't work. The difference is the restore task. So, I changed the restore task to NuGetCommand@2 restore . This time it works.

    enter image description here

    The changed yaml:

    variables:
      NUGET_PACKAGES: $(Pipeline.Workspace)/.nuget/packages
      
    stages:
      - stage: CI
        displayName: 'Continuous Integration'
        jobs:
          - job: 'CI'
            pool:
              vmImage: ubuntu-latest
            steps:
              - task: NuGetToolInstaller@1
                displayName: 'NuGet tool installer'
    
              - task: Cache@2
                inputs:
                  key: 'nuget | "$(Agent.OS)" | **/packages.lock.json,!**/bin/**,!**/obj/**'
                  restoreKeys: |
                    nuget | "$(Agent.OS)"
                    nuget
                  path: $(NUGET_PACKAGES)
                displayName: Cache NuGet packages
              - task: NuGetCommand@2
                displayName: 'NuGet restore'
                inputs:
                  command: 'restore'
                  restoreSolution: '**/*.sln'
                  feedsToUse: 'select'
                  vstsFeed: 'feedID'