Fix package manager detection in hydrogen upgrade for monorepos#3794
Fix package manager detection in hydrogen upgrade for monorepos#3794JohnCashmore wants to merge 5 commits into
hydrogen upgrade for monorepos#3794Conversation
|
I have signed the CLA! |
fredericoo
left a comment
There was a problem hiding this comment.
all looks good except one test, pls revisit – then im happy to get this onto the next release!
| return { | ||
| ...original, | ||
| getPackageManager: vi.fn(() => Promise.resolve('pnpm')), | ||
| findPackageManagerByLockfile: vi.fn(() => Promise.resolve('pnpm')), |
There was a problem hiding this comment.
blocking: this still lets the regression pass if the upgrade command is not actually wired to the new detector everywhere.
The helper tests prove findPackageManagerByLockfile() can walk up to an ancestor lockfile, but the upgradeNodeModules() tests mock renderTasks, so the install/remove task callbacks that call the detector never run. The final undo-message path also isn't asserted, so it could still print npm i for a pnpm workspace.
Let's add regression coverage that proves the command uses ancestor-lockfile detection end-to-end: execute the upgrade task callback and assert exec is called with pnpm, and assert the summary/undo instructions render pnpm i for the same monorepo shape.
There was a problem hiding this comment.
Good catch @fredericoo — I've added regression coverage that runs the real detector against a monorepo shape (lockfile at the workspace root, app nested without its own): it asserts the upgrade/remove tasks invoke pnpm and that the undo instructions render pnpm i rather than npm i.
I think this covers what you were after, but happy to adjust if there's a project standard for this kind of coverage I should follow instead.
0b4cf57 to
056f718
Compare
… detection Execute the upgrade/remove task callbacks and the undo-summary path with the real findPackageManagerByLockfile against a monorepo shape (ancestor pnpm-lock.yaml, app nested without its own lockfile), proving the upgrade command feeds ancestor-lockfile detection into exec and the undo instructions rather than relying on the suite-wide stub.
a40e796 to
3483396
Compare
WHY are these changes introduced?
Fixes #3793
When a Hydrogen app lives inside a monorepo workspace (pnpm/yarn/bun), the lockfile sits at the workspace root — not in the app directory.
hydrogen upgradedetects the package manager with cli-kit'sgetPackageManager(appPath), which only checks that single directory for a lockfile before falling back to npm. The result: the upgrade runsnpm install --legacy-peer-depsinside a pnpm workspace, which fails onworkspace:protocol dependencies (or pollutes the app dir with a straypackage-lock.json), and the final "Undo these upgrades?" message printsnpm iinstead of the workspace's package manager.WHAT is this pull request doing?
findPackageManagerByLockfile(directory, options?)topackages/cli/src/lib/package-managers.ts: walks up from the app directory looking for a known lockfile, built on the existingpackageManagersmetadata table (including alternative lockfiles such asbun.lockandnpm-shrinkwrap.json).'unknown', preserving the existing npm +--legacy-peer-depsfallback path untouched.getPackageManager(appPath)call sites inupgrade.ts(dependency removal, dependency upgrade, and the undo-instructions message) with the new helper. The undo message is additionally wrapped inresolvePackageManagerName()so it can never render the literal stringunknown.upgrade.test.tspackage-manager mock to the new module and adds 9 unit tests covering: single-repo detection, monorepo ancestor detection (pnpm/yarn/bun), nearest-wins precedence, no-lockfile fallback, alternative lockfiles, and the same-directory tie-break order.@shopify/cli-hydrogen).Out of scope (left untouched, happy to follow up): the same single-directory detection pattern exists in
build.ts,setup/css.ts,setup/vite.ts, andlib/shell.ts.HOW to test your changes?
Unit tests:
pnpm --filter @shopify/cli-hydrogen test src/lib/package-managers.test.ts src/commands/hydrogen/upgrade.test.tsManual end-to-end:
pnpm-workspace.yamlwithpackages: ['apps/*']) containing a Hydrogen app atapps/storefrontpinned to an older Hydrogen version. Runpnpm installfrom the root (singlepnpm-lock.yamlat the root, no lockfile in the app dir) and commit.pnpm --filter @shopify/cli-hydrogen build) and run the upgrade against the app directory.pnpm add …(previouslynpm install --legacy-peer-deps), nopackage-lock.jsonappears in the app dir, the rootpnpm-lock.yamlupdates, and the closing undo message reads… && pnpm i.Checklist
resolvePath/dirname/joinPathand terminates whendirname(dir) === dir, which holds at filesystem roots on both POSIX (/) and Windows drive roots (C:\)