Automate Pro generator gem/package swap and import updates#2822
Automate Pro generator gem/package swap and import updates#2822
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughAdds a new --rsc-pro install mode and predicates, pins and retries RSC npm installs, and automates Pro upgrades by swapping the Gemfile gem, running bundle install with rollback, updating frontend imports to the Pro package, and updating install messages and tests. Changes
Sequence DiagramsequenceDiagram
actor User
participant CLI as CLI / Generator
participant Helper as Generator Helper
participant Installer as Install Generator
participant ProGen as Pro Generator
participant Gemfile as Gemfile (file)
participant Bundle as Bundler
participant NPM as npm / package.json
participant Files as Frontend files
User->>CLI: rails g react_on_rails:install --rsc-pro
CLI->>Helper: use_rsc_pro_mode?
Helper-->>CLI: true
CLI->>Installer: run install (rsc_pro: true)
Installer->>NPM: add RSC & Pro npm packages (pinned)
NPM-->>Installer: success / fallback to unpinned
User->>CLI: rails g react_on_rails:pro
CLI->>ProGen: run_generator (invoked_by_install?)
alt invoked_by_install == false
ProGen->>Gemfile: atomically replace react_on_rails → react_on_rails_pro
Gemfile-->>ProGen: updated
ProGen->>Bundle: spawn bundle install (with timeout)
Bundle-->>ProGen: success / fail
alt fail
ProGen->>Gemfile: rollback to previous content
end
ProGen->>Files: scan & rewrite imports to react-on-rails-pro
Files-->>ProGen: files updated
else invoked_by_install == true
ProGen-->>CLI: skip Gemfile & import swaps
end
ProGen-->>User: Pro setup complete
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Greptile SummaryThis PR extends the standalone Key changes:
Issues found:
Confidence Score: 3/5
Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A([run_generator]) --> B{invoked_by_install?}
B -- yes --> C[setup_pro]
B -- no --> D{prerequisites_met?}
D -- no --> E[add_error: prerequisites not met]
D -- yes --> F[swap_base_gem_for_pro_in_gemfile]
F --> G{Gemfile exists?}
G -- no --> H[skip]
G -- yes --> I{react_on_rails entry found?}
I -- no --> H
I -- yes --> J[Write updated Gemfile]
J --> K[bundle_install_after_gem_swap]
K --> L{bundle install succeeded?}
L -- yes --> M[continue]
L -- no --> N[add_warning: run manually]
M --> C
H --> C
C --> O[add_pro_npm_dependencies]
O --> P[update_imports_to_pro_package]
P --> Q[glob JS/TS files in app/javascript + client]
Q --> R{any imports to rewrite?}
R -- no --> S[skip]
R -- yes --> T[gsub react-on-rails -> react-on-rails-pro]
T --> U[print_success_message]
S --> U
U --> V([ensure: print_generator_messages])
Reviews (1): Last reviewed commit: "Automate Pro generator gem and import up..." | Re-trigger Greptile |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7be45091ca
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
PR Review: Automate Pro Generator Gem/Package SwapThe feature intent is correct and the overall structure is sound. One issue should be fixed before merge; the rest are lower-priority. Must FixExact version pin instead of pessimistic constraint (see inline comment on line 87) The replacement Gemfile line uses an exact pin ( Should FixImport regex can corrupt sibling package names (see inline comment on line 123) The pattern Gemfile indentation not preserved (see inline comment on lines 84-87) If the gem is inside a Low Priority / Follow-up
|
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
Autofix Details
Bugbot Autofix prepared fixes for both issues found in the latest run.
- ✅ Fixed: Duplicate Gemfile entry after auto-install plus swap
- The Gemfile swap now detects existing react_on_rails_pro entries and removes the react_on_rails line instead of adding a second pro gem declaration.
- ✅ Fixed: Gemfile replacement drops leading whitespace from indented gems
- The replacement regex now captures and reuses leading whitespace so indented gem lines keep their original indentation.
Or push these changes by commenting:
@cursor push 41d1ea4a52
Preview (41d1ea4a52)
diff --git a/react_on_rails/lib/generators/react_on_rails/pro_generator.rb b/react_on_rails/lib/generators/react_on_rails/pro_generator.rb
--- a/react_on_rails/lib/generators/react_on_rails/pro_generator.rb
+++ b/react_on_rails/lib/generators/react_on_rails/pro_generator.rb
@@ -82,9 +82,16 @@
return unless File.exist?(gemfile_path)
gemfile_content = File.read(gemfile_path)
+ pro_gem_line_pattern = /^\s*gem\s+["']react_on_rails_pro["'][^\n]*$/
+ pro_gem_already_present = gemfile_content.match?(pro_gem_line_pattern)
updated_content = gemfile_content.gsub(
- /^\s*gem\s+["']react_on_rails["'][^\n]*$/,
- "gem 'react_on_rails_pro', '#{recommended_pro_gem_version}'"
+ /^(\s*)gem\s+["']react_on_rails["'][^\n]*$/
+ ) do
+ if pro_gem_already_present
+ ""
+ else
+ "#{Regexp.last_match(1)}gem 'react_on_rails_pro', '#{recommended_pro_gem_version}'"
+ end
)
return if updated_content == gemfile_content
diff --git a/react_on_rails/spec/react_on_rails/generators/pro_generator_spec.rb b/react_on_rails/spec/react_on_rails/generators/pro_generator_spec.rb
--- a/react_on_rails/spec/react_on_rails/generators/pro_generator_spec.rb
+++ b/react_on_rails/spec/react_on_rails/generators/pro_generator_spec.rb
@@ -58,6 +58,7 @@
describe "#swap_base_gem_for_pro_in_gemfile" do
let(:generator) { described_class.new }
let(:gemfile_path) { File.join(destination_root, "Gemfile") }
+ let(:expected_version) { Gem::Version.new(ReactOnRails::VERSION).release.to_s }
before do
prepare_destination
@@ -74,12 +75,44 @@
generator.send(:swap_base_gem_for_pro_in_gemfile)
gemfile_content = File.read(gemfile_path)
- expected_version = Gem::Version.new(ReactOnRails::VERSION).release.to_s
expect(gemfile_content).to include("gem 'react_on_rails_pro', '#{expected_version}'")
expect(gemfile_content).not_to match(/gem\s+["']react_on_rails["']/)
expect(generator).to have_received(:bundle_install_after_gem_swap)
end
+ it "removes react_on_rails when react_on_rails_pro is already present" do
+ simulate_existing_file("Gemfile", <<~RUBY)
+ source "https://rubygems.org"
+ gem "react_on_rails", "~> 16.0"
+ gem "react_on_rails_pro", "~> 16.0"
+ RUBY
+ allow(generator).to receive(:bundle_install_after_gem_swap)
+
+ generator.send(:swap_base_gem_for_pro_in_gemfile)
+
+ gemfile_content = File.read(gemfile_path)
+ pro_gem_lines = gemfile_content.scan(/^\s*gem\s+["']react_on_rails_pro["'][^\n]*$/)
+ expect(pro_gem_lines.length).to eq(1)
+ expect(gemfile_content).not_to match(/gem\s+["']react_on_rails["']/)
+ expect(generator).to have_received(:bundle_install_after_gem_swap)
+ end
+
+ it "preserves leading whitespace when replacing indented react_on_rails entry" do
+ simulate_existing_file("Gemfile", <<~RUBY)
+ source "https://rubygems.org"
+
+ group :production do
+ gem "react_on_rails", "~> 16.0"
+ end
+ RUBY
+ allow(generator).to receive(:bundle_install_after_gem_swap)
+
+ generator.send(:swap_base_gem_for_pro_in_gemfile)
+
+ gemfile_content = File.read(gemfile_path)
+ expect(gemfile_content).to include(" gem 'react_on_rails_pro', '#{expected_version}'")
+ end
+
it "does nothing when Gemfile has no react_on_rails entry" do
simulate_existing_file("Gemfile", <<~RUBY)
source "https://rubygems.org"
Review: Automate Pro generator gem/package swap and import updatesGood overall direction — automating manual migration steps reduces friction for Pro upgrades. A few issues to address before merging. Potential bugs / reliability issues
Style / minor
What looks good
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 70acd651c6
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Review: Automate Pro generator gem/package swap and import updatesOverall this is a well-structured addition with solid test coverage. The three new methods each have a clear responsibility, the multiline Gemfile handling is correct, and the import-rewrite regex correctly avoids false positives on scoped packages, subpaths, and URLs. A few things to address: Bug — inline Gemfile comments break the gem swap (needs fix)
gem "react_on_rails" # pinned, don't upgrade automaticallyThis line won't be matched, so the base gem silently stays in the Gemfile alongside the new Pro entry. See inline comment on line 88. Thread-safety: prefer
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d1d84e286d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Review SummaryThe PR cleanly automates the Pro upgrade path and the implementation is well-structured. Test coverage for the Gemfile swap edge cases is thorough. A few issues worth addressing before merge: Medium: Gemfile left dirty if bundle install fails
Medium: gemspec-based Gemfiles silently skipped Projects that pin Minor: Process.spawn should use array form
Minor: .vue/.svelte files excluded from import rewriting Vue SFCs and Svelte components frequently import from Nit: The last alternative matches too broadly and causes unnecessary backtracking on every named/default import. Adding The multiline Gemfile consumption loop was reviewed carefully and the logic is correct for all traced cases (single-line, multi-continuation, trailing-comment-after-comma, last-line-of-file). |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9a52331289
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Autofix Details
Bugbot Autofix prepared a fix for the issue found in the latest run.
- ✅ Fixed: Comment-trailing commas falsely trigger multiline consumption
- I updated comma-continuation detection to strip trailing comments before checking for a code-level comma and added a regression spec ensuring the next Gemfile line is preserved.
Or push these changes by commenting:
@cursor push 1a3e8b72e2
Preview (1a3e8b72e2)
diff --git a/react_on_rails/lib/generators/react_on_rails/pro_generator.rb b/react_on_rails/lib/generators/react_on_rails/pro_generator.rb
--- a/react_on_rails/lib/generators/react_on_rails/pro_generator.rb
+++ b/react_on_rails/lib/generators/react_on_rails/pro_generator.rb
@@ -215,7 +215,8 @@
end
def line_continues_with_comma?(line)
- line.rstrip.match?(/,\s*(?:#.*)?\z/)
+ code_without_comment = line.sub(/\s*#.*\z/, "")
+ code_without_comment.rstrip.end_with?(",")
end
def print_success_message
diff --git a/react_on_rails/spec/react_on_rails/generators/pro_generator_spec.rb b/react_on_rails/spec/react_on_rails/generators/pro_generator_spec.rb
--- a/react_on_rails/spec/react_on_rails/generators/pro_generator_spec.rb
+++ b/react_on_rails/spec/react_on_rails/generators/pro_generator_spec.rb
@@ -193,6 +193,23 @@
expect(gemfile_content).not_to include("gem \"react_on_rails\" # pinned for compatibility")
expect(generator).to have_received(:bundle_install_after_gem_swap)
end
+
+ it "does not treat trailing comment commas as multiline continuation" do
+ simulate_existing_file("Gemfile", <<~RUBY)
+ source "https://rubygems.org"
+ gem "react_on_rails" # keep this one,
+ gem "rails"
+ RUBY
+ allow(generator).to receive(:bundle_install_after_gem_swap)
+
+ generator.send(:swap_base_gem_for_pro_in_gemfile)
+
+ gemfile_content = File.read(gemfile_path)
+ expected_version = Gem::Version.new(ReactOnRails::VERSION).release.to_s
+ expect(gemfile_content).to include("gem \"react_on_rails_pro\", \"~> #{expected_version}\"")
+ expect(gemfile_content).to include("gem \"rails\"")
+ expect(generator).to have_received(:bundle_install_after_gem_swap)
+ end
end
describe "#bundle_install_after_gem_swap" do|
|
||
| def line_has_unescaped_backtick?(line, line_for_tracking: nil) | ||
| line_to_track = line_for_tracking || line_for_template_literal_tracking(line) | ||
| update_multiline_template_literal_state(false, line_to_track) |
There was a problem hiding this comment.
Bug (edge case): wrong return value for lines with even backtick count
update_multiline_template_literal_state(false, line) returns false when the line has an even number of unescaped backticks (including 0, 2, 4 …), so line_has_unescaped_backtick? returns false for those lines even when backticks are actually present.
For the common case (2 backticks = one complete inline template literal), the line falls through to the normal yield path and rewrite_outside_inline_template_literals correctly masks the template content — so this is safe. However, for a line with 3 backticks, e.g.:
`done`; import("react-on-rails"); `multiline-startthe method returns true (odd count), so rewrite_line_before_template_literal_open is called. That method finds the first backtick at index 0, the opening_index&.positive? guard returns the line unchanged, and the import("react-on-rails") in the middle is never rewritten.
The Cursor autofix on this review (commit 2f35144a2a, branch cursor/template-literal-rewriting-bug-4fa1) fixes both this method and rewrite_line_before_template_literal_open to handle the single-line-then-multiline scenario. Applying that fix (or an equivalent) would close this gap.
This is an uncommon pattern in real JS, but it is a correctness hole in the import rewriter.
| 🚫 Failed to auto-install #{PRO_GEM_NAME} gem. | ||
|
|
||
| #{context_line} | ||
| #{prerelease_note} |
There was a problem hiding this comment.
Minor: double blank line when prerelease note is empty
When rsc_pro_prerelease_note returns "" (non-RSC-pro mode, or non-prerelease version), the #{prerelease_note} interpolation expands to an empty string, leaving two consecutive blank lines between context_line and Please add manually …:
You specified --pro, which requires the react_on_rails_pro gem.
Please add manually to your Gemfile:
One option to suppress the extra blank line when the note is empty:
| #{prerelease_note} | |
| #{prerelease_note.empty? ? nil : "#{prerelease_note}\n"} |
Or conditionally omit the line:
#{" #{prerelease_note}\n" unless prerelease_note.empty?}|
Code Review summary - see inline comments for specifics. Overall this is a well-engineered PR: Gemfile swap with multiline/parenthesized gem support, atomic writes, rollback-on-failure for bundle install, and the comment/template-literal-aware import rewriter are all solid. Test coverage is thorough. One remaining bug (inline comment on pro_generator.rb line 691): line_has_unescaped_backtick? delegates to update_multiline_template_literal_state(false, line) which returns false for lines with an even backtick count. For the 3-backtick case (complete template literal + dynamic import + multiline template literal start, all on one line), the odd count sends the line to rewrite_line_before_template_literal_open, which hits the opening_index not positive early return, and the import between the two template literals is never rewritten. The Cursor autofix on branch cursor/template-literal-rewriting-bug-4fa1 (commit 2f35144) addresses this. Minor (inline comment on pro_setup.rb line 70): when rsc_pro_prerelease_note returns an empty string, the heredoc interpolation leaves two consecutive blank lines in the error output. |
| next_line = gemfile_lines[line_index] | ||
| current_line = next_line unless comment_or_blank_line?(next_line) | ||
| line_index += 1 | ||
| end |
There was a problem hiding this comment.
Bug: options on non-parenthesized multiline continuation lines are silently dropped.
The suffix passed to build_pro_gem_replacement_line is taken exclusively from line[match.end(0)..] (the tail of the first matched line). When a non-parenthesized declaration spreads Ruby options across continuation lines, e.g.:
gem "react_on_rails",
"~> 16.0",
require: false # ← this line is consumed below but never capturedthe require: false line is consumed by this inner while loop but is never appended to suffix, so it's silently lost in the replacement.
The parenthesized form (gem(...)) handles this correctly via match_multiline_parenthesized_base_gem and the multi-line trailing_suffix construction. The non-parenthesized form needs the same treatment: collect every consumed non-version-string continuation line and append it to suffix.
There is no test covering this pattern (multiline non-parenthesized with a Ruby keyword argument on a continuation line).
| temp_path = nil | ||
| ensure | ||
| temp_file&.close unless temp_file&.closed? | ||
| File.delete(temp_path) if temp_path && File.exist?(temp_path) |
There was a problem hiding this comment.
Tempfile finalizer will attempt to unlink the already-moved file.
After FileUtils.mv(temp_path, path) succeeds and temp_path = nil is set, the temp_file object still holds the original path internally. When it is garbage-collected, Ruby's Tempfile finalizer will call unlink on that path — which no longer exists. This is harmless (the unlink silently fails) but it is a resource-management smell.
To be explicit and avoid the dangling finalizer, call temp_file.unlink immediately after the mv (before setting temp_path = nil):
| File.delete(temp_path) if temp_path && File.exist?(temp_path) | |
| FileUtils.mv(temp_path, path) | |
| temp_file.unlink | |
| File.chmod(original_mode, path) if original_mode | |
| temp_path = nil |
| next [] unless Dir.exist?(root_path) | ||
|
|
||
| Dir.glob(File.join(root_path, "**", "*.{#{js_extensions}}")) | ||
| .reject { |f| f.include?("/node_modules/") } |
There was a problem hiding this comment.
Unix-only path separator in node_modules exclusion.
f.include?("/node_modules/") uses a hard-coded forward slash. On Windows the path would contain \node_modules\, so this filter would silently fail and the generator would attempt to rewrite files inside node_modules.
| .reject { |f| f.include?("/node_modules/") } | |
| .reject { |f| f.include?("#{File::SEPARATOR}node_modules#{File::SEPARATOR}") } |
Or simply:
| .reject { |f| f.include?("/node_modules/") } | |
| .reject { |f| f.split(File::SEPARATOR).include?("node_modules") } |
| static_import_specifier_pattern = %r{ | ||
| (?<prefix> | ||
| \A\s*(?:/\*.*?\*/\s*)?(?:import|export)(?:\s+type)?\s+.*?\s+from\s+| | ||
| \A\s*[\w\}\],\*\$\s]+\s+from\s+ | ||
| ) | ||
| (?<quote>["']) | ||
| react-on-rails(?!-pro) | ||
| (?=(?:["']|/)) | ||
| }x |
There was a problem hiding this comment.
\A anchor with String#gsub rewrites at most one match per line for static imports.
\A anchors to the very start of the string (here, one line). gsub can only find a second match after the first, but \A never matches except at position 0, so at most one static import per line is rewritten.
For the common case this is fine (one import per line). However a line like:
import A from "react-on-rails"; import B from "react-on-rails";would have only the first import rewritten. The dynamic_or_require_specifier_pattern (no \A) handles its targets correctly for multi-occurrence lines.
This is a low-probability edge case, but it's worth documenting as a known limitation, or switching to ^ (start-of-line) with the m flag and \n? at the end of the match to stay line-scoped.
| pid = Process.spawn( | ||
| { "BUNDLE_GEMFILE" => gemfile_path }, | ||
| "bundle", | ||
| "install", | ||
| out: $stdout, | ||
| err: $stderr, | ||
| chdir: destination_root | ||
| ) | ||
| wait_for_bundle_process(pid) |
There was a problem hiding this comment.
bundle install output is interleaved with generator output.
out: $stdout, err: $stderr routes the subprocess's stdio to the generator's own handles. During a normal rails generate run this means raw Bundler output (resolving gems, fetching sources, etc.) is printed inline with the generator's own say_status lines, without any visual distinction.
Consider buffering or suppressing subprocess output and only surfacing it on failure, similar to how attempt_pro_gem_auto_install in ProSetup works. If verbose output is desired, at minimum print a separator so users know what they're seeing:
say "─── bundle install output ───────────────────────────────────", :cyanThere was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
There are 5 total unresolved issues (including 4 from previous reviews).
Bugbot Autofix prepared a fix for the issue found in the latest run.
- ✅ Fixed: RSC Pro auto-install uses
~>instead of exact pin- Updated
pro_gem_auto_install_commandto omit--strictin RSC Pro mode sobundle addkeeps the exact version pin, and adjusted the RSC Pro install spec expectations accordingly.
- Updated
Or push these changes by commenting:
@cursor push c86d3e44f1
Preview (c86d3e44f1)
diff --git a/react_on_rails/lib/generators/react_on_rails/pro_setup.rb b/react_on_rails/lib/generators/react_on_rails/pro_setup.rb
--- a/react_on_rails/lib/generators/react_on_rails/pro_setup.rb
+++ b/react_on_rails/lib/generators/react_on_rails/pro_setup.rb
@@ -483,7 +483,9 @@
end
def pro_gem_auto_install_command
- "bundle add #{PRO_GEM_NAME} --version='#{pro_gem_version_requirement}' --strict"
+ command = "bundle add #{PRO_GEM_NAME} --version='#{pro_gem_version_requirement}'"
+ command += " --strict" unless use_rsc_pro_mode?
+ command
end
def pro_gem_version_requirement
diff --git a/react_on_rails/spec/react_on_rails/generators/install_generator_spec.rb b/react_on_rails/spec/react_on_rails/generators/install_generator_spec.rb
--- a/react_on_rails/spec/react_on_rails/generators/install_generator_spec.rb
+++ b/react_on_rails/spec/react_on_rails/generators/install_generator_spec.rb
@@ -2881,7 +2881,7 @@
expect(install_generator.send(:missing_pro_gem?)).to be true
expect(Bundler).to have_received(:with_unbundled_env)
expect(Process).to have_received(:spawn)
- .with("bundle add react_on_rails_pro --version='#{expected_pro_version}' --strict",
+ .with("bundle add react_on_rails_pro --version='#{expected_pro_version}'",
out: anything,
err: anything)
error_text = GeneratorMessages.messages.join("\n")
@@ -2895,7 +2895,7 @@
expect(install_generator.send(:missing_pro_gem?)).to be true
expect(Process).to have_received(:spawn)
- .with("bundle add react_on_rails_pro --version='16.4.0.rc.5' --strict",
+ .with("bundle add react_on_rails_pro --version='16.4.0.rc.5'",
out: anything,
err: anything)
error_text = GeneratorMessages.messages.join("\n")You can send follow-ups to this agent here.
|
|
||
| def pro_gem_auto_install_command | ||
| "bundle add #{PRO_GEM_NAME} --version='~> #{recommended_pro_gem_version}' --strict" | ||
| "bundle add #{PRO_GEM_NAME} --version='#{pro_gem_version_requirement}' --strict" |
There was a problem hiding this comment.
RSC Pro auto-install uses ~> instead of exact pin
Low Severity
pro_gem_auto_install_command unconditionally appends --strict, which tells bundle add to use the ~> operator. In RSC Pro mode, pro_gem_version_requirement returns an exact version (e.g., "16.4.0"), so the command produces gem "react_on_rails_pro", "~> 16.4.0" instead of the intended exact pin "16.4.0". The standalone pro generator's swap corrects this, but the install generator skips the swap, leaving a pessimistic constraint.
Additional Locations (1)
The --rsc-pro flag was redundant with --rsc (which already implies Pro) and was originally closed as an "unnecessary parallel mode" in #2821 before shipping unintentionally alongside the Pro upgrade automation in #2822. Fold the useful behaviors previously gated on --rsc-pro into --rsc: - Pro verification checklist message now fires on any --rsc install instead of only when use_rsc_pro_mode? was true. - Prerelease installation note (rsc_prerelease_note) now fires on any --rsc install with a prerelease gem version. - Exact version pin for the Pro gem now triggers on Gem::Version.new(ReactOnRails::VERSION).prerelease? instead of the flag. This is the real underlying reason: Bundler's ~> does not match prerelease versions, so stable --rsc installs continue to use ~> while prerelease cycles get an exact pin that actually installs. Side effect: plain --rsc on a prerelease gem version now installs correctly where it previously would have failed against ~> pinning. Removes: - class_option :rsc_pro - use_rsc_pro_mode? helper - the --rsc-pro branches in use_pro?, use_rsc?, pro_requirement_flag, recovery_install_command - all --rsc-pro test contexts in install_generator_spec and the RSC Pro mode helpers describe block in generator_helper_spec Does not touch pro_generator.rb or pro_generator_spec.rb; those cover the #2626 upgrade automation scope (independent of this flag), and the silent-failure bugs there are tracked separately in #3104. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
## Summary - Add first-class `--rsc-pro` install mode to the generator, unifying `--rsc --pro` into a single flag with matched Pro/RSC defaults, verification checklist, and recovery commands - Extend standalone `react_on_rails:pro` upgrade flow to automate Gemfile gem swap (`react_on_rails` → `react_on_rails_pro`) with mode-aware version requirements (`~>` for standard Pro, exact pin in RSC Pro mode when applicable), plus `bundle install` after swap and automatic rollback on failure - Rewrite JS/TS/Vue/Svelte imports from `react-on-rails` to `react-on-rails-pro` across common frontend roots using atomic file writes, with full comment-aware parsing (block comments, multiline imports, and inline template-literal masking to avoid false rewrites inside template strings) - Improve `package_json` add return handling — treat `nil` as success instead of falsy failure - Pin RSC dependencies to explicit versions (`react`/`react-dom` to `~19.0.4`, `react-on-rails-rsc` to `19.0.4`) with fallback to unpinned install when pinned install fails - Improve Pro flag detection: `use_pro?` and `use_rsc?` now respect `--rsc-pro`, and new `use_rsc_pro_mode?` helper controls RSC Pro–specific behavior - Add Pro gem version requirement helper (`pro_gem_version_requirement`) — exact pin for RSC Pro mode, pessimistic (`~>`) for standard Pro - Add prerelease messaging for RSC Pro mode when the gem version is a prerelease - Add RSC Pro post-install verification message with startup/streaming/hydration checklist Closes #2626 ## Test Plan - `bundle exec rspec react_on_rails/spec/react_on_rails/generators/pro_generator_spec.rb` - `bundle exec rspec react_on_rails/spec/react_on_rails/generators/generator_helper_spec.rb` - `bundle exec rspec react_on_rails/spec/react_on_rails/generators/install_generator_spec.rb` - `bundle exec rspec react_on_rails/spec/react_on_rails/generators/js_dependency_manager_spec.rb` - `bundle exec rubocop react_on_rails/lib/generators/react_on_rails/pro_generator.rb react_on_rails/lib/generators/react_on_rails/pro_setup.rb react_on_rails/lib/generators/react_on_rails/install_generator.rb` 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Medium risk: generator behavior now mutates `Gemfile`/runs `bundle install`, pins RSC/Pro versions, and rewrites frontend imports, which could impact existing apps if edge cases in parsing or version constraints are missed. > > **Overview** > Adds a first-class `--rsc-pro` installation mode (and `use_rsc_pro_mode?` helper) so install flows, sub-generator invocation, recovery commands, prerequisite errors, and post-install messaging treat RSC+Pro as a single, consistent mode. > > Enhances dependency handling by treating `package_json` `add` returning `nil` as success, pinning RSC React versions to `~19.0.4`, pinning `react-on-rails-rsc` to `19.0.4` with retry-to-latest fallback, and making Pro gem version requirements exact in RSC Pro mode. > > Extends `react_on_rails:pro` to automatically swap `react_on_rails` → `react_on_rails_pro` in `Gemfile` (with atomic writes, `bundle install`, and rollback on failure) and to rewrite JS/TS/Vue/Svelte imports from `react-on-rails` to `react-on-rails-pro`, with extensive spec coverage for edge cases. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 7c0ecb8. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added `--rsc-pro` CLI option to enable first-class React Server Components with Pro features in a single installation command. * Automatic Gemfile gem swap from `react_on_rails` to `react_on_rails_pro` with bundler integration. * Automatic rewriting of module imports from `react-on-rails` to `react-on-rails-pro` across JavaScript/TypeScript files. * Introduced React version pinning (~19.0.4) for RSC installations. * **Bug Fixes** * Improved npm dependency installation return value handling to correctly interpret `nil` responses as successful. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
## Summary - Add first-class `--rsc-pro` install mode to the generator, unifying `--rsc --pro` into a single flag with matched Pro/RSC defaults, verification checklist, and recovery commands - Extend standalone `react_on_rails:pro` upgrade flow to automate Gemfile gem swap (`react_on_rails` → `react_on_rails_pro`) with mode-aware version requirements (`~>` for standard Pro, exact pin in RSC Pro mode when applicable), plus `bundle install` after swap and automatic rollback on failure - Rewrite JS/TS/Vue/Svelte imports from `react-on-rails` to `react-on-rails-pro` across common frontend roots using atomic file writes, with full comment-aware parsing (block comments, multiline imports, and inline template-literal masking to avoid false rewrites inside template strings) - Improve `package_json` add return handling — treat `nil` as success instead of falsy failure - Pin RSC dependencies to explicit versions (`react`/`react-dom` to `~19.0.4`, `react-on-rails-rsc` to `19.0.4`) with fallback to unpinned install when pinned install fails - Improve Pro flag detection: `use_pro?` and `use_rsc?` now respect `--rsc-pro`, and new `use_rsc_pro_mode?` helper controls RSC Pro–specific behavior - Add Pro gem version requirement helper (`pro_gem_version_requirement`) — exact pin for RSC Pro mode, pessimistic (`~>`) for standard Pro - Add prerelease messaging for RSC Pro mode when the gem version is a prerelease - Add RSC Pro post-install verification message with startup/streaming/hydration checklist Closes #2626 ## Test Plan - `bundle exec rspec react_on_rails/spec/react_on_rails/generators/pro_generator_spec.rb` - `bundle exec rspec react_on_rails/spec/react_on_rails/generators/generator_helper_spec.rb` - `bundle exec rspec react_on_rails/spec/react_on_rails/generators/install_generator_spec.rb` - `bundle exec rspec react_on_rails/spec/react_on_rails/generators/js_dependency_manager_spec.rb` - `bundle exec rubocop react_on_rails/lib/generators/react_on_rails/pro_generator.rb react_on_rails/lib/generators/react_on_rails/pro_setup.rb react_on_rails/lib/generators/react_on_rails/install_generator.rb` 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Medium risk: generator behavior now mutates `Gemfile`/runs `bundle install`, pins RSC/Pro versions, and rewrites frontend imports, which could impact existing apps if edge cases in parsing or version constraints are missed. > > **Overview** > Adds a first-class `--rsc-pro` installation mode (and `use_rsc_pro_mode?` helper) so install flows, sub-generator invocation, recovery commands, prerequisite errors, and post-install messaging treat RSC+Pro as a single, consistent mode. > > Enhances dependency handling by treating `package_json` `add` returning `nil` as success, pinning RSC React versions to `~19.0.4`, pinning `react-on-rails-rsc` to `19.0.4` with retry-to-latest fallback, and making Pro gem version requirements exact in RSC Pro mode. > > Extends `react_on_rails:pro` to automatically swap `react_on_rails` → `react_on_rails_pro` in `Gemfile` (with atomic writes, `bundle install`, and rollback on failure) and to rewrite JS/TS/Vue/Svelte imports from `react-on-rails` to `react-on-rails-pro`, with extensive spec coverage for edge cases. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 7c0ecb8. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added `--rsc-pro` CLI option to enable first-class React Server Components with Pro features in a single installation command. * Automatic Gemfile gem swap from `react_on_rails` to `react_on_rails_pro` with bundler integration. * Automatic rewriting of module imports from `react-on-rails` to `react-on-rails-pro` across JavaScript/TypeScript files. * Introduced React version pinning (~19.0.4) for RSC installations. * **Bug Fixes** * Improved npm dependency installation return value handling to correctly interpret `nil` responses as successful. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
## Summary - Add missing test assertions for the `--rsc-pro` generator context to match the thoroughness of the `--rsc` tests - Verifies node-renderer.js creation, RSC bundle watcher in Procfile.dev, HelloServer replacing HelloWorld (controller + routes + components), hello_server and rsc_payload routes, and rscWebpackConfig.js The `--rsc-pro` generator mode implementation was completed in #2822, but the test coverage was incomplete — only version pinning and DEFAULT_ROUTE were verified. This closes the gap by adding route, component, Procfile, and webpack config assertions. Closes #2793 ## Test plan - [x] `bundle exec rspec react_on_rails/spec/react_on_rails/generators/install_generator_spec.rb -e "with --rsc-pro"` — 12 examples, 0 failures - [x] `bundle exec rubocop` — no offenses 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Low risk: only adds RSpec assertions around generator output, with no production code changes. Main risk is increased test brittleness if templates evolve. > > **Overview** > Strengthens test coverage for the `react_on_rails:install --rsc-pro` path by asserting generation of `client/node-renderer.js`, the RSC bundle watcher entry in `Procfile.dev`, and the switch from `HelloWorld` scaffolding to `HelloServer`. > > Adds checks that `config/routes.rb` includes both `hello_server` and `rsc_payload`, and verifies RSC-specific webpack artifacts (`config/webpack/rscWebpackConfig.js` plus `RSCWebpackPlugin` usage and the `rscBundle` parameter in `serverWebpackConfig`). > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 1b5b1d1. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Tests** * Expanded test coverage for installation configuration validation, including scaffold setup and configuration file generation checks. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
The --rsc-pro flag was redundant with --rsc (which already implies Pro) and was originally closed as an "unnecessary parallel mode" in #2821 before shipping unintentionally alongside the Pro upgrade automation in #2822. Fold the useful behaviors previously gated on --rsc-pro into --rsc: - Pro verification checklist message now fires on any --rsc install instead of only when use_rsc_pro_mode? was true. - Prerelease installation note (rsc_prerelease_note) now fires on any --rsc install with a prerelease gem version. - Exact version pin for the Pro gem now triggers on Gem::Version.new(ReactOnRails::VERSION).prerelease? instead of the flag. This is the real underlying reason: Bundler's ~> does not match prerelease versions, so stable --rsc installs continue to use ~> while prerelease cycles get an exact pin that actually installs. Side effect: plain --rsc on a prerelease gem version now installs correctly where it previously would have failed against ~> pinning. Removes: - class_option :rsc_pro - use_rsc_pro_mode? helper - the --rsc-pro branches in use_pro?, use_rsc?, pro_requirement_flag, recovery_install_command - all --rsc-pro test contexts in install_generator_spec and the RSC Pro mode helpers describe block in generator_helper_spec Does not touch pro_generator.rb or pro_generator_spec.rb; those cover the #2626 upgrade automation scope (independent of this flag), and the silent-failure bugs there are tracked separately in #3104. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
## Summary #2821 introduced a dedicated `--rsc-pro` install flag. It was closed the next day with: "Closing as redundant: current generator semantics already treat --rsc as including Pro by design, so introducing --rsc-pro adds an unnecessary parallel mode." The flag then shipped anyway in #2822, which was primarily about the Pro upgrade automation (#2626 — Gemfile swap, import rewriter). The --rsc-pro bits rode along as a ~10% passenger in that larger PR and were never removed after #2821's close. #3098 was then opened to add more tests for the flag, further entrenching something that was explicitly called redundant. This PR completes the intent behind #2821's close: removes the flag and folds its useful behaviors into --rsc, where they belong. ## What moves from --rsc-pro to --rsc - Pro verification checklist now fires on any --rsc install - Prerelease installation note now fires on any --rsc install with a prerelease gem version - Exact version pin for the Pro gem now triggers on `Gem::Version.new(ReactOnRails::VERSION).prerelease?` instead of the flag — this is the real reason exact pinning matters (Bundler's `~>` doesn't match prereleases), not a flag-specific behavior Side effect: plain `--rsc` on a prerelease gem version now installs correctly where it previously would have failed against `~>` pinning. ## What is removed - `class_option :rsc_pro` - `use_rsc_pro_mode?` helper - `--rsc-pro` branches in `use_pro?`, `use_rsc?`, `pro_requirement_flag`, `recovery_install_command` - All `--rsc-pro` test contexts ## What is NOT touched `pro_generator.rb` and `pro_generator_spec.rb` (the #2626 upgrade automation — Gemfile swap, import rewriter) are independent of this flag and untouched. Bugs in that code are tracked separately in #3104. ## Closes / supersedes Supersedes #3098 (its test assertions were inside `context "with --rsc-pro"`, which no longer exists). ## Test plan - `bundle exec rubocop` on all modified files — clean - CI to run the full rspec suite 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Removed** * The Pro-specific install flag `--rsc-pro` has been removed. * **Changed** * Pro-related behaviors that previously required `--rsc-pro` now apply when using `--rsc` (post-install verification checklist, prerelease install notes, and exact Pro gem pinning for prereleases). * **Chore** * Added a URL exclusion to link-checking configuration to skip a specific domain. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>



Summary
--rsc-proinstall mode to the generator, unifying--rsc --prointo a single flag with matched Pro/RSC defaults, verification checklist, and recovery commandsreact_on_rails:proupgrade flow to automate Gemfile gem swap (react_on_rails→react_on_rails_pro) with mode-aware version requirements (~>for standard Pro, exact pin in RSC Pro mode when applicable), plusbundle installafter swap and automatic rollback on failurereact-on-railstoreact-on-rails-proacross common frontend roots using atomic file writes, with full comment-aware parsing (block comments, multiline imports, and inline template-literal masking to avoid false rewrites inside template strings)package_jsonadd return handling — treatnilas success instead of falsy failurereact/react-domto~19.0.4,react-on-rails-rscto19.0.4) with fallback to unpinned install when pinned install failsuse_pro?anduse_rsc?now respect--rsc-pro, and newuse_rsc_pro_mode?helper controls RSC Pro–specific behaviorpro_gem_version_requirement) — exact pin for RSC Pro mode, pessimistic (~>) for standard ProCloses #2626
Test Plan
bundle exec rspec react_on_rails/spec/react_on_rails/generators/pro_generator_spec.rbbundle exec rspec react_on_rails/spec/react_on_rails/generators/generator_helper_spec.rbbundle exec rspec react_on_rails/spec/react_on_rails/generators/install_generator_spec.rbbundle exec rspec react_on_rails/spec/react_on_rails/generators/js_dependency_manager_spec.rbbundle exec rubocop react_on_rails/lib/generators/react_on_rails/pro_generator.rb react_on_rails/lib/generators/react_on_rails/pro_setup.rb react_on_rails/lib/generators/react_on_rails/install_generator.rb🤖 Generated with Claude Code
Note
Medium Risk
Medium risk: generator behavior now mutates
Gemfile/runsbundle install, pins RSC/Pro versions, and rewrites frontend imports, which could impact existing apps if edge cases in parsing or version constraints are missed.Overview
Adds a first-class
--rsc-proinstallation mode (anduse_rsc_pro_mode?helper) so install flows, sub-generator invocation, recovery commands, prerequisite errors, and post-install messaging treat RSC+Pro as a single, consistent mode.Enhances dependency handling by treating
package_jsonaddreturningnilas success, pinning RSC React versions to~19.0.4, pinningreact-on-rails-rscto19.0.4with retry-to-latest fallback, and making Pro gem version requirements exact in RSC Pro mode.Extends
react_on_rails:proto automatically swapreact_on_rails→react_on_rails_proinGemfile(with atomic writes,bundle install, and rollback on failure) and to rewrite JS/TS/Vue/Svelte imports fromreact-on-railstoreact-on-rails-pro, with extensive spec coverage for edge cases.Written by Cursor Bugbot for commit 7c0ecb8. This will update automatically on new commits. Configure here.
Summary by CodeRabbit
New Features
--rsc-proCLI option to enable first-class React Server Components with Pro features in a single installation command.react_on_railstoreact_on_rails_prowith bundler integration.react-on-railstoreact-on-rails-proacross JavaScript/TypeScript files.Bug Fixes
nilresponses as successful.