fix(ci): cache every workspace's node_modules, not just the root and one app - #9596
Conversation
…one app 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.
|
Important 🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨 ⏳ LoopOver is waiting…LoopOver has seen this pull request and is waiting on CI checks to finish before reviewing it. This comment will update once the review runs. 🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed · 🟨 Waiting |
|
Superagent didn't find any vulnerabilities or security issues in this PR. |
|
Follow-up correction pushed: widening Added an explicit |
…y takes effect (#9597) #9596 widened the node_modules cache to every workspace but left the key untouched, so nothing changed for a branch with an unchanged lockfile: it keeps HITTING the entry archived under the narrow list, which restores no apps/loopover-miner-ui/node_modules, and a hit skips npm ci -- leaving the tree exactly as broken and UI lint still failing on 'Cannot find module @eslint/js'. Add an explicit npm-v2- generation salt so one clean miss re-archives a complete tree under the current path list, and document that the salt must be bumped whenever that list changes.
❌ 1 Tests Failed:
View the top 1 failed test(s) by shortest run time
To view more test analytics, go to the Test Analytics Dashboard |
…ath list (#9603) #9596/#9597 changed the node_modules cache to glob every workspace and added a generation salt to the key, but the composite-action test still asserted the old literal `apps/loopover-ui/node_modules`, so it has been failing on main and on every branch since. Assert the contract that now holds, and tighten it in two places the old test left open: - both workspace globs, matching what package.json declares; - the `npm-v2-` salt, asserted beside the paths, because widening the paths without bumping the salt is a no-op and the two must move together; - the SAVE step's path list equals the RESTORE step's -- the save list decides what a future run can restore, so a narrowing there would stay invisible until some later job failed on a missing workspace.
The failure
Every PR's UI lint step is failing on
mainright now:Why
setup-workspace's node_modules cache listed onlynode_modulesandapps/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 made npm nest@eslint/jsunder both UI apps — so on a cache hit,apps/loopover-miner-ui/node_moduleswas never restored (it isn't in the path list) and the config's very first import failed.It reproduces on no developer machine: a real
npm ci/npm installalways creates those directories, so only the cache-hit path is broken. That's also why it slipped through #9589's own green run — that run was a cache miss (the lockfile had just changed), which installed everything for real.The fix
Glob
apps/*/node_modules+packages/*/node_modules— the same workspace globspackage.jsondeclares — in both the restore and the save step, so the cache follows npm's layout automatically instead of re-breaking on the next hoist change.review-enrichmentandcontrol-planeare deliberately untouched: they are not workspaces, and they already have their own installs and their own cache steps.Verified:
actionlintandlint:composite-actionsboth clean. The real proof is this PR's own CI — a first run installs fresh and saves the widened cache; every subsequent PR then restores a complete tree.