Shopify / Shopify/hydrogen

`hydrogen upgrade` detects the wrong package manager in monorepos and runs npm inside pnpm/yarn/bun workspaces

Open
#3,793 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
2.1k
Forks
443
Avg merge
4d 19h
Merged PRs (30d)
24

Description

What is the location of your example repository?

n/a — reproduction steps below create one from scratch.

Which package or tool is having this issue?

CLI

What version of that package or tool are you using?

@shopify/cli-hydrogen 12.0.1 (also reproducible on earlier versions)

Steps to Reproduce
  1. Create a pnpm workspace with a Hydrogen app as a workspace member:

    my-monorepo/
    ├── pnpm-workspace.yaml      # packages: ['apps/*']
    ├── pnpm-lock.yaml           # single lockfile at the workspace root
    └── apps/
        └── storefront/          # Hydrogen app (no lockfile in here)
            └── package.json
    
  2. Pin the app to an older Hydrogen version (so an upgrade is available), run pnpm install from the workspace root, and commit everything.

  3. From apps/storefront, run shopify hydrogen upgrade and select a newer version.

Expected Behavior

The CLI detects that the project is a pnpm workspace (lockfile at the workspace root) and runs the upgrade with pnpm (pnpm add …), updating the root pnpm-lock.yaml.

Actual Behavior

Package manager detection only looks for a lockfile in the app directory itself. In a monorepo the lockfile lives at the workspace root, so detection finds nothing and falls back to npm. The upgrade then runs npm install --legacy-peer-deps inside the pnpm workspace, which fails on workspace: protocol dependencies (and in partial-failure cases leaves a stray package-lock.json in the app directory). The "Undo these upgrades?" instructions at the end also print npm i instead of pnpm i.

The same applies to yarn and bun workspaces — any setup where the lockfile is in an ancestor directory of the app.

Root cause: upgrade.ts uses cli-kit's getPackageManager(appPath), which checks only that single directory for yarn.lock/pnpm-lock.yaml/bun.lockb before falling back to npm — it never walks up to the workspace root.

I have a fix ready and will open a PR shortly.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in upgrade.ts at the getPackageManager(appPath) call and trace how the CLI identifies lockfiles from the app directory. Reproduce the described pnpm workspace, then verify that hydrogen upgrade selects pnpm, updates the root pnpm-lock.yaml, avoids creating an app-level package-lock.json, and gives matching undo instructions; the same behavior should hold for yarn and bun.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
cli
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.