Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Caching npm dependency with github action

I want to cache npm dependencies so that I does not do npm install every time I push and instead just load it from cache.

I think github action support this now?: How do I cache steps in GitHub actions?

Here are few cases

  • If package.json changes, which means yarn.lock or package-lock.json changed so do npm install and update cache
  • Extending my above point, the contributor could be doing both yarn install and npm install

From the same above question, I changed my github action to something like this

name: Tsc compilation test
on: [push, pull_request]
jobs:
  build:
    name: Build
    runs-on: ubuntu-18.04
    steps:
      - name: Checkout
        uses: actions/checkout@v2
      - name: Cache NPM dependencies
        uses: actions/cache@v1
        with:
          path: ~/.npm
          key: ${{ runner.OS }}-npm-cache-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.OS }}-npm-cache-
      - name: Install dependencies
        run: npm install
      - name: Test tsc
        run: npm run ts-compile-check

This still does npm install and haven't reduced my computation time for installing dependencies (So I am not sure if this is working correctly or not)

Then I did yarn install axios hoping it would update my cache but in post-install I see this as logged

Post job cleanup.
Cache hit occurred on the primary key Linux-npm-cache-, not saving cache.

So here is my questions, Is it possible to achieve

  • If package.json changes, which means yarn.lock or package-lock.json changed so do npm install and update cache
  • Extending my above point, the contributor could be doing both yarn install and npm install

And can someone explain me this

    with:
      path: ~/.npm
      key: ${{ runner.OS }}-npm-cache-${{ hashFiles('**/package-lock.json') }}
      restore-keys: |
        ${{ runner.OS }}-npm-cache-
like image 778
iRohitBhatia Avatar asked Oct 06 '20 12:10

iRohitBhatia


1 Answers

In order to have efficient caching with GitHub actions there needs to be a package-lock.json or yarn.lock present. This file is automatically generated when installing packages. If you want more information about package-lock.json, check out the docs.

Now there's the subject of whether npm and yarn should be used in the same project. More about that subject here.

Based on the question, let's assume that both a package-lock.json and yarn.lock exists. If you're only using one of both, feel free to remove one from below. The config below is for yarn version 2 which uses yarn config get cacheFolder to get the cache folder. For another yarn version see the docs.

name: Tsc compilation test
on: [push, pull_request]
jobs:
  build:
    name: Build
    runs-on: ubuntu-18.04
    steps:
      - name: Checkout
        uses: actions/checkout@v2

      - name: Get yarn cache directory path
        id: yarn-cache-dir-path
        run: echo "::set-output name=dir::$(yarn config get cacheFolder)"

      - name: Cache yarn dependencies
        uses: actions/cache@v2
        with:
          path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
          key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
          restore-keys: |
            ${{ runner.os }}-yarn-

      - name: Cache npm dependencies
        uses: actions/cache@v2
        with:
          path: '~/.npm'
          key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-node-

      - name: Install dependencies
        run: npm install # or yarn install

      - name: Test tsc
        run: npm run ts-compile-check

That's it! Well except for one more thing. Above we're using ~/.npm for caching npm dependencies. Performance wise it would be quicker to cache **/node_modules however in some cases this would introduce conflicts. Feel free to experiment to see which one works for you. More about that here and here.


From your question you also asked to explain the following code:

    with:
      path: ~/.npm
      key: ${{ runner.OS }}-npm-cache-${{ hashFiles('**/package-lock.json') }}
      restore-keys: |
        ${{ runner.OS }}-npm-cache-

https://github.com/actions/cache#usage:

path - A list of files, directories, and wildcard patterns to cache and restore. See @actions/glob for supported patterns.
key - An explicit key for restoring and saving the cache
restore-keys - An ordered list of keys to use for restoring the cache if no cache hit occurred for key

Therefore the code above:

  • path is the folder that will be cached/restored (where the dependencies are installed)
  • key is a unique identifier for the path that will be cached. In this case it hashes the contents of any **/package-lock.json file using hashFiles. Basically when the package-lock.json file changes, that means that the dependencies changed, and the cache shouldn't be used.
  • restore-keys is basically a default key to use in case there's no match for the key
like image 132
Patrick Avatar answered Nov 16 '22 03:11

Patrick