Search code examples
cachinggoogle-cloud-storagenode-modulesgoogle-cloud-build

How to zip yarn global folder for reuse in subsequent Google Cloud Build runs


I'm trying to cache my node_module dependencies to speed up my build time, but the zip file that results is empty. With inspiration from THIS response to another question I have the following cloudbuild.yaml.

steps:
  - id: 'download-cached-yarn-dependencies'
    name: gcr.io/cloud-builders/gsutil
    entrypoint: bash
    args:
      - '-c'
      - |
        gsutil cp gs://${PROJECT_ID}_cloudbuild/my-app.cache.tgz build-cache.tgz || exit 0
        tar -zxf build-cache.tgz || exit 0


  - id: install
    name: $_NODE
    entrypoint: 'bash'
    args:
      - '-c'
      - |
        mkdir .yarn-cache
        yarn config set enableGlobalCache true
        yarn config set globalFolder .yarn-cache
        yarn install --immutable

  - id: 'upload-cached-yarn-dependencies'
    name: gcr.io/cloud-builders/gsutil
    entrypoint: bash
    args:
      - '-c'
      - |
        tar -zcvf build-cache.tgz .yarn-cache
        gsutil cp build-cache.tgz gs://${PROJECT_ID}_cloudbuild/my-app.cache.tgz

The only thing that I modified from the previous ANSWER was to add mkdir .yarn-cache to avoid a "Cannot stat: No such file or directory" error.

This build successfully created a my-app.cache.tgz file in my storage bucket, but when unzipped, it is empty.

I also tried to remove the line yarn config set globalFolder .yarn-cache and use the default cache folder /usr/local/share/.config/yarn/global (SOURCE) but this also gave a "Cannot stat: No such file or directory" error.

How can I successfully zip the global folder for reuse in later builds?


Solution

  • I've modified my approach based on THIS answer to another question.

    steps:
      # retrieve the cached node_modules from Cloud Storage
      - id: get-cache
        waitFor: ['-']
        name: 'gcr.io/cloud-builders/gsutil'
        # This approach should work for unpacking the local npm package cache.
        script: |
          #!/usr/bin/env bash
          set -Eeuo pipefail
          gsutil -m cp gs://${PROJECT_ID}_cloudbuild/node_modules.cache.tgz  /tmp/build-cache.tgz || echo "Cache archive not found!"
          tar -xzf /tmp/build-cache.tgz || echo "Cache archive not found!"
    
      # Install dependencies
      - id: install
        waitFor: ['get-cache']
        name: $_NODE
        entrypoint: 'bash'
        args:
          - '-c'
          - |
            yarn install --immutable --frozen-lockfile
    
      # Zip and upload the node_modules to Cloud Storage
      # - Uncomment to update the cache
      # - comment out to speed up the build
      - id: cache-node-dependencies
        name: 'gcr.io/cloud-builders/gsutil'
        waitFor: ['install']
        script: |
          #!/usr/bin/env bash
          set -Eeuo pipefail
          tar -czf /tmp/cache.tar.gz ./node_modules &&
          gsutil -m cp /tmp/cache.tar.gz gs://${PROJECT_ID}_cloudbuild/node_modules.cache.tgz