Skip to content

Commit b50a74d

Browse files
authored
Restructure monorepo with two top-level product directories (#2114)
## Summary Implements the two top-level directories structure for clearer product separation in the monorepo. Core React on Rails code moves into `react_on_rails/` alongside the existing `react_on_rails_pro/` directory, creating symmetric product organization with clear licensing boundaries. This addresses #2113 and provides a clearer, more maintainable monorepo structure than the previous attempt in #2108. ## Changes ### Directory Structure - Moves `lib/`, `spec/`, `sig/`, and `react_on_rails.gemspec` into `react_on_rails/` - Pro code remains in `react_on_rails_pro/` (minimal changes) - NPM packages stay in `packages/` (unchanged) ### Configuration Updates - **Gemfile**: Updated to reference core gem path - **Gemspecs**: Fixed file listing with proper git ls-files handling - **CI Workflows**: Updated all GitHub Actions path references - **Documentation**: Updated LICENSE.md, CONTRIBUTING.md, Steepfile - **Rake helpers**: Added monorepo_root, updated gem_root ### Build Verification - ✅ Core gem builds successfully - ✅ Pro gem builds successfully - ✅ Bundle install works with new structure ## Pull Request Checklist - [x] Configuration updates for new structure - [x] CI/CD workflow path updates - [x] Build verification (gems compile) - [ ] Full test suite (requires RSpec configuration work) - [ ] CHANGELOG update (follow-up in separate PR) ## Testing Notes - Gems build successfully with new paths - Bundle install completes without errors - RSpec needs configuration adjustments (follow-up work to connect spec paths) - All path references in CI/documentation have been updated ## Benefits 1. **Crystal clear separation**: Core code in `react_on_rails/`, Pro in `react_on_rails_pro/` 2. **Symmetric structure**: Both products have identical internal organization 3. **Simpler licensing**: Directory boundaries match license boundaries exactly 4. **Maintainability**: Clear separation makes monorepo easier to navigate Closes #2113 ## Summary by CodeRabbit * **New Features** * Added PropTypes runtime validation to example React components. * **Chores** * Restructured repository into scoped package directories and updated CI/workflows, cache/artifact paths, and task scripts to the new layout. * Bumped several dev dependencies and added/updated linting and tooling scripts. * **Documentation** * Updated contributor guide, changelog, license notes, ignore rules, and added CI best-practices and monitoring guidance for the monorepo.
1 parent 449cc7b commit b50a74d

File tree

569 files changed

+2253
-8583
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

569 files changed

+2253
-8583
lines changed

.claude/docs/avoiding-ci-failure-cycles.md

Lines changed: 409 additions & 0 deletions
Large diffs are not rendered by default.

.claude/docs/master-health-monitoring.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,31 @@ Within 30 minutes of your PR merging to master:
2121
- Don't assume "someone else will fix it"
2222
- You are responsible for ensuring your PR doesn't break master
2323

24+
## Polling CI Status While Waiting
25+
26+
**When actively monitoring CI, poll every 30 seconds (not 180 seconds):**
27+
28+
```bash
29+
# Poll every 30 seconds while CI is running
30+
while true; do
31+
gh pr view --json statusCheckRollup --jq '.statusCheckRollup | group_by(.conclusion) | map({conclusion: .[0].conclusion, count: length})'
32+
sleep 30
33+
done
34+
```
35+
36+
Or use the automated tool which polls at 30-second intervals:
37+
38+
```bash
39+
bin/ci-rerun-failures # Automatically waits for in-progress CI, polling every 30s
40+
```
41+
42+
**Why 30 seconds?**
43+
44+
- CI jobs typically complete in 3-15 minutes
45+
- 30-second polling gives responsive feedback without excessive API calls
46+
- 180 seconds (3 minutes) is too slow—you waste time waiting unnecessarily
47+
- GitHub API rate limits are 5000 requests/hour, so 30-second polls are fine
48+
2449
## When You Discover Master is Broken
2550

2651
1. **Determine if it's from your PR:**

.github/workflows/examples.yml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,8 @@ jobs:
136136
- name: Save root ruby gems to cache
137137
uses: actions/cache@v4
138138
with:
139-
path: vendor/bundle
140-
key: package-app-gem-cache-${{ hashFiles('Gemfile.lock') }}-ruby${{ matrix.ruby-version }}-${{ matrix.dependency-level }}
139+
path: react_on_rails/vendor/bundle
140+
key: package-app-gem-cache-${{ hashFiles('react_on_rails/Gemfile.lock') }}-ruby${{ matrix.ruby-version }}-${{ matrix.dependency-level }}
141141
- id: get-sha
142142
run: echo "sha=\"$(git rev-parse HEAD)\"" >> "$GITHUB_OUTPUT"
143143
- name: Install Node modules with Yarn for renderer package
@@ -147,9 +147,10 @@ jobs:
147147
- name: yalc publish for react-on-rails
148148
# Use yarn workspace script to publish all workspace packages to yalc
149149
# Runs the "yalc:publish" script defined in each workspace's package.json
150-
run: yarn yalc publish
150+
run: yarn run yalc:publish
151151
- name: Install Ruby Gems for package
152152
run: |
153+
cd react_on_rails
153154
bundle lock --add-platform 'x86_64-linux'
154155
if ! bundle check --path=vendor/bundle; then
155156
bundle _2.5.9_ install --path=vendor/bundle --jobs=4 --retry=3
@@ -172,7 +173,7 @@ jobs:
172173
run: |
173174
echo "CI_DEPENDENCY_LEVEL=${{ matrix.dependency-level }}" >> $GITHUB_ENV
174175
- name: Main CI
175-
run: bundle exec rake run_rspec:shakapacker_examples
176+
run: cd react_on_rails && bundle exec rake run_rspec:shakapacker_examples
176177
- name: Store test results
177178
uses: actions/upload-artifact@v4
178179
with:

.github/workflows/gem-tests.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -128,10 +128,10 @@ jobs:
128128
- name: Save root ruby gems to cache
129129
uses: actions/cache@v4
130130
with:
131-
path: vendor/bundle
132-
key: package-app-gem-cache-${{ hashFiles('Gemfile.lock') }}-${{ matrix.ruby-version }}-${{ matrix.dependency-level }}
131+
path: react_on_rails/vendor/bundle
132+
key: package-app-gem-cache-${{ hashFiles('react_on_rails/Gemfile.lock') }}-${{ matrix.ruby-version }}-${{ matrix.dependency-level }}
133133
- name: Install Ruby Gems for package
134-
run: bundle check --path=vendor/bundle || bundle _2.5.9_ install --path=vendor/bundle --jobs=4 --retry=3
134+
run: cd react_on_rails && (bundle check --path=vendor/bundle || bundle _2.5.9_ install --path=vendor/bundle --jobs=4 --retry=3)
135135
- name: Git Stuff
136136
if: matrix.dependency-level == 'minimum'
137137
run: |
@@ -142,7 +142,7 @@ jobs:
142142
run: |
143143
echo "CI_DEPENDENCY_LEVEL=${{ matrix.dependency-level }}" >> $GITHUB_ENV
144144
- name: Run rspec tests
145-
run: bundle exec rspec spec/react_on_rails
145+
run: cd react_on_rails && bundle exec rspec spec/react_on_rails
146146
- name: Store test results
147147
uses: actions/upload-artifact@v4
148148
with:

.github/workflows/integration-tests.yml

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -142,31 +142,31 @@ jobs:
142142
- name: yalc publish for react-on-rails
143143
run: cd packages/react-on-rails && yalc publish
144144
- name: yalc add react-on-rails
145-
run: cd spec/dummy && yalc add react-on-rails
145+
run: cd react_on_rails/spec/dummy && yalc add react-on-rails
146146
- name: Install Node modules with Yarn for dummy app
147-
run: cd spec/dummy && yarn install --no-progress --no-emoji ${{ matrix.dependency-level == 'latest' && '--frozen-lockfile' || '' }}
147+
run: cd react_on_rails/spec/dummy && yarn install --no-progress --no-emoji ${{ matrix.dependency-level == 'latest' && '--frozen-lockfile' || '' }}
148148
- name: Save dummy app ruby gems to cache
149149
uses: actions/cache@v4
150150
with:
151-
path: spec/dummy/vendor/bundle
152-
key: dummy-app-gem-cache-${{ hashFiles('spec/dummy/Gemfile.lock') }}-ruby${{ matrix.ruby-version }}-${{ matrix.dependency-level }}
151+
path: react_on_rails/spec/dummy/vendor/bundle
152+
key: dummy-app-gem-cache-${{ hashFiles('react_on_rails/spec/dummy/Gemfile.lock') }}-ruby${{ matrix.ruby-version }}-${{ matrix.dependency-level }}
153153
- name: Install Ruby Gems for dummy app
154154
run: |
155-
cd spec/dummy
155+
cd react_on_rails/spec/dummy
156156
bundle lock --add-platform 'x86_64-linux'
157157
if ! bundle check --path=vendor/bundle; then
158158
bundle _2.5.9_ install --path=vendor/bundle --jobs=4 --retry=3
159159
fi
160160
- name: generate file system-based packs
161-
run: cd spec/dummy && RAILS_ENV="test" bundle exec rake react_on_rails:generate_packs
161+
run: cd react_on_rails/spec/dummy && RAILS_ENV="test" bundle exec rake react_on_rails:generate_packs
162162
- name: Build test bundles for dummy app
163-
run: cd spec/dummy && rm -rf public/webpack/test && yarn run build:rescript && RAILS_ENV="test" NODE_ENV="test" bin/shakapacker
163+
run: cd react_on_rails/spec/dummy && rm -rf public/webpack/test && yarn run build:rescript && RAILS_ENV="test" NODE_ENV="test" bin/shakapacker
164164
- id: get-sha
165165
run: echo "sha=\"$(git rev-parse HEAD)\"" >> "$GITHUB_OUTPUT"
166166
- name: Save test Webpack bundles to cache (for build number checksum used by RSpec job)
167167
uses: actions/cache/save@v4
168168
with:
169-
path: spec/dummy/public/webpack
169+
path: react_on_rails/spec/dummy/public/webpack
170170
key: dummy-app-webpack-bundle-${{ steps.get-sha.outputs.sha }}-ruby${{ matrix.ruby-version }}-${{ matrix.dependency-level }}
171171

172172
dummy-app-integration-tests:
@@ -217,19 +217,19 @@ jobs:
217217
- name: Save root ruby gems to cache
218218
uses: actions/cache@v4
219219
with:
220-
path: vendor/bundle
221-
key: package-app-gem-cache-${{ hashFiles('Gemfile.lock') }}-ruby${{ matrix.ruby-version }}-${{ matrix.dependency-level }}
220+
path: react_on_rails/vendor/bundle
221+
key: package-app-gem-cache-${{ hashFiles('react_on_rails/Gemfile.lock') }}-ruby${{ matrix.ruby-version }}-${{ matrix.dependency-level }}
222222
- name: Save dummy app ruby gems to cache
223223
uses: actions/cache@v4
224224
with:
225-
path: spec/dummy/vendor/bundle
226-
key: dummy-app-gem-cache-${{ hashFiles('spec/dummy/Gemfile.lock') }}-ruby${{ matrix.ruby-version }}-${{ matrix.dependency-level }}
225+
path: react_on_rails/spec/dummy/vendor/bundle
226+
key: dummy-app-gem-cache-${{ hashFiles('react_on_rails/spec/dummy/Gemfile.lock') }}-ruby${{ matrix.ruby-version }}-${{ matrix.dependency-level }}
227227
- id: get-sha
228228
run: echo "sha=\"$(git rev-parse HEAD)\"" >> "$GITHUB_OUTPUT"
229229
- name: Save test Webpack bundles to cache (for build number checksum used by RSpec job)
230230
uses: actions/cache@v4
231231
with:
232-
path: spec/dummy/public/webpack
232+
path: react_on_rails/spec/dummy/public/webpack
233233
key: dummy-app-webpack-bundle-${{ steps.get-sha.outputs.sha }}-ruby${{ matrix.ruby-version }}-${{ matrix.dependency-level }}
234234
- name: Install Node modules with Yarn
235235
run: |
@@ -238,22 +238,23 @@ jobs:
238238
- name: yalc publish for react-on-rails
239239
run: cd packages/react-on-rails && yalc publish
240240
- name: yalc add react-on-rails
241-
run: cd spec/dummy && yalc add react-on-rails
241+
run: cd react_on_rails/spec/dummy && yalc add react-on-rails
242242
- name: Install Node modules with Yarn for dummy app
243-
run: cd spec/dummy && yarn install --no-progress --no-emoji ${{ matrix.dependency-level == 'latest' && '--frozen-lockfile' || '' }}
243+
run: cd react_on_rails/spec/dummy && yarn install --no-progress --no-emoji ${{ matrix.dependency-level == 'latest' && '--frozen-lockfile' || '' }}
244244
- name: Dummy JS tests
245245
run: |
246-
cd spec/dummy
246+
cd react_on_rails/spec/dummy
247247
yarn run test:js
248248
- name: Install Ruby Gems for package
249249
run: |
250+
cd react_on_rails
250251
bundle lock --add-platform 'x86_64-linux'
251252
if ! bundle check --path=vendor/bundle; then
252253
bundle _2.5.9_ install --path=vendor/bundle --jobs=4 --retry=3
253254
fi
254255
- name: Install Ruby Gems for dummy app
255256
run: |
256-
cd spec/dummy
257+
cd react_on_rails/spec/dummy
257258
bundle lock --add-platform 'x86_64-linux'
258259
if ! bundle check --path=vendor/bundle; then
259260
bundle _2.5.9_ install --path=vendor/bundle --jobs=4 --retry=3
@@ -273,19 +274,19 @@ jobs:
273274
- name: Increase the amount of inotify watchers
274275
run: echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p
275276
- name: generate file system-based packs
276-
run: cd spec/dummy && RAILS_ENV="test" bundle exec rake react_on_rails:generate_packs
277+
run: cd react_on_rails/spec/dummy && RAILS_ENV="test" bundle exec rake react_on_rails:generate_packs
277278
- name: Git Stuff
278279
if: matrix.dependency-level == 'minimum'
279280
run: |
280281
git config user.email "[email protected]"
281282
git config user.name "Your Name"
282283
git commit -am "stop generators from complaining about uncommitted code"
283-
- run: cd spec/dummy && bundle info shakapacker
284+
- run: cd react_on_rails/spec/dummy && bundle info shakapacker
284285
- name: Set packer version environment variable
285286
run: |
286287
echo "CI_DEPENDENCY_LEVEL=ruby${{ matrix.ruby-version }}-${{ matrix.dependency-level }}" >> $GITHUB_ENV
287288
- name: Main CI
288-
run: bundle exec rake run_rspec:all_dummy
289+
run: cd react_on_rails && bundle exec rake run_rspec:all_dummy
289290
- name: Store test results
290291
uses: actions/upload-artifact@v4
291292
with:
@@ -295,14 +296,14 @@ jobs:
295296
uses: actions/upload-artifact@v4
296297
with:
297298
name: dummy-app-capybara-${{ github.run_id }}-${{ github.job }}-ruby${{ matrix.ruby-version }}-${{ matrix.dependency-level }}
298-
path: spec/dummy/tmp/capybara
299+
path: react_on_rails/spec/dummy/tmp/capybara
299300
- name: Store artifacts
300301
uses: actions/upload-artifact@v4
301302
with:
302303
name: dummy-app-test-log-${{ github.run_id }}-${{ github.job }}-ruby${{ matrix.ruby-version }}-${{ matrix.dependency-level }}
303-
path: spec/dummy/log/test.log
304+
path: react_on_rails/spec/dummy/log/test.log
304305
- name: Store artifacts
305306
uses: actions/upload-artifact@v4
306307
with:
307308
name: dummy-app-yarn-log-${{ github.run_id }}-${{ github.job }}-ruby${{ matrix.ruby-version }}-${{ matrix.dependency-level }}
308-
path: spec/dummy/yarn-error.log
309+
path: react_on_rails/spec/dummy/yarn-error.log

.github/workflows/lint-js-and-ruby.yml

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -112,46 +112,45 @@ jobs:
112112
- name: Save root ruby gems to cache
113113
uses: actions/cache@v4
114114
with:
115-
path: vendor/bundle
116-
key: package-app-gem-cache-${{ hashFiles('Gemfile.lock') }}-lint
115+
path: react_on_rails/vendor/bundle
116+
key: package-app-gem-cache-${{ hashFiles('react_on_rails/Gemfile.lock') }}-lint
117117
- name: Install Node modules with Yarn for renderer package
118118
run: |
119119
yarn install --no-progress --no-emoji --frozen-lockfile
120120
sudo yarn global add yalc
121121
- name: yalc publish for react-on-rails
122122
run: cd packages/react-on-rails && yalc publish
123123
- name: yalc add react-on-rails
124-
run: cd spec/dummy && yalc add react-on-rails
124+
run: cd react_on_rails/spec/dummy && yalc add react-on-rails
125125
- name: Install Node modules with Yarn for dummy app
126-
run: cd spec/dummy && yarn install --no-progress --no-emoji --frozen-lockfile
126+
run: cd react_on_rails/spec/dummy && yarn install --no-progress --no-emoji
127127
- name: Install Ruby Gems for package
128-
run: bundle check --path=vendor/bundle || bundle _2.5.9_ install --path=vendor/bundle --jobs=4 --retry=3
128+
run: cd react_on_rails && bundle check --path=vendor/bundle || bundle _2.5.9_ install --path=vendor/bundle --jobs=4 --retry=3
129129
- name: Lint Ruby
130-
run: bundle exec rubocop
130+
run: cd react_on_rails && bundle exec rubocop
131131
- name: Validate RBS type signatures
132-
run: bundle exec rake rbs:validate
132+
run: cd react_on_rails && bundle exec rake rbs:validate
133133
# TODO: Re-enable Steep once RBS signatures are complete for all checked files
134134
# Currently disabled because 374 type errors need to be fixed first
135135
# - name: Run Steep type checker
136136
# run: bundle exec rake rbs:steep
137137
- name: Save dummy app ruby gems to cache
138138
uses: actions/cache@v4
139139
with:
140-
path: spec/dummy/vendor/bundle
141-
key: dummy-app-gem-cache-${{ hashFiles('spec/dummy/Gemfile.lock') }}-lint
140+
path: react_on_rails/spec/dummy/vendor/bundle
141+
key: dummy-app-gem-cache-${{ hashFiles('react_on_rails/spec/dummy/Gemfile.lock') }}-lint
142142
- name: Install Ruby Gems for dummy app
143143
run: |
144-
cd spec/dummy
144+
cd react_on_rails/spec/dummy
145145
bundle lock --add-platform 'x86_64-linux'
146146
if ! bundle check --path=vendor/bundle; then
147147
bundle _2.5.9_ install --path=vendor/bundle --jobs=4 --retry=3
148148
fi
149149
- name: generate file system-based packs
150-
run: cd spec/dummy && RAILS_ENV="test" bundle exec rake react_on_rails:generate_packs
150+
run: cd react_on_rails/spec/dummy && RAILS_ENV="test" bundle exec rake react_on_rails:generate_packs
151151
- name: Detect dead code
152152
run: |
153153
yarn run knip --exclude binaries
154-
yarn run knip --production --exclude binaries
155154
- name: Lint JS
156155
run: yarn run eslint --report-unused-disable-directives
157156
- name: Check formatting

.github/workflows/package-js-tests.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ on:
99
paths-ignore:
1010
- '**.md'
1111
- 'docs/**'
12-
- 'lib/**'
13-
- 'spec/react_on_rails/**'
12+
- 'react_on_rails/lib/**'
13+
- 'react_on_rails/spec/react_on_rails/**'
1414
- 'react_on_rails_pro/**'
1515
workflow_dispatch:
1616
inputs:

.github/workflows/playwright.yml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -61,32 +61,32 @@ jobs:
6161
run: yarn install
6262

6363
- name: Install dummy app dependencies
64-
working-directory: spec/dummy
64+
working-directory: react_on_rails/spec/dummy
6565
run: |
6666
bundle install
6767
yarn install
6868
6969
- name: Install Playwright browsers
70-
working-directory: spec/dummy
70+
working-directory: react_on_rails/spec/dummy
7171
run: yarn playwright install --with-deps
7272

7373
- name: Generate React on Rails packs
74-
working-directory: spec/dummy
74+
working-directory: react_on_rails/spec/dummy
7575
env:
7676
RAILS_ENV: test
7777
run: bundle exec rake react_on_rails:generate_packs
7878

7979
- name: Build test assets
80-
working-directory: spec/dummy
80+
working-directory: react_on_rails/spec/dummy
8181
run: yarn run build:test
8282

8383
- name: Run Playwright tests
84-
working-directory: spec/dummy
84+
working-directory: react_on_rails/spec/dummy
8585
run: yarn run test:e2e
8686

8787
- uses: actions/upload-artifact@v4
8888
if: always()
8989
with:
9090
name: playwright-report
91-
path: spec/dummy/e2e/playwright-report/
91+
path: react_on_rails/spec/dummy/e2e/playwright-report/
9292
retention-days: 30

.github/workflows/pro-integration-tests.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ on:
99
paths-ignore:
1010
- '**.md'
1111
- 'docs/**'
12-
- 'lib/**'
13-
- 'spec/**'
12+
- 'react_on_rails/lib/**'
13+
- 'react_on_rails/spec/**'
1414
- 'packages/react_on_rails/**'
1515
workflow_dispatch:
1616
inputs:

.github/workflows/pro-lint.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ on:
99
paths-ignore:
1010
- '**.md'
1111
- 'docs/**'
12-
- 'lib/**'
13-
- 'spec/**'
12+
- 'react_on_rails/lib/**'
13+
- 'react_on_rails/spec/**'
1414
- 'packages/react_on_rails/**'
1515
workflow_dispatch:
1616
inputs:
@@ -178,4 +178,5 @@ jobs:
178178
run: yarn run nps format.listDifferent
179179

180180
- name: Check TypeScript
181+
working-directory: .
181182
run: yarn run nps check-typescript

0 commit comments

Comments
 (0)