azure-pipelinesnx-monorepo

How to use Cache@2 in Azure Pipeline to store NX cache without NX Cloud


I am working on a monorepo using Nx, and I am looking to optimize my build times by caching Nx results. However, I am not using Nx Cloud and want to achieve this using the Cache@2 task in Azure Pipelines.

I have read that Nx can store its cache locally, and I am looking to integrate this local cache with Azure Pipelines. However, I’m not sure how to properly configure the Cache@2 task to store and restore this cache.

Here are the relevant details:

I do not have a workspace.json file, but I do have an nx.json file.

I would appreciate it if you could provide an example of how to define the key and path for the cache, along with any necessary tasks to set up Nx caching.

  steps:
      - task: NodeTool@0
        inputs:
            versionSpec: '20.17.x'
        displayName: 'Install Node.js'

      - task: Cache@2
        inputs:
          key: 'npm | "$(Agent.OS)" | $(projectPath)/package-lock.json'
          path: '$(NODE_MODULES_CACHE_FOLDER)'
          cacheHitVar: NODE_MODULES_CACHE_RESTORED
          workingDirectory: '$(projectPath)'
        displayName: 'Restore node_modules cache'

      - task: Cache@2
        inputs:
          key: 'nx | "$(Agent.OS)" | $(projectPath)/nx.json'
          path: '$(NX_CACHE_FOLDER)'
          cacheHitVar: NX_CACHE_RESTORED
          workingDirectory: '$(projectPath)'
        displayName: 'Restore NX cache'

Here is my pipeline.yml file. The cache@2 works as intended and it does reduce the build time for nx builds. But the problem comes for the key of cache@2, right now I am using nx.json file as the fingerprint. But if anything changes in the source code, it still uses the old cache and never updates the cache until the nx.json is updated.

Any ideas how can I accomplish this?


Solution

  • When we use Cache task to cache related files in Azure Pipeline, it will use the Key set by the cache task to determine whether the cache needs to be updated.

    Refer to this doc: Pipeline caching

    key: should be set to the identifier for the cache you want to restore or save. Keys are composed of a combination of string values, file paths, or file patterns, where each segment is separated by a | character.

    The Key filed in cache task supports using file path or file patterns.

    In your case, when you set the key to single file(nx.json), the cache task will update only when the nx.json update.

    if anything changes in the source code, it still uses the old cache and never updates the cache until the nx.json is updated.

    Based on your requirement, you need to update the cache when the source code changes.

    To meet this requirement, you can define file patterns in the key field.

    For example: You can set the folder path and use wildcards to indicate that all files in the folder are counted as part of the key.

      - task: Cache@2
        inputs:
          key: 'nx | "$(Agent.OS)" | $(build.sourcesdirectory)/src/**'
          path: '$(NX_CACHE_FOLDER)'
          cacheHitVar: NX_CACHE_RESTORED
          workingDirectory: '$(projectPath)'
        displayName: 'Restore NX cache'
    

    Note: You can use single file and file patterns in key field at the same time. For example:

    key: 'nx | "$(Agent.OS)" |  $(projectPath)/nx.json | $(build.sourcesdirectory)/src/**'
    

    Result:

    enter image description here

    In this case, any changes in the folder will let the cache task to update the old cache.