Fix doctor command false version mismatch for beta/prerelease versions#2064
Fix doctor command false version mismatch for beta/prerelease versions#2064
Conversation
Fixes #2063 ## Problem The doctor command incorrectly reported version mismatches for beta/alpha/rc versions even when gem and NPM package versions were identical. For example: - Gem: 16.2.0.beta.10 - NPM: 16.2.0-beta.10 Would trigger a false "version mismatch" warning. ## Root Cause The original code (from PR #1787) stripped all non-numeric/non-dot characters from the NPM version for comparison: ```ruby clean_npm_version = npm_version.gsub(/[^0-9.]/, "") # "16.2.0-beta.10" → "16.2.0.10" gem_version = ReactOnRails::VERSION # "16.2.0.beta.10" ``` This removed both the dash AND "beta", turning "16.2.0-beta.10" into "16.2.0.10", which would never match "16.2.0.beta.10". Note: CodeRabbit caught this bug during the original PR review but the suggestion was not implemented. ## Solution Use the existing VersionSyntaxConverter.npm_to_rubygem utility which properly converts NPM semver format (dash separator) to Ruby gem format (dot separator): - "16.2.0-beta.10" → "16.2.0.beta.10" - "^16.2.0-beta.10" → "16.2.0.beta.10" - Handles all prerelease formats: beta, alpha, rc, pre ## Testing Verified with test app using both gem and NPM at 16.2.0.beta.10: - ✅ Matching versions: No false warning - ✅ Caret/tilde prefixes: Handled correctly - ✅ Real mismatches: Still detected properly - ✅ All edge cases: 16/16 test scenarios pass 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
WalkthroughThe changes fix a version mismatch detection bug where NPM prerelease versions (e.g., Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes
Possibly related PRs
Suggested labels
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing touches
🧪 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 |
Addresses missing test coverage for the version sync check that was identified during bug investigation. ## Tests Added (9 scenarios) **Matching versions:** - Beta versions: 16.2.0-beta.10 matches 16.2.0.beta.10 - Beta with caret prefix: ^16.2.0-beta.10 - Alpha versions: 16.2.0-alpha.5 - RC versions: 16.2.0-rc.1 - Stable versions: 16.2.0 **Mismatches:** - Minor version mismatch: beta.9 vs beta.10 → warning - Major version mismatch: v15 vs v16 → error **Edge cases:** - No package.json file - Invalid JSON in package.json ## Coverage Impact Before: 31 specs for SystemChecker (check_package_version_sync had 0 tests) After: 40 specs (added 9 tests for check_package_version_sync) All tests pass, ensuring the bug fix works correctly and preventing future regressions. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Code Review: Fix doctor command false version mismatch for beta/prerelease versions✅ Overall Assessment: LGTM with minor suggestionsThis is an excellent bug fix that addresses a real issue with prerelease version matching. The solution is clean, well-documented, and leverages existing tested code. 🎯 Strengths
🔍 Code QualityFile: The changes are minimal and focused: # Before (buggy)
clean_npm_version = npm_version.gsub(/[^0-9.]/, "")
# After (correct)
converter = ReactOnRails::VersionSyntaxConverter.new
normalized_npm_version = converter.npm_to_rubygem(npm_version)Correctness: ✅ The fix properly handles:
📋 Suggestions1. Add Test Coverage (Important)While Recommendation: Add a test case like this: describe "#check_package_version_sync" do
context "when versions match with prerelease format" do
let(:package_json_content) do
{ "dependencies" => { "react-on-rails" => "16.2.0-beta.10" } }.to_json
end
before do
allow(File).to receive(:exist?).with("package.json").and_return(true)
allow(File).to receive(:read).with("package.json").and_return(package_json_content)
stub_const("ReactOnRails::VERSION", "16.2.0.beta.10")
end
it "reports matching versions without warnings" do
checker.send(:check_package_version_sync)
expect(checker.messages.any? { |msg| msg[:type] == :success }).to be true
expect(checker.warnings?).to be false
end
end
context "when versions have prerelease mismatch" do
let(:package_json_content) do
{ "dependencies" => { "react-on-rails" => "16.2.0-beta.9" } }.to_json
end
before do
allow(File).to receive(:exist?).with("package.json").and_return(true)
allow(File).to receive(:read).with("package.json").and_return(package_json_content)
stub_const("ReactOnRails::VERSION", "16.2.0.beta.10")
end
it "reports version mismatch warning" do
checker.send(:check_package_version_sync)
expect(checker.warnings?).to be true
expect(checker.messages.last[:content]).to include("Version mismatch detected")
end
end
endThis would prevent future regressions and document the expected behavior. 2. Potential Edge Case: nil handlingLooking at def npm_to_rubygem(npm_version)
match = npm_version
.tr("-", ".")
.strip
.match(/(\d.*)/)
match.present? ? match[0] : nil
endIf Current code at line 229: npm_major = normalized_npm_version.split(".")[0].to_iRecommendation: Add a safety check: if normalized_npm_version.nil?
add_warning("⚠️ Could not parse NPM package version: #{npm_version}")
return
end
if normalized_npm_version == gem_version
# ... rest of the logicHowever, this is likely a theoretical edge case since 3. Minor: Instance CreationThe converter is instantiated but has no state: converter = ReactOnRails::VersionSyntaxConverter.new
normalized_npm_version = converter.npm_to_rubygem(npm_version)Could be simplified to: normalized_npm_version = ReactOnRails::VersionSyntaxConverter.new.npm_to_rubygem(npm_version)But the current approach is perfectly fine and more readable. This is purely stylistic. 🔒 Security Considerations✅ No security concerns. The code processes version strings from ⚡ Performance Considerations✅ Negligible performance impact. Creating one converter instance and calling a simple string transformation method during a diagnostic rake task is trivial. 🧪 Testing RequirementsAccording to
Recommendation before merge: bundle exec rubocop lib/react_on_rails/system_checker.rbThe git hooks should catch this automatically, but worth verifying. 📝 Documentation✅ The PR description is exemplary - it includes:
The inline code comment is clear and helpful. 🎓 Historical ContextExcellent catch noting that CodeRabbit flagged this during the original PR #1787 review but it wasn't addressed. This reinforces the value of code review feedback! Final Recommendation: APPROVE ✅This PR successfully fixes a real bug with a clean, well-thought-out solution. The only improvement I'd strongly recommend is adding test coverage for Merge checklist:
Great work! 🎉 Reviewed using project guidelines from |
Code Review - PR #2064: Fix doctor command false version mismatch✅ Overall AssessmentThis is an excellent fix that resolves a real bug with a clean, well-tested solution. The PR demonstrates strong understanding of the codebase and follows best practices. 🎯 Strengths1. Problem Identification
2. Solution Quality
3. Test Coverage
4. Documentation
🔍 Potential Issues & Suggestions1. Nil Handling Edge Case
|
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
spec/lib/react_on_rails/system_checker_spec.rb (1)
324-481: New#check_package_version_synccoverage is thorough and matches the intended behaviorThis block does a good job exercising all the important paths: missing
package.json, matching prerelease variants (beta/alpha/rc) and stable, caret‑prefixed prerelease (success + warning), minor vs major mismatches, and invalid JSON handling. The use ofstub_constper context keepsReactOnRails::VERSIONexplicit and aligned with each scenario.If you want to lock in parity with all prerelease formats mentioned in the PR description, you could optionally add one more example for a
-pre/.prepairing, but the current suite already gives solid confidence in the new normalization logic.lib/react_on_rails/system_checker.rb (1)
216-221: Switch toVersionSyntaxConvertercorrectly fixes prerelease comparisonNormalizing the npm version via
ReactOnRails::VersionSyntaxConverter#npm_to_rubygemand comparingnormalized_npm_versiontoReactOnRails::VERSIONis the right move here and should resolve the beta/alpha/rc false mismatches (e.g.,"16.2.0-beta.10"→"16.2.0.beta.10"). Using the normalized value as the basis fornpm_majoralso keeps the major‑version check consistent.Guard against
nilfromnpm_to_rubygemto avoid relying on generic rescueIn edge cases where the npm spec has no digits at all (e.g.,
"latest"or a pure git URL),npm_to_rubygemcan returnnil, which will causenormalized_npm_version.split('.')to raise and be swallowed by the broadrescue StandardError. It’d be cleaner and cheaper to handle that explicitly before splitting, e.g.:- normalized_npm_version = converter.npm_to_rubygem(npm_version) + normalized_npm_version = converter.npm_to_rubygem(npm_version) + return unless normalized_npm_versionThis keeps behavior graceful without depending on an exception path for control flow.
Also applies to: 223-223, 229-229
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
lib/react_on_rails/system_checker.rb(1 hunks)spec/lib/react_on_rails/system_checker_spec.rb(1 hunks)
🧰 Additional context used
🧠 Learnings (7)
📓 Common learnings
Learnt from: alexeyr-ci
Repo: shakacode/react_on_rails PR: 1687
File: spec/dummy/package.json:0-0
Timestamp: 2025-01-23T18:20:45.824Z
Learning: When adding or updating dependencies in spec/dummy/package.json, maintain version consistency with other package.json files in the codebase to avoid potential version conflicts.
📚 Learning: 2025-01-23T18:20:45.824Z
Learnt from: alexeyr-ci
Repo: shakacode/react_on_rails PR: 1687
File: spec/dummy/package.json:0-0
Timestamp: 2025-01-23T18:20:45.824Z
Learning: When adding or updating dependencies in spec/dummy/package.json, maintain version consistency with other package.json files in the codebase to avoid potential version conflicts.
Applied to files:
spec/lib/react_on_rails/system_checker_spec.rblib/react_on_rails/system_checker.rb
📚 Learning: 2025-09-29T14:45:42.687Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1833
File: lib/react_on_rails/dev/process_manager.rb:72-83
Timestamp: 2025-09-29T14:45:42.687Z
Learning: In Ruby bundler contexts, when bundler intercepts system commands for executables not in the Gemfile, both version checks (like `system("foreman", "--version")`) and execution commands (like `system("foreman", "start", ...)`) fail equally, both returning false. This means availability checks using version flags accurately reflect whether execution commands will work in the current bundler context.
Applied to files:
spec/lib/react_on_rails/system_checker_spec.rb
📚 Learning: 2025-04-26T21:55:55.874Z
Learnt from: alexeyr-ci2
Repo: shakacode/react_on_rails PR: 1732
File: spec/dummy/client/app-react16/startup/ReduxSharedStoreApp.client.jsx:40-44
Timestamp: 2025-04-26T21:55:55.874Z
Learning: In the react_on_rails project, files under `app-react16` directories are copied/moved to corresponding `/app` directories during the conversion process (removing the `-react16` suffix), which affects their relative import paths at runtime.
Applied to files:
lib/react_on_rails/system_checker.rb
📚 Learning: 2025-02-13T16:50:26.861Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1644
File: node_package/src/turbolinksUtils.ts:34-36
Timestamp: 2025-02-13T16:50:26.861Z
Learning: In React on Rails, when checking for Turbolinks version 5 using `turbolinksVersion5()`, always ensure `Turbolinks` exists first by checking `turbolinksInstalled()` to prevent TypeError when accessing properties.
Applied to files:
lib/react_on_rails/system_checker.rb
📚 Learning: 2025-10-23T17:22:01.074Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1875
File: lib/react_on_rails/utils.rb:112-124
Timestamp: 2025-10-23T17:22:01.074Z
Learning: In React on Rails, when Pro is installed but not licensed, the intended behavior is to raise an error on boot. The `react_on_rails_pro?` method validates licenses and should raise errors early (including during path resolution in methods like `server_bundle?`) to enforce licensing requirements rather than failing later with obscure errors.
Applied to files:
lib/react_on_rails/system_checker.rb
📚 Learning: 2025-02-18T13:08:01.477Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1644
File: lib/react_on_rails/helper.rb:190-197
Timestamp: 2025-02-18T13:08:01.477Z
Learning: RSC support validation in React on Rails Pro is handled through a chain of validations:
1. Pro version check in `run_stream_inside_fiber`
2. RSC support check during pack generation via `ReactOnRailsPro.configuration.enable_rsc_support`
3. RSC support validation during component registration
This makes additional validation in the helper methods unnecessary.
Applied to files:
lib/react_on_rails/system_checker.rb
🧬 Code graph analysis (2)
spec/lib/react_on_rails/system_checker_spec.rb (2)
lib/generators/react_on_rails/generator_messages.rb (1)
messages(21-23)lib/react_on_rails/system_checker.rb (2)
warnings?(36-38)errors?(32-34)
lib/react_on_rails/system_checker.rb (2)
lib/react_on_rails/version_syntax_converter.rb (1)
npm_to_rubygem(14-20)lib/react_on_rails/version_checker.rb (1)
gem_version(203-205)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: dummy-app-integration-tests (3.4, 22, latest)
- GitHub Check: rspec-package-tests (3.4, latest)
- GitHub Check: build
- GitHub Check: claude-review
Code Review - PR #2064: Fix doctor command false version mismatch for beta/prerelease versions✅ Overall AssessmentLGTM with minor suggestions. This is an excellent bug fix that properly addresses the root cause identified in #2063. The solution is clean, well-tested, and leverages existing infrastructure. 🎯 Strengths
🔍 Code Quality Observationslib/react_on_rails/system_checker.rb:216-219Good:
Minor Concern - Performance:
🧪 Test Coverage AnalysisThe test suite in ✅ Happy paths:
✅ Error cases:
✅ Edge cases:
One potential gap: The tests don't explicitly verify that the it "uses VersionSyntaxConverter for version normalization" do
converter = instance_double(ReactOnRails::VersionSyntaxConverter)
allow(ReactOnRails::VersionSyntaxConverter).to receive(:new).and_return(converter)
allow(converter).to receive(:npm_to_rubygem).with("16.2.0-beta.10").and_return("16.2.0.beta.10")
checker.send(:check_package_version_sync)
expect(converter).to have_received(:npm_to_rubygem)
endHowever, this is optional since the integration tests already verify the correct behavior. 🔐 Security Considerations✅ No security concerns identified:
⚡ Performance Considerations✅ Performance impact is negligible:
📋 Suggestions1. Optional: Memoize converter (low priority)If you want to micro-optimize: def version_converter
@version_converter ||= ReactOnRails::VersionSyntaxConverter.new
end
# Then use:
normalized_npm_version = version_converter.npm_to_rubygem(npm_version)But honestly, this is unnecessary given the usage pattern. 2. Consider adding a test comment referencing the bugIn # Regression test for #2063 - Doctor command false version mismatch for beta/prerelease versions
describe "#check_package_version_sync" doThis helps future maintainers understand why these tests exist. 📚 Documentation & Changelog✅ PR description is excellent:
Suggested entry: #### Fixed
- [PR 2064](https://github.com/shakacode/react_on_rails/pull/2064) by [username](https://github.com/username): Fixed `react_on_rails:doctor` command showing false version mismatch warnings for beta/alpha/rc/pre versions. The doctor now correctly compares NPM prerelease versions (e.g., `16.2.0-beta.10`) with gem versions (e.g., `16.2.0.beta.10`).✅ Pre-Merge ChecklistBefore merging, ensure:
🎓 Learning MomentThis PR is a textbook example of how code review feedback (CodeRabbit's comment on #1787) can prevent bugs. The original implementation used an overly aggressive regex that stripped prerelease identifiers along with version prefixes. Key takeaway: When dealing with versioning, always test with prerelease versions (alpha, beta, rc), not just stable versions. Final VerdictApproved with minor changelog addition needed. This is high-quality work that:
Great job! 🚀 Review conducted using project guidelines from CLAUDE.md |
|
thanks @ihabadham |
…se-otp-timing * origin/master: (27 commits) Fix doctor command false version mismatch for beta/prerelease versions (#2064) Fix beta/RC version handling in generator (#2066) Document Rails Engine development nuances and add tests for automatic rake task loading (#2067) Add /run-skipped-tests as alias for /run-skipped-ci (#XXXX) (#2068) Fix: Add Rails 5.2-6.0 compatibility for compact_blank (#2058) Break CI circular dependency with non-docs change (#2065) Fix CI safety check to evaluate latest workflow attempt (#2062) Fix yalc publish (#2054) Add Shakapacker 9.0+ private_output_path integration for server bundles (#2028) Consolidate all beta versions into v16.2.0.beta.10 (#2057) Improve reliability of CI debugging scripts (#2056) Clarify monorepo changelog structure in documentation (#2055) Bump version to 16.2.0.beta.10 Bump version to 16.2.0.beta.9 Fix duplicate rake task execution by removing explicit task loading (#2052) Simplify precompile hook and restore Pro dummy app to async loading (#2053) Add Shakapacker precompile hook with ReScript support to Pro dummy app (#1977) Guard master docs-only pushes and ensure full CI runs (#2042) Refactor: Extract JS dependency management into shared module (#2051) Add workflow to detect invalid CI command attempts (#2037) ... # Conflicts: # rakelib/release.rake
Summary
Fixes #2063 - The doctor command was incorrectly reporting version mismatches for beta/alpha/rc versions even when gem and NPM package versions were identical.
Problem
When running
rake react_on_rails:doctorwith matching prerelease versions:16.2.0.beta.1016.2.0-beta.10The doctor would show a false warning:
Root Cause
The original code from PR #1787 used
gsub(/[^0-9.]/, "")to strip all non-numeric/non-dot characters:"16.2.0-beta.10""16.2.0.10"(both dash AND "beta" removed)"16.2.0.beta.10"(gem version)Note: CodeRabbit caught this bug during the original PR review but the suggestion was not implemented.
Solution
Use the existing
VersionSyntaxConverter.npm_to_rubygemutility which properly handles NPM-to-Ruby version format conversion:^,~,=)-beta) to Ruby gem format (.beta)Changes
File:
lib/react_on_rails/system_checker.rbBefore:
After:
Testing
Verified with test app using both gem and NPM at
16.2.0.beta.10:✅ Matching versions: No false warning
✅ Caret/tilde prefixes: Handled correctly with appropriate warning
✅ Real mismatches: Still detected properly
✅ All prerelease formats: Tested beta, alpha, rc, pre (16/16 scenarios pass)
Benefits
normalized_npm_versionvsclean_npm_version)🤖 Generated with Claude Code
Co-Authored-By: Claude [email protected]
Summary by CodeRabbit
Bug Fixes
Tests
✏️ Tip: You can customize this high-level summary in your review settings.