Hi
I'd like to lint my react-based codebase with github actions and use this library to optimize the job duration.
My yaml file for workflow configure is here:
name: ESLint
on: [push]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v2
- name: setup node
uses: actions/setup-node@v1
with:
node-version: "12"
- name: cache node modules
id: cache-node_modules
uses: actions/cache@v1
env:
cache-name: cache-node-modules
with:
path: ~/.npm
key: ${{ runner.os }}-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-${{ env.cache-name }}-
- name: install dependencies
if: steps.cache-node_modules.outputs.cache-hit != 'true'
run: npm ci
- name: run eslint
run: npm run lint
At first the cache doesn't hit, npm ci is triggered, this job works and the generated cache is posted to ~/.npm dir.
Post job cleanup.
/bin/tar -cz -f /home/runner/work/_temp/885b6838-636b-49ea-a563-41734fd8977d/cache.tgz -C /home/runner/.npm .
Cache saved successfully
Next time I run this job, github actions restore cache successfully, as I intended.
Run actions/cache@v1
with:
path: ~/.npm
key: Linux-cache-node-modules-1001ef79e1a0df9c0bf9013e62376251ae8ec7cb518016d4da61abfc8087539a
restore-keys: Linux-cache-node-modules-
env:
cache-name: cache-node-modules
Cache Size: ~46 MB (48000811 B)
/bin/tar -xz -f /home/runner/work/_temp/b378e123-f68d-4e18-87d6-7942df1629b7/cache.tgz -C /home/runner/.npm
Cache restored from key: Linux-cache-node-modules-1001ef79e1a0df9c0bf9013e62376251ae8ec7cb518016d4da61abfc8087539a
But the step of npm run lint somehow fails.
> [email protected] lint /home/runner/work/Jinrikisha-client/Jinrikisha-client
> eslint src/*/.{ts,tsx}
sh: 1: eslint: not found
...(some npm ERRs)
npm WARN Local package.json exists, but node_modules missing, did you mean to install?
npm ERR! A complete log of this run can be found in:
npm ERR! /home/runner/.npm/_logs/2020-05-10T05_25_36_742Z-debug.log[error]Process completed with exit code 1.
I used another cache by changing the key to ${{ runner.os }}-${{ env.cache-name }}-v2-${{ hashFiles('**/package-lock.json') }} and the restore key to ${{ runner.os }}-${{ env.cache-name }}-v2- but the result ends up in the same way.
This may be related to https://github.com/actions/cache/issues/281
👋 Hey @bokusunny, your cache path is ~/.npm which is the NPM cache directory that NPM will use when running npm install or npm ci, it does not include node_modules. You should either change your path to node_modules and switch to npm install, or always run npm ci in your workflow.
Well, you should definitely avoid caching node_modules.
I am experiencing the same issue when trying to use yarn workspaces. Dependencies are missing when using the yarn cache.
Have you checked the various examples linked to the README?
Yes. I followed the example for yarn. The following is how my workflow looks with the yarn example
name: Install/Restore Prerequisites
# This job runs on Linux
runs-on: macos-10.15
steps:
- uses: actions/checkout@v2
- name: Use Node.js 10.15
uses: actions/setup-node@v1
with:
node-version: '10.15'
- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- uses: actions/cache@v1
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: Install project dependencies
if: steps.yarn-cache.outputs.cache-hit != 'true' # Over here!
run: yarn
- name: Lint
run: yarn lint
The lint command then runs eslint across each workspace. I have 5 workspaces in the mono repo.
I get the following error when trying to run eslint:
â–¸ Using input files from .eslintrc.json
error Command "eslint" not found.
Remove this if: steps.yarn-cache.outputs.cache-hit != 'true'
Additionally, using restore-keys means you won't always get an exact match of your dependencies, so some will be missing.
Well, you should definitely avoid caching
node_modules.
I've read the warning for npm
Note: It is not recommended to cache
node_modules, as it can break across Node versions and won't work withnpm ci
but is that true for yarn as well? yarn recommends caching node_modules, at least for GitLab CI.
Yes, that's true for yarn as well. Also, where is the warranty that GitLab is correct?
It's not GitLab recommending it, it's the official yarn documentation for yarn 1.x (hence classic.yarnpkg.com)
So if I use the same Node version always, it _should be_ okay to cache it, correct?
Oops, I see. Well, it depends on what you want. For example, yarn --frozen-lockfile and npm ci will check if the dependencies are reproducible even though the cache is still usable for you. Also, in this case, something like a post-install will work correctly. But, if you cache node_modules, they aren't available. If you fully understand what you are doing, it should be fine.
This is the real world problem if post-install is not available. https://docs.cypress.io/guides/guides/continuous-integration.html#Caching
using yarn install --frozen-lockfile has decreased the install time from ~5mins to ~2mins on a macos-latest machine for me
Example:
- name: "Get yarn cache"
uses: actions/cache@v1
id: yarn-cache
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: Install Dependencies
run: yarn install --frozen-lockfile
@walterholohan
using
yarn install --frozen-lockfilehas decreased the install time from ~5mins to ~2mins on amacos-latestmachine for meExample:
- name: "Get yarn cache" uses: actions/cache@v1 id: yarn-cache with: path: ${{ steps.yarn-cache-dir-path.outputs.dir }} key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} restore-keys: | ${{ runner.os }}-yarn- - name: Install Dependencies run: yarn install --frozen-lockfileTime for me:
yarn install~1 min 40s
yarn install --frozen-lockfile ~50s
yarn install --frozen-lockfile --prefer-offline ~40s
Going to close this issue out.
To summarize:
Using restore-keys means you're not guaranteed to have an exact cache hit and some dependencies could be missing. Using the cache-hit output variable can work for some scenarios, but depending on your ecosystem and the contents of your cache, you may want to run the install step to ensure consistency.
This specific issue was from caching the npm cache, which won't populate any node_modules.
Thanks all for your feedback and suggestions 😄
Most helpful comment
Going to close this issue out.
To summarize:
Using
restore-keysmeans you're not guaranteed to have an exact cache hit and some dependencies could be missing. Using thecache-hitoutput variable can work for some scenarios, but depending on your ecosystem and the contents of your cache, you may want to run the install step to ensure consistency.This specific issue was from caching the npm cache, which won't populate any
node_modules.Thanks all for your feedback and suggestions 😄