Use an Expression as Part of the Cache Key in an Azure yml Pipeline

Viewed 201

I want to create a cache key from an expression in cache step located in a steps template. Since caches are imutable, I want to start with a clean cache every week or every months. My template file looks like this:

# steps-tpl.yml
steps:
- task: Cache@2
  inputs:
    key: compiler-cache | "<expression>" | "$(Agent.JobName)" | "$(Build.SourceBranch)" | "$(Build.SourceVersion)"
    restoreKeys: |
      compiler-cache | "<expression>" | "$(Agent.OS)" | "$(Agent.JobName)" | "$(Build.SourceBranch)" |  "$(Build.SourceVersion)"
      compiler-cache | "<expression>" | "$(Agent.OS)" | "$(Agent.JobName)" | "$(Build.SourceBranch)"
      compiler-cache | "<expression>" | "$(Agent.OS)" | "$(Agent.JobName)" | "refs/heads/master"
    path: $(Pipeline.Workspace)/ccache
  displayName: 'ccache/clcache: Warm up cache'

The expression should give me a different value each week of the year or for simplicity, the number of the current month.

I tried different things for expression and none of them worked. Firs I tried to put the expression into a parameter default value which didn't work. Then I tried to put the expression directly in place like this:

"${{ format('{0:MM}', pipeline.startTime) }}"

which didn't work either. And neither this:

"$[format('{0:MM}', pipeline.startTime)]"

I guess run-time expressions are not available outside a script context.

I even tried to set an environment variable in a step before the caching:

    echo '##vso[task.setvariable variable=COMPILER_CACHE_KEY_PREFIX,isOutput=true]$[ counter(format("{0:yyyMMdd}", pipeline.startTime), 7) ]'

and to use that with $(previousStep.COMPILER_CACHE_KEY_PREFIX) which didn't work either.

How can I put such an expression into the cache key? Is it possible at all?

2 Answers

I had to do something similar. What worked for me was setting a variable in a Powershell task, then using it with the syntax that expands at runtime:

variables:        
    - name: projectFolder
      value: ''


 # assign temporary variable resultfolder to variable projectFolder
 - powershell: |
        Write-Host "##vso[task.setvariable variable=projectFolder]$(resultfolder)"
   displayName: Save project folder path

 # refer to projectFolder, not the temporary variable resultfolder
 - task: Cache@2
   inputs:
     key: 'nuget | "$(Agent.OS)" | $(projectFolder)/packages.lock.json'
     restoreKeys: |
      nuget | "$(Agent.OS)"
     path: $(NUGET_PACKAGES)
   displayName: Cache NuGet packages

The Cache task outputs the following:

Resolving key:
 - nuget                                 [string]
 - "Windows_NT"                          [string]
 - D:\a\1\s\PTS_Tasks/packages.lock.json [file] --> 811E162D4016AFBA61F7850XXXXXXXXXXXXX366DFAC37C757FC4D4F49992
Resolved to: nuget|"Windows_NT"|/9Pr8Jh9L66tny00XXXXXXXXXXnL23DoLKFCDGhG8=

Showing that the variable projectFolder has been expanded correctly.

So perhaps execute your expression inside the Powershell script, then assign the result to a variable.

I'm not sure why it doesn't work directly in the Cache task, but this worked for me:

variables:
  cacheKeyDay: $[format('{0:ddMMyyyy}', pipeline.startTime)]

- task: Cache@2
  inputs:
    key: $(cacheKeyDay)
Related