Skip to content

Commit fc6ffc0

Browse files
justin808claude
andcommitted
Migrate from Yarn Classic to pnpm (#2120)
Migrate the react-on-rails monorepo from Yarn Classic (v1.22.22) to pnpm for improved monorepo management, faster installs, and native workspace linking that eliminates the need for yalc in internal development. Key changes: - Add pnpm-workspace.yaml and .npmrc for pnpm configuration - Update packageManager field to [email protected] in all package.json files - Convert workspace dependencies from "*" to "workspace:*" protocol - Move pnpm.overrides from workspace package to root - Replace yarn.lock with pnpm-lock.yaml - Update all GitHub Actions workflows with pnpm setup and commands - Update rake tasks to use pnpm commands - Update CONTRIBUTING.md and CLAUDE.md documentation Note for users: End users of react_on_rails can continue using their preferred package manager (npm, yarn, pnpm, or bun). The generators automatically detect your package manager. These changes only affect contributors working on the react_on_rails codebase itself. Closes #2120 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent c3a0225 commit fc6ffc0

35 files changed

+10974
-34402
lines changed

.claude/docs/pr-splitting-strategy.md

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,16 @@
55
### Indicators That Splitting Makes Sense
66

77
1. **Multiple Independent Test Failures**
8-
98
- Different test suites failing for different reasons
109
- Failures span multiple subsystems (integration, unit, Pro package, etc.)
1110
- Each failure requires significant debugging time
1211

1312
2. **Long Git History**
14-
1513
- 50+ commits in the branch
1614
- Multiple feature changes mixed together
1715
- Hard to bisect or identify which commit broke what
1816

1917
3. **Mixed Concerns**
20-
2118
- Infrastructure changes + feature changes
2219
- Multiple unrelated fixes bundled together
2320
- Refactoring mixed with new functionality
@@ -86,19 +83,16 @@ Group 4 (Monorepo Node Renderer):
8683
**Principle**: Merge least risky changes first
8784

8885
1. **Documentation-only changes** (safest)
89-
9086
- No code changes
9187
- No risk of breaking tests
9288
- Provides value immediately
9389

9490
2. **Bug fixes with tests** (safe if tests pass)
95-
9691
- Clear, focused changes
9792
- Well-tested
9893
- Doesn't change infrastructure
9994

10095
3. **Refactoring with no behavior change** (moderate risk)
101-
10296
- Keep tests passing
10397
- No API changes
10498
- Can be verified by running existing tests
@@ -392,19 +386,16 @@ This PR has been split into smaller, more focused PRs for easier review and debu
392386
### New PRs (in merge order):
393387

394388
1. **#XXXX: Documentation & Testing Requirements** ✅ READY
395-
396389
- CI failure analysis
397390
- Testing requirement documentation
398391
- Zero risk (docs only)
399392

400393
2. **#YYYY: Build Console Replay Parameter Fix** 🔄 IN REVIEW
401-
402394
- Focused bug fix
403395
- All tests passing
404396
- Addresses one of the three failures
405397

406398
3. **#ZZZZ: Workspace Dependencies Fix** ⏳ DRAFT
407-
408399
- Yarn Classic compatibility
409400
- Small infrastructure fix
410401
- Easy to verify

.claude/docs/testing-build-scripts.md

Lines changed: 34 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44

55
## Why This Matters
66

7-
- The `prepack`/`prepare` scripts in package.json/package-scripts.yml run during:
8-
- `npm install` / `yarn install` (for git dependencies)
7+
- The `prepack`/`prepare` scripts in package.json run during:
8+
- `npm install` / `pnpm install` (for git dependencies)
99
- `yalc publish` (critical for local development)
1010
- `npm publish`
1111
- Package manager prepare phase
@@ -40,7 +40,7 @@ gh pr view --json statusCheckRollup | jq '.statusCheckRollup[] | select(.conclus
4040

4141
## Mandatory Testing After ANY Changes
4242

43-
**If you modify package.json, package-scripts.yml, or build configs:**
43+
**If you modify package.json or build configs:**
4444

4545
### Step 1: ALWAYS Test Clean Install First
4646

@@ -51,7 +51,7 @@ This is the **MOST CRITICAL** test - it's what CI does first, and installation f
5151
rm -rf node_modules
5252

5353
# Test the exact command CI uses
54-
yarn install --frozen-lockfile
54+
pnpm install --frozen-lockfile
5555

5656
# If this fails, STOP and fix it before testing anything else
5757
```
@@ -62,7 +62,7 @@ yarn install --frozen-lockfile
6262

6363
```bash
6464
# Build all packages
65-
yarn run build
65+
pnpm run build
6666

6767
# Should succeed without errors
6868
```
@@ -71,10 +71,10 @@ yarn run build
7171

7272
```bash
7373
# Test prepack/prepare scripts work
74-
yarn nps build.prepack
74+
pnpm run prepack
7575

7676
# Test yalc publish (CRITICAL for local development)
77-
yarn run yalc:publish
77+
pnpm run yalc:publish
7878

7979
# Should publish all workspace packages successfully
8080
```
@@ -97,48 +97,48 @@ ls -la packages/react-on-rails-pro-node-renderer/lib/ReactOnRailsProNodeRenderer
9797
bundle exec rubocop
9898

9999
# JS/TS formatting
100-
yarn start format.listDifferent
100+
pnpm run format.listDifferent
101101
```
102102

103103
## When Directory Structure Changes
104104

105105
If you rename/move directories that contain build artifacts:
106106

107-
1. **Update ALL path references in package-scripts.yml**
107+
1. **Update ALL path references in package.json**
108108
2. **Test yalc publish BEFORE pushing**
109109
3. **Test in a fresh clone to ensure no local assumptions**
110110
4. **Consider adding a CI job to validate artifact paths**
111111

112-
## Workspace Dependencies: Yarn Classic vs Yarn Berry
112+
## Workspace Dependencies: PNPM
113113

114-
**CRITICAL: This project uses Yarn Classic (v1.x), not Yarn Berry (v2+)**
114+
**CRITICAL: This project uses PNPM (v9+)**
115115

116-
Check `package.json` for: `"packageManager": "[email protected]"`
116+
Check `package.json` for: `"packageManager": "[email protected]"`
117117

118118
### Correct Workspace Dependency Syntax
119119

120-
For Yarn Classic workspaces:
120+
For PNPM workspaces:
121121

122122
```json
123123
{
124124
"dependencies": {
125-
"react-on-rails": "*"
125+
"react-on-rails": "workspace:*"
126126
}
127127
}
128128
```
129129

130130
**DO NOT USE:**
131131

132-
- `"workspace:*"` - This is Yarn Berry v2+ syntax, will cause installation errors
132+
- `"*"` - This is Yarn Classic v1.x syntax
133133
- `"file:../react-on-rails"` - This bypasses workspace resolution
134134

135-
### Why `*` Works
135+
### Why `workspace:*` Works
136136

137-
In Yarn Classic workspaces:
137+
In PNPM workspaces:
138138

139-
- `"*"` tells Yarn to resolve to the local workspace package
140-
- Yarn automatically links to the workspace version
141-
- This is the official Yarn v1 workspace syntax
139+
- `"workspace:*"` tells PNPM to resolve to the local workspace package
140+
- PNPM automatically links to the workspace version
141+
- This is the official PNPM workspace syntax
142142

143143
### Testing Workspace Changes
144144

@@ -149,32 +149,34 @@ When modifying workspace dependencies in package.json:
149149
rm -rf node_modules
150150

151151
# 2. Test CI command - this will fail immediately if syntax is wrong
152-
yarn install --frozen-lockfile
152+
pnpm install --frozen-lockfile
153153

154154
# 3. Verify workspace linking worked
155-
yarn workspaces info
155+
pnpm -r list
156156

157157
# 4. Test that packages can import each other
158-
yarn run build
158+
pnpm run build
159159
```
160160

161161
## Real Examples: What Went Wrong
162162

163163
### Example 1: Path Reference Issue (Sep 2024)
164164

165165
We moved `node_package/``packages/react-on-rails/`. The path in
166-
package-scripts.yml was updated to `packages/react-on-rails/lib/ReactOnRails.full.js`.
167-
Later, the structure was partially reverted to `lib/` at root, but package-scripts.yml
166+
package.json was updated to `packages/react-on-rails/lib/ReactOnRails.full.js`.
167+
Later, the structure was partially reverted to `lib/` at root, but package.json
168168
wasn't updated. This broke yalc publish silently for 7 weeks. Manual testing of
169-
`yarn run yalc.publish` would have caught this immediately.
169+
`pnpm run yalc:publish` would have caught this immediately.
170170

171-
### Example 2: Workspace Protocol Issue (Nov 2024)
171+
### Example 2: Workspace Protocol Migration (2024)
172172

173-
Changed workspace dependencies from `"*"` to `"workspace:*"` without testing clean install.
174-
This caused CI to fail with: `Couldn't find any versions for "react-on-rails" that matches "workspace:*"`
173+
When migrating from Yarn to PNPM, workspace dependencies needed to change from `"*"` to `"workspace:*"`.
175174

176-
**Root cause:** Assumed `workspace:*` was standard, but it's only supported in Yarn Berry v2+.
177-
This project uses Yarn Classic v1.x which requires `"*"` for workspace dependencies.
175+
**Root cause:** Different package managers use different workspace protocols:
178176

179-
**Lesson:** ALWAYS test `yarn install --frozen-lockfile` after modifying workspace dependencies.
177+
- Yarn Classic v1.x uses `"*"` for workspace dependencies
178+
- PNPM uses `"workspace:*"` for workspace dependencies
179+
- Yarn Berry v2+ also uses `"workspace:*"`
180+
181+
**Lesson:** ALWAYS test `pnpm install --frozen-lockfile` after modifying workspace dependencies.
180182
Your local node_modules masked the issue - CI starts fresh and caught it immediately.

.github/workflows/examples.yml

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,6 @@ jobs:
101101
fail-fast: false
102102
matrix: ${{ fromJson(needs.setup-matrix.outputs.matrix) }}
103103
env:
104-
SKIP_YARN_COREPACK_CHECK: 0
105104
BUNDLE_FROZEN: ${{ matrix.dependency-level == 'minimum' && 'false' || 'true' }}
106105
runs-on: ubuntu-22.04
107106
steps:
@@ -117,18 +116,28 @@ jobs:
117116
uses: ./.github/actions/setup-node-with-retry
118117
with:
119118
node-version: 20
120-
# Retry logic now handles V8 crashes automatically
121-
# Tracking: https://github.com/actions/setup-node/issues/1028
122-
cache: yarn
123-
cache-dependency-path: '**/yarn.lock'
119+
- name: Setup pnpm
120+
uses: pnpm/action-setup@v4
121+
with:
122+
version: 9
123+
- name: Get pnpm store directory
124+
shell: bash
125+
run: echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
126+
- name: Setup pnpm cache
127+
uses: actions/cache@v4
128+
with:
129+
path: ${{ env.STORE_PATH }}
130+
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
131+
restore-keys: |
132+
${{ runner.os }}-pnpm-store-
124133
- name: Print system information
125134
run: |
126135
echo "Linux release: "; cat /etc/issue
127136
echo "Current user: "; whoami
128137
echo "Current directory: "; pwd
129138
echo "Ruby version: "; ruby -v
130139
echo "Node version: "; node -v
131-
echo "Yarn version: "; yarn --version
140+
echo "pnpm version: "; pnpm --version
132141
echo "Bundler version: "; bundle --version
133142
- name: run conversion script to support shakapacker v6
134143
if: matrix.dependency-level == 'minimum'
@@ -140,14 +149,14 @@ jobs:
140149
key: package-app-gem-cache-${{ hashFiles('Gemfile.lock') }}-ruby${{ matrix.ruby-version }}-${{ matrix.dependency-level }}
141150
- id: get-sha
142151
run: echo "sha=\"$(git rev-parse HEAD)\"" >> "$GITHUB_OUTPUT"
143-
- name: Install Node modules with Yarn for renderer package
152+
- name: Install Node modules with pnpm for renderer package
144153
run: |
145-
yarn install --no-progress --no-emoji ${{ matrix.dependency-level == 'latest' && '--frozen-lockfile' || '' }}
146-
sudo yarn global add yalc
154+
pnpm install ${{ matrix.dependency-level == 'latest' && '--frozen-lockfile' || '' }}
155+
pnpm add -g yalc
147156
- name: yalc publish for react-on-rails
148-
# Use yarn workspace script to publish all workspace packages to yalc
157+
# Use pnpm workspace script to publish all workspace packages to yalc
149158
# Runs the "yalc:publish" script defined in each workspace's package.json
150-
run: yarn yalc publish
159+
run: pnpm yalc:publish
151160
- name: Install Ruby Gems for package
152161
run: |
153162
bundle lock --add-platform 'x86_64-linux'

.github/workflows/gem-tests.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,6 @@ jobs:
120120
echo "Current directory: "; pwd
121121
echo "Ruby version: "; ruby -v
122122
echo "Node version: "; node -v
123-
echo "Yarn version: "; yarn --version
124123
echo "Bundler version: "; bundle --version
125124
- name: run conversion script to use minimum supported dependency versions
126125
if: matrix.dependency-level == 'minimum'

0 commit comments

Comments
 (0)