Skip to content

Commit a2c5a89

Browse files
authored
fix(ci): cache every workspace's node_modules, not just the root and one app (#9596)
The node_modules cache saved only `node_modules` and `apps/loopover-ui/node_modules`. npm decides per dependency whether it hoists to the root or nests under a workspace, and that decision moves whenever a version range changes -- #8608's eslint-10 bump nested `@eslint/js` under both UI apps, so on a cache HIT `apps/loopover-miner-ui/node_modules` did not exist at all and `eslint .` died with "Cannot find module '@eslint/js'", failing UI lint on every PR. It reproduces on no developer machine, because a real npm ci/npm install always creates those directories. Glob `apps/*` + `packages/*` (the workspace globs from package.json) so the cache follows npm's layout automatically instead of re-breaking on the next hoist change. review-enrichment and control-plane are not workspaces -- they keep their own installs and their own cache steps.
1 parent b19111d commit a2c5a89

1 file changed

Lines changed: 14 additions & 2 deletions

File tree

.github/actions/setup-workspace/action.yml

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,23 @@ runs:
5151
with:
5252
path: |
5353
node_modules
54-
apps/loopover-ui/node_modules
54+
apps/*/node_modules
55+
packages/*/node_modules
5556
# hashFiles('.nvmrc') matters as much as the package manifests and lockfile: a Node bump
5657
# with no lockfile change would otherwise still hit and silently reuse node_modules whose
5758
# native addons (sharp, workerd, fsevents) were compiled against the OLD Node's ABI. The
5859
# manifests matter too because npm ci validates package.json/package-lock.json consistency
5960
# and runs lifecycle scripts from package.json; a package.json-only change must not skip it.
61+
#
62+
# The path list must cover EVERY workspace's own node_modules, not just the root and one app.
63+
# npm decides per dependency whether it hoists to the root or nests under a workspace, and that
64+
# decision moves whenever a version range changes: the #8608 eslint-10 bump nested `@eslint/js`
65+
# under both UI apps, so on a cache HIT `apps/loopover-miner-ui/node_modules` did not exist at all
66+
# and `eslint .` died with "Cannot find module '@eslint/js'" -- a failure that reproduces on no
67+
# developer machine, because a real `npm ci`/`npm install` always creates those directories.
68+
# Globbing `apps/*` + `packages/*` (the workspace globs from package.json) makes the cache follow
69+
# npm's layout automatically instead of re-breaking on the next hoist change. review-enrichment
70+
# and control-plane are NOT workspaces -- they have their own installs and their own cache steps.
6071
key: npm-${{ (github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == true) && 'fork' || 'trusted' }}-${{ hashFiles('.nvmrc') }}-${{ hashFiles('package.json', 'apps/*/package.json', 'packages/*/package.json', 'package-lock.json') }}
6172

6273
- name: Install dependencies (retry on transient failures)
@@ -82,5 +93,6 @@ runs:
8293
with:
8394
path: |
8495
node_modules
85-
apps/loopover-ui/node_modules
96+
apps/*/node_modules
97+
packages/*/node_modules
8698
key: ${{ steps.node-modules-cache.outputs.cache-primary-key }}

0 commit comments

Comments
 (0)