Skip to content

Conversation

@alexeyr-ci2
Copy link
Collaborator

@alexeyr-ci2 alexeyr-ci2 commented Dec 1, 2025

Summary

Extracted from #1868 because it adds spec/performance/bench.rb and the default Rubocop config doesn't fit our repo.

Pull Request checklist

  • Add/update test to cover these changes
  • Update documentation
  • Update CHANGELOG file

Summary by CodeRabbit

  • Refactor

    • Centralized RuboCop configuration across the monorepo by establishing a shared root configuration file inherited by all projects, ensuring consistent code quality standards.
    • Consolidated development dependencies into a shared file to reduce duplication across projects.
  • Chores

    • Removed inline linting suppressions throughout the codebase for uniform code quality enforcement.
    • Updated test metadata formatting for consistency.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 1, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

This PR centralizes RuboCop and development dependency configuration across the React on Rails monorepo. A root .rubocop.yml file establishes shared linting rules, while individual projects inherit from it. RuboCop pragmas are removed from code files, and rubocop gems are consolidated into a shared Gemfile. Gemfile.loader is refactored to use path-resolved evaluation.

Changes

Cohort / File(s) Change Summary
Root RuboCop Configuration
.rubocop.yml
New comprehensive root RuboCop configuration with AllCops settings, cop-specific rules, metrics thresholds, and string literal enforcement; establishes shared baseline for the monorepo.
Prettier Ignore Updates
.prettierignore, react_on_rails_pro/.prettierignore
Removed .rubocop.yml exception from root .prettierignore; added .rubocop.yml with ERB comment to react_on_rails_pro/.prettierignore.
Project RuboCop Inheritance
react_on_rails/.rubocop.yml, react_on_rails_pro/.rubocop.yml
Both files refactored to inherit from root config with Exclude array merging; removed duplicate local configurations (Layout, Style, Metrics, RSpec cops); retained only project-specific exclusions.
RuboCop Pragma Removals
react_on_rails/lib/generators/react_on_rails/templates/base/base/bin/switch-bundler, react_on_rails/lib/react_on_rails/doctor.rb, react_on_rails/lib/react_on_rails/server_rendering_pool/ruby_embedded_java_script.rb, react_on_rails/lib/react_on_rails/system_checker.rb, react_on_rails/lib/react_on_rails/utils.rb, react_on_rails/lib/react_on_rails/version_checker.rb, react_on_rails_pro/spec/dummy/spec/system/integration_spec.rb
Removed inline RuboCop disable/enable comments for Metrics/CyclomaticComplexity and similar checks; no behavioral changes to methods or control flow.
Shared Development Dependencies
Gemfile.shared_dev_dependencies
New file establishing pinned versions for rubocop, rubocop-performance, and rubocop-rspec gems with frozen_string_literal and require: false.
Gemfile Development Dependencies
react_on_rails/Gemfile.development_dependencies, react_on_rails_pro/Gemfile.development_dependencies
Added eval_gemfile to load shared dependencies; removed explicit RuboCop-related gem declarations (now loaded via shared file).
Gemfile Loader Refactoring
react_on_rails_pro/Gemfile.loader
Refactored to use path-resolved File.read and instance_eval with explicit paths instead of direct eval; added override_gem_names parsing and removal logic from base_deps content.
Spec Configuration and Comments
react_on_rails_pro/spec/dummy/spec/prepare_node_renderer_bundles_spec.rb, react_on_rails_pro/spec/dummy/spec/rails_helper.rb, react_on_rails_pro/spec/dummy/spec/system/integration_spec.rb
Added RuboCop cop to linting comment (RSpec/SpecFilePathFormat); updated before(:each) metadata keys (js: true and rack_test: true to :js and :rack_test); removed inline RuboCop disable comment from example.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

  • Gemfile.loader refactoring: Verify path resolution logic, File.read usage with instance_eval, and override_gem_names parsing and removal behavior are correct and handle edge cases (missing files, empty overrides, nil paths).
  • Inheritance chain validation: Ensure all inherited RuboCop rules are correctly merged and that Exclude arrays combine properly across root and project-level configs.
  • Development dependency consistency: Confirm that moving RuboCop gems to shared_dev_dependencies doesn't break gem resolution or version pinning in both projects.

Possibly related PRs

Suggested labels

full-ci

Poem

A bundler's dance, now clean and bright,
RuboCop rules consolidated right,
Pragmas vanish, configs aligned,
Shared dependencies in one place we find,
Hop along, the linting path is fine! 🐰✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Unify Rubocop config' directly and clearly summarizes the main change: consolidating RuboCop configuration across the monorepo by creating a root .rubocop.yml and having child projects inherit from it.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch alexeyr/rubocop-config

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@claude
Copy link

claude bot commented Dec 1, 2025

Code Review: Unify RuboCop Config

Summary

This PR successfully consolidates the RuboCop configuration by extracting common settings to a root .rubocop.yml file, with react_on_rails/ and react_on_rails_pro/ inheriting via inherit_from. This is excellent DRY practice and eliminates configuration drift between the two packages.

Strengths

  1. Proper DRY Architecture: Moving shared settings to root and using inherit_from is the correct approach for a monorepo
  2. Good Exclusion Cleanup: Removed redundant exclusions from child configs that are already in root
  3. Prettier Protection: Correctly added .rubocop.yml to react_on_rails_pro/.prettierignore since it contains ERB
  4. Preserved Customizations: Package-specific overrides are correctly kept in child configs

Issues and Concerns

1. ERB in RuboCop Config - Potential Compatibility Issue

The react_on_rails_pro/.rubocop.yml file contains ERB template code that dynamically generates exclusion patterns from git-ignored files. RuboCops ERB support is not guaranteed across all versions and executes shell commands during config parsing, which could be slow or error-prone.

Recommendation: Consider using static exclusion patterns instead, or document why ERB is necessary and test with minimum supported RuboCop version.

2. Missing Root TargetRubyVersion Validation

The root config sets TargetRubyVersion: 3.0. Please verify this matches the gemspecs required_ruby_version and the minimum CI configuration.

3. Configuration Path Testing

Per CLAUDE.md guidance on Managing File Paths, configuration changes should be tested from all locations to ensure inheritance works correctly.

Testing Checklist

Before merging, please confirm:

  • bundle exec rubocop passes from repo root
  • cd react_on_rails && bundle exec rubocop passes
  • cd react_on_rails_pro && bundle exec rubocop passes
  • ERB in Pro config parses correctly
  • Pre-commit hooks still work
  • CI passes

Overall Assessment

Verdict: Approve with minor concerns

This is a solid refactoring that improves maintainability. The ERB concern is the main issue to address. Once verified that ERB works reliably and the testing checklist is complete, this is good to merge.

- 'lib/generators/react_on_rails/install_generator.rb' # Generator setup methods require comprehensive error handling

Metrics/CyclomaticComplexity:
Max: 7
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This remains here because it doesn't match exactly with RORP

Metrics/CyclomaticComplexity:
Max: 8
but I could just pick the greater limit in cases like that (also Metrics/ClassLength 150 here vs. 140 in RORP etc.)

@alexeyr-ci2 alexeyr-ci2 force-pushed the alexeyr/rubocop-config branch from 0812423 to b7cfbb2 Compare December 1, 2025 16:01
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
react_on_rails_pro/.rubocop.yml (1)

6-8: ERB-based dynamic git exclusions are clever but performance-sensitive; consider CI/CD implications.

RuboCop processes .rubocop.yml as ERB before YAML parsing, allowing arbitrary Ruby code embedding. Lines 6-8 execute git status --ignored --porcelain on each RuboCop invocation to exclude git-ignored files dynamically.

Pros:

  • Automatically respects .gitignore without manual maintenance

Cons:

  • Runs a shell command on every RuboCop check (performance impact, especially in large repos)
  • May fail in non-git environments or shallow clones
  • Could behave unexpectedly in CI/CD if git state differs from local

Consider adding error handling or an environment variable escape hatch if git state is unavailable.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0812423 and b7cfbb2.

📒 Files selected for processing (5)
  • .prettierignore (0 hunks)
  • .rubocop.yml (1 hunks)
  • react_on_rails/.rubocop.yml (1 hunks)
  • react_on_rails_pro/.prettierignore (1 hunks)
  • react_on_rails_pro/.rubocop.yml (1 hunks)
💤 Files with no reviewable changes (1)
  • .prettierignore
🚧 Files skipped from review as they are similar to previous changes (2)
  • react_on_rails_pro/.prettierignore
  • .rubocop.yml
🧰 Additional context used
🧠 Learnings (17)
📓 Common learnings
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: Applies to **/*.{rb,rake} : ALWAYS run `bundle exec rubocop` and fix ALL violations before every commit/push
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: The `react_on_rails_pro/` directory has its own Prettier/ESLint configuration and must be linted separately
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: ALWAYS let Prettier and RuboCop handle ALL formatting - never manually format
📚 Learning: 2025-11-25T08:05:17.804Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: The `react_on_rails_pro/` directory has its own Prettier/ESLint configuration and must be linted separately

Applied to files:

  • react_on_rails_pro/.rubocop.yml
  • react_on_rails/.rubocop.yml
📚 Learning: 2025-11-25T08:05:17.804Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: Applies to **/*.{rb,rake} : ALWAYS run `bundle exec rubocop` and fix ALL violations before every commit/push

Applied to files:

  • react_on_rails_pro/.rubocop.yml
  • react_on_rails/.rubocop.yml
📚 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:

  • react_on_rails_pro/.rubocop.yml
  • react_on_rails/.rubocop.yml
📚 Learning: 2025-09-16T08:01:11.146Z
Learnt from: justin808
Repo: shakacode/react_on_rails PR: 1770
File: lib/generators/react_on_rails/templates/base/base/app/javascript/src/HelloWorld/ror_components/HelloWorld.client.jsx:2-2
Timestamp: 2025-09-16T08:01:11.146Z
Learning: React on Rails uses webpack CSS Modules configuration with namedExports: true, which requires the import syntax `import * as style from './file.module.css'` rather than the default export pattern. This configuration enables better tree shaking and bundle size optimization for CSS modules.

Applied to files:

  • react_on_rails_pro/.rubocop.yml
  • react_on_rails/.rubocop.yml
📚 Learning: 2025-11-25T08:05:17.804Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: Applies to /CHANGELOG.md : Update `/CHANGELOG.md` for user-visible changes (features, bug fixes, breaking changes, deprecations, performance improvements) to the open-source React on Rails gem and npm package

Applied to files:

  • react_on_rails_pro/.rubocop.yml
  • react_on_rails/.rubocop.yml
📚 Learning: 2025-11-25T08:05:17.804Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: Applies to lib/react_on_rails/*.rb : Create RBS signature files for new Ruby files in `lib/react_on_rails/` by adding corresponding `.rbs` file in `sig/react_on_rails/`, adding to Steepfile, and validating before committing

Applied to files:

  • react_on_rails_pro/.rubocop.yml
  • react_on_rails/.rubocop.yml
📚 Learning: 2025-11-25T08:05:17.804Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: Applies to sig/react_on_rails/**/*.rbs : In RBS type signature files, define type signatures that correspond to Ruby files in `lib/react_on_rails/`

Applied to files:

  • react_on_rails_pro/.rubocop.yml
  • react_on_rails/.rubocop.yml
📚 Learning: 2025-02-12T16:38:06.537Z
Learnt from: Romex91
Repo: shakacode/react_on_rails PR: 1697
File: package-scripts.yml:28-28
Timestamp: 2025-02-12T16:38:06.537Z
Learning: The file `node_package/lib/ReactOnRails.full.js` is autogenerated during the build process and should not be present in the repository.

Applied to files:

  • react_on_rails_pro/.rubocop.yml
  • react_on_rails/.rubocop.yml
📚 Learning: 2025-11-25T08:05:17.804Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: Exclude `/coverage`, `/tmp`, `/gen-examples`, `/packages/react-on-rails/lib`, `/node_modules`, `/spec/dummy/node_modules`, `/spec/dummy/tmp`, `/spec/dummy/app/assets/webpack`, `/spec/dummy/log`, `/spec/dummy/e2e/playwright-report`, `/spec/dummy/test-results` from IDE indexing

Applied to files:

  • react_on_rails_pro/.rubocop.yml
  • react_on_rails/.rubocop.yml
📚 Learning: 2025-11-25T08:05:17.804Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: ALWAYS let Prettier and RuboCop handle ALL formatting - never manually format

Applied to files:

  • react_on_rails_pro/.rubocop.yml
  • react_on_rails/.rubocop.yml
📚 Learning: 2025-11-25T08:05:17.804Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: Applies to spec/dummy/e2e/playwright/**/*.spec.js : Use Rails helpers (`appFactories`, `appEval`) in Playwright tests instead of UI-based setup to leverage factory_bot and arbitrary Ruby code execution

Applied to files:

  • react_on_rails_pro/.rubocop.yml
  • react_on_rails/.rubocop.yml
📚 Learning: 2025-02-13T14:29:49.267Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1644
File: spec/react_on_rails/utils_spec.rb:218-218
Timestamp: 2025-02-13T14:29:49.267Z
Learning: In RSpec tests, prefer using local variables over constants within test blocks to avoid constant redefinition warnings and maintain better test isolation.

Applied to files:

  • react_on_rails_pro/.rubocop.yml
  • react_on_rails/.rubocop.yml
📚 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 is handled in deeper level calls of the React on Rails Pro codebase, so it doesn't need to be validated again in the `rsc_payload_react_component` helper method.

Applied to files:

  • react_on_rails/.rubocop.yml
📚 Learning: 2025-11-25T08:05:17.804Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: Runtime type checking via RBS is enabled by default in test runs; disable with `DISABLE_RBS_RUNTIME_CHECKING=true` only for rapid development iterations

Applied to files:

  • react_on_rails/.rubocop.yml
📚 Learning: 2025-11-25T08:05:17.804Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: Applies to lib/tasks/*.rake : Rails::Engine rake tasks should NOT be explicitly loaded via `rake_tasks` block; instead, place them in `lib/tasks/*.rake` where Rails::Engine automatically loads them

Applied to files:

  • react_on_rails/.rubocop.yml
📚 Learning: 2024-10-08T20:53:47.076Z
Learnt from: justin808
Repo: shakacode/react_on_rails PR: 1622
File: spec/dummy/spec/rake/assets_precompile_rake_spec.rb:12-12
Timestamp: 2024-10-08T20:53:47.076Z
Learning: When stubbing environment variables in RSpec tests, use `before` and `after` hooks to ensure that the original values are restored after the tests, preventing any side effects on other tests. Example provided by justin808:
```ruby
describe "My test" do
  before do
    original_value = ENV["VARIABLE_NAME"]
    allow(ENV).to receive(:[]).with("VARIABLE_NAME").and_return("stubbed_value")
  end

  after do
    allow(ENV).to receive(:[]).with("VARIABLE_NAME").and_call_original
    ENV["VARIABLE_NAME"] = original_value
  end

  it "tests something" do
    # Your test code here
  end
end
```
This practice ensures test isolation and reliability.

Applied to files:

  • react_on_rails/.rubocop.yml
⏰ 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). (7)
  • GitHub Check: examples (3.4, latest)
  • GitHub Check: rspec-package-tests (3.4, latest)
  • GitHub Check: build-dummy-app-webpack-test-bundles
  • GitHub Check: build-dummy-app-webpack-test-bundles
  • GitHub Check: pro-lint-js-and-ruby
  • GitHub Check: build
  • GitHub Check: claude-review
🔇 Additional comments (2)
react_on_rails_pro/.rubocop.yml (1)

1-2: Root config inheritance established; verify same root file is properly configured.

This file now inherits from the same root config via ../. rubocop.yml. Same verification needed as react_on_rails/.rubocop.yml:

  1. Root config exists and contains all necessary cop definitions
  2. Root config appropriately handles the pro package's stricter or looser limits (e.g., Metrics/ClassLength: Max: 140 here vs. 150 in the open-source package)
  3. Performance benchmark file handling is configured
react_on_rails/.rubocop.yml (1)

1-2: Root RuboCop configuration is correctly set up and inheritance is working as expected.

The root .rubocop.yml exists at the repository root and properly defines all necessary cop configurations including Layout/LineLength (Max: 120), Style/StringLiterals, and others. The relative path ../.rubocop.yml in react_on_rails/.rubocop.yml correctly resolves to the root config. The spec/performance/bench.rb file will be included in RuboCop checks via the **/*.rb include pattern in the root config's AllCops section, so no additional configuration is needed.

@claude
Copy link

claude bot commented Dec 1, 2025

Code Review

Summary

This PR successfully unifies RuboCop configuration across the monorepo by creating a root-level config that both react_on_rails/ and react_on_rails_pro/ inherit from. This is a good refactoring that reduces duplication and ensures consistency.

✅ Strengths

  1. DRY Principle Applied: Consolidating shared RuboCop rules into a root config eliminates ~150 lines of duplicate configuration
  2. Proper Inheritance: Both sub-packages correctly use inherit_from: ../.rubocop.yml to extend the base config
  3. Prettier Ignore Handling: Smart handling of ERB in Pro's .rubocop.yml by keeping it in .prettierignore while removing the blanket exclusion at root
  4. Maintained Flexibility: Sub-packages can still override rules as needed (e.g., Metrics/CyclomaticComplexity differs between packages)

🔍 Issues Found

1. Inconsistent AllCops Setting (Minor)

Location: react_on_rails_pro/.rubocop.yml:5

AllCops:
  EnableNewCops: true  # Note: "Enable" not "New"

The root config uses NewCops: enable but Pro uses EnableNewCops: true. While RuboCop may accept both, this inconsistency could cause confusion.

Recommendation: Use NewCops: enable everywhere for consistency, or verify this wasn't intentional.

2. Missing Exclusion Pattern (Potential Bug)

Location: Root .rubocop.yml:26

The root config excludes gen-examples/**/* but the old react_on_rails/.rubocop.yml excluded gen-examples/examples/**/* (more specific).

Question: Does gen-examples/ contain files outside of examples/ that should be linted? If so, the new pattern is more correct. If not, the old pattern was more precise.

3. TargetRubyVersion Precision

Location: Root .rubocop.yml:11

TargetRubyVersion: 3.0

The old react_on_rails/.rubocop.yml had 3.0.0 (patch version specified). While both work, double-check this matches your actual minimum supported Ruby version per CLAUDE.md (which mentions 3.0 as the minimum).

📋 Testing Recommendations

Per CLAUDE.md's requirements, before merging:

  1. Run RuboCop on both packages:

    bundle exec rubocop
    cd react_on_rails_pro && bundle exec rubocop
  2. Verify no new offenses were introduced by the config changes

  3. Test the ERB in Pro's config still works:

    cd react_on_rails_pro
    git status --ignored --porcelain | grep '^\!\! ' # Should output ignored files
    bundle exec rubocop --debug # Should process exclusions correctly
  4. Verify Prettier respects the new ignore rules:

    pnpm run format.listDifferent

💡 Suggestions for Future

  1. Document the ERB usage: Consider adding a comment in react_on_rails_pro/.rubocop.yml explaining why ERB is used (to dynamically exclude git-ignored files)

  2. Consolidate Prettier ignores: The Pro package now has a specific .prettierignore for .rubocop.yml, but the root already excludes all *.yml. This works but creates a dependency on order of operations.

🎯 Verdict

Approve with minor recommendations. The refactoring is sound and follows the monorepo structure correctly. The inconsistencies noted are minor and could be addressed in a follow-up if needed. The CI checks passing will confirm no regressions were introduced.

Great work on reducing configuration duplication! 🚀

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
react_on_rails_pro/.rubocop.yml (1)

7-9: Consider adding error handling or static fallback for the git-based ERB exclusions.

The ERB pattern dynamically excludes git-ignored files, which is a valid and officially supported RuboCop feature. However, if the git status command fails (e.g., in shallow clones without git history, or CI environments without git), the entire RuboCop config fails to load with no graceful fallback. While this is unlikely in typical development or your current CI setup (GitHub Actions provides git), defensive coding would suggest either:

  • Wrapping the backtick command with error handling: <% \git status --ignored --porcelain 2>/dev/null`.lines.grep(/^!! /).each do |path| %>`
  • Or providing a static fallback list for environments where git is unavailable

The performance impact is minimal (git runs once per RuboCop invocation, not per file).

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b7cfbb2 and c029e91.

📒 Files selected for processing (1)
  • react_on_rails_pro/.rubocop.yml (1 hunks)
🧰 Additional context used
🧠 Learnings (14)
📓 Common learnings
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: Applies to **/*.{rb,rake} : ALWAYS run `bundle exec rubocop` and fix ALL violations before every commit/push
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: The `react_on_rails_pro/` directory has its own Prettier/ESLint configuration and must be linted separately
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: ALWAYS let Prettier and RuboCop handle ALL formatting - never manually format
📚 Learning: 2025-11-25T08:05:17.804Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: The `react_on_rails_pro/` directory has its own Prettier/ESLint configuration and must be linted separately

Applied to files:

  • react_on_rails_pro/.rubocop.yml
📚 Learning: 2025-11-25T08:05:17.804Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: Applies to **/*.{rb,rake} : ALWAYS run `bundle exec rubocop` and fix ALL violations before every commit/push

Applied to files:

  • react_on_rails_pro/.rubocop.yml
📚 Learning: 2025-09-16T08:01:11.146Z
Learnt from: justin808
Repo: shakacode/react_on_rails PR: 1770
File: lib/generators/react_on_rails/templates/base/base/app/javascript/src/HelloWorld/ror_components/HelloWorld.client.jsx:2-2
Timestamp: 2025-09-16T08:01:11.146Z
Learning: React on Rails uses webpack CSS Modules configuration with namedExports: true, which requires the import syntax `import * as style from './file.module.css'` rather than the default export pattern. This configuration enables better tree shaking and bundle size optimization for CSS modules.

Applied to files:

  • react_on_rails_pro/.rubocop.yml
📚 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:

  • react_on_rails_pro/.rubocop.yml
📚 Learning: 2025-11-25T08:05:17.804Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: Applies to lib/react_on_rails/*.rb : Create RBS signature files for new Ruby files in `lib/react_on_rails/` by adding corresponding `.rbs` file in `sig/react_on_rails/`, adding to Steepfile, and validating before committing

Applied to files:

  • react_on_rails_pro/.rubocop.yml
📚 Learning: 2025-11-25T08:05:17.804Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: Applies to /CHANGELOG.md : Update `/CHANGELOG.md` for user-visible changes (features, bug fixes, breaking changes, deprecations, performance improvements) to the open-source React on Rails gem and npm package

Applied to files:

  • react_on_rails_pro/.rubocop.yml
📚 Learning: 2025-11-25T08:05:17.804Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: Applies to sig/react_on_rails/**/*.rbs : In RBS type signature files, define type signatures that correspond to Ruby files in `lib/react_on_rails/`

Applied to files:

  • react_on_rails_pro/.rubocop.yml
📚 Learning: 2025-02-12T16:38:06.537Z
Learnt from: Romex91
Repo: shakacode/react_on_rails PR: 1697
File: package-scripts.yml:28-28
Timestamp: 2025-02-12T16:38:06.537Z
Learning: The file `node_package/lib/ReactOnRails.full.js` is autogenerated during the build process and should not be present in the repository.

Applied to files:

  • react_on_rails_pro/.rubocop.yml
📚 Learning: 2025-11-25T08:05:17.804Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: ALWAYS let Prettier and RuboCop handle ALL formatting - never manually format

Applied to files:

  • react_on_rails_pro/.rubocop.yml
📚 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:

  • react_on_rails_pro/.rubocop.yml
📚 Learning: 2025-11-25T08:05:17.804Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: Applies to spec/dummy/e2e/playwright/**/*.spec.js : Use Rails helpers (`appFactories`, `appEval`) in Playwright tests instead of UI-based setup to leverage factory_bot and arbitrary Ruby code execution

Applied to files:

  • react_on_rails_pro/.rubocop.yml
📚 Learning: 2025-02-13T14:29:49.267Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1644
File: spec/react_on_rails/utils_spec.rb:218-218
Timestamp: 2025-02-13T14:29:49.267Z
Learning: In RSpec tests, prefer using local variables over constants within test blocks to avoid constant redefinition warnings and maintain better test isolation.

Applied to files:

  • react_on_rails_pro/.rubocop.yml
📚 Learning: 2025-11-25T08:05:17.804Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: Exclude `/coverage`, `/tmp`, `/gen-examples`, `/packages/react-on-rails/lib`, `/node_modules`, `/spec/dummy/node_modules`, `/spec/dummy/tmp`, `/spec/dummy/app/assets/webpack`, `/spec/dummy/log`, `/spec/dummy/e2e/playwright-report`, `/spec/dummy/test-results` from IDE indexing

Applied to files:

  • react_on_rails_pro/.rubocop.yml
⏰ 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). (8)
  • GitHub Check: examples (3.4, latest)
  • GitHub Check: build-dummy-app-webpack-test-bundles
  • GitHub Check: rspec-package-tests (3.4, latest)
  • GitHub Check: build-dummy-app-webpack-test-bundles (3.4, 22, latest)
  • GitHub Check: pro-lint-js-and-ruby
  • GitHub Check: build
  • GitHub Check: build-dummy-app-webpack-test-bundles
  • GitHub Check: claude-review
🔇 Additional comments (3)
react_on_rails_pro/.rubocop.yml (3)

5-5: Good practice: EnableNewCops: true aligns with staying current.

This setting ensures new cops introduced in future RuboCop versions are enabled by default, supporting consistent linting standards.


16-42: No duplication or conflicts detected—local configuration properly extends root config.

The local cop configurations in react_on_rails_pro/.rubocop.yml correctly inherit from the root config via inherit_from: ../.rubocop.yml. The local settings (Metrics/CyclomaticComplexity, Metrics/ClassLength, RSpec/NestedGroups, RSpec/BeforeAfterAll, RSpec/MultipleDescribes, Style/GlobalVars) are unique to this subdirectory and do not duplicate any root-level configurations. The root config defines different Metrics rules (AbcSize, PerceivedComplexity, ParameterLists, MethodLength, ModuleLength) and RSpec rules without these specific exclusions, so the local overrides and exclusion lists are intentional and conflict-free.


1-2: Root .rubocop.yml exists and is properly configured. The inheritance in react_on_rails_pro/.rubocop.yml is correctly set up with inherit_from: ../.rubocop.yml. The root config includes standard exclusions that adequately cover project artifacts. No configuration issues detected.

Note: spec/performance/bench.rb does not currently exist in the repository, so the stated PR objective cannot be verified against the actual codebase state.

@alexeyr-ci2 alexeyr-ci2 force-pushed the alexeyr/rubocop-config branch from c029e91 to 5ff29fb Compare December 1, 2025 18:30
@coderabbitai coderabbitai bot added the full-ci label Dec 1, 2025
@claude
Copy link

claude bot commented Dec 1, 2025

Code Review - RuboCop Config Unification

Thank you for unifying the RuboCop configuration! This is a valuable cleanup that reduces duplication.

✅ Strengths

  1. Good consolidation: Moving shared configuration to root level reduces duplication
  2. Proper inheritance: Both packages now use inherit_from correctly
  3. Preserved package-specific overrides: Package-specific exceptions are maintained
  4. Prettier config updated appropriately: Removed .rubocop.yml from root .prettierignore, kept it in Pro package

⚠️ Issues & Concerns

1. Configuration Inconsistency: NewCops vs EnableNewCops

Root config uses NewCops: enable (line 8) but react_on_rails_pro/.rubocop.yml overrides with EnableNewCops: true (line 5). These are different settings - NewCops is modern, EnableNewCops is legacy. Remove EnableNewCops from Pro config since it is redundant.

2. Missing Gem Requirement

rubocop-rails-omakase was added to Gemfile but not required in .rubocop.yml. Either add it to require: section if using its cops, or remove from Gemfile if not needed yet.

3. ERB Template in Pro Config

Pro .rubocop.yml uses ERB to run git status dynamically. This makes linting non-deterministic and could be slow. Consider replacing with explicit exclusion patterns.

4. CyclomaticComplexity Relaxed

Root config sets Max: 8 but old react_on_rails config had Max: 7 (stricter). This relaxes the limit from 7 to 8. Is this intentional?

5. RSpec/NestedGroups Relaxed

Root config sets Max: 5 but old react_on_rails config had Max: 4 (stricter). This allows deeper nesting. Is this intentional?

6. Metrics/ClassLength Change

Root uses Max: 150, Pro had Max: 140 before. Pro now allows slightly longer classes.

Testing Checklist

  • Run bundle exec rubocop from root and each package
  • Check for new violations from relaxed limits
  • Verify inheritance works correctly
  • Test with fresh bundle

Overall Assessment

This is a good refactoring. Main concerns:

  1. Configuration value inconsistencies may indicate unintended changes
  2. Unclear purpose of rubocop-rails-omakase dependency
  3. Dynamic ERB-based exclusions in Pro package

Recommendation: Address inconsistencies, verify no new violations, and document intentional policy changes.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
react_on_rails/.rubocop.yml (1)

1-80: File must end with a newline character.

The file is missing a trailing newline after line 80, which violates the coding guideline.

As per coding guidelines, add a newline at the end of the file:

 RSpec/StubbedMock:
   Exclude:
     - 'spec/react_on_rails/dev/**/*_spec.rb'  # Dev module tests use mixed stub/mock patterns
+
react_on_rails_pro/.rubocop.yml (1)

1-33: File must end with a newline character.

The file is missing a trailing newline after line 33, which violates the coding guideline.

As per coding guidelines, add a newline at the end of the file:

 Style/GlobalVars:
   Exclude:
     - 'spec/dummy/config/environments/development.rb'
+
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c029e91 and 5ff29fb.

⛔ Files ignored due to path filters (1)
  • react_on_rails/Gemfile.lock is excluded by !**/*.lock
📒 Files selected for processing (6)
  • .prettierignore (0 hunks)
  • .rubocop.yml (1 hunks)
  • react_on_rails/.rubocop.yml (1 hunks)
  • react_on_rails/Gemfile.development_dependencies (1 hunks)
  • react_on_rails_pro/.prettierignore (1 hunks)
  • react_on_rails_pro/.rubocop.yml (1 hunks)
💤 Files with no reviewable changes (1)
  • .prettierignore
🚧 Files skipped from review as they are similar to previous changes (1)
  • react_on_rails_pro/.prettierignore
🧰 Additional context used
📓 Path-based instructions (1)
**/*

📄 CodeRabbit inference engine (CLAUDE.md)

ALWAYS ensure files end with a newline character before committing/pushing

Files:

  • react_on_rails/Gemfile.development_dependencies
🧠 Learnings (18)
📓 Common learnings
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: Applies to **/*.{rb,rake} : ALWAYS run `bundle exec rubocop` and fix ALL violations before every commit/push
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: The `react_on_rails_pro/` directory has its own Prettier/ESLint configuration and must be linted separately
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: Applies to lib/react_on_rails/*.rb : Create RBS signature files for new Ruby files in `lib/react_on_rails/` by adding corresponding `.rbs` file in `sig/react_on_rails/`, adding to Steepfile, and validating before committing
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: ALWAYS let Prettier and RuboCop handle ALL formatting - never manually format
📚 Learning: 2025-11-25T08:05:17.804Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: Applies to /CHANGELOG.md : Update `/CHANGELOG.md` for user-visible changes (features, bug fixes, breaking changes, deprecations, performance improvements) to the open-source React on Rails gem and npm package

Applied to files:

  • react_on_rails/Gemfile.development_dependencies
  • react_on_rails/.rubocop.yml
  • react_on_rails_pro/.rubocop.yml
📚 Learning: 2025-11-25T08:05:17.804Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: Applies to lib/react_on_rails/*.rb : Create RBS signature files for new Ruby files in `lib/react_on_rails/` by adding corresponding `.rbs` file in `sig/react_on_rails/`, adding to Steepfile, and validating before committing

Applied to files:

  • react_on_rails/Gemfile.development_dependencies
  • react_on_rails/.rubocop.yml
  • react_on_rails_pro/.rubocop.yml
  • .rubocop.yml
📚 Learning: 2025-02-12T16:38:06.537Z
Learnt from: Romex91
Repo: shakacode/react_on_rails PR: 1697
File: package-scripts.yml:28-28
Timestamp: 2025-02-12T16:38:06.537Z
Learning: The file `node_package/lib/ReactOnRails.full.js` is autogenerated during the build process and should not be present in the repository.

Applied to files:

  • react_on_rails/Gemfile.development_dependencies
  • react_on_rails/.rubocop.yml
  • react_on_rails_pro/.rubocop.yml
📚 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:

  • react_on_rails/Gemfile.development_dependencies
  • react_on_rails/.rubocop.yml
  • react_on_rails_pro/.rubocop.yml
📚 Learning: 2025-11-25T08:05:17.804Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: Applies to sig/react_on_rails/**/*.rbs : In RBS type signature files, define type signatures that correspond to Ruby files in `lib/react_on_rails/`

Applied to files:

  • react_on_rails/Gemfile.development_dependencies
  • react_on_rails/.rubocop.yml
  • react_on_rails_pro/.rubocop.yml
  • .rubocop.yml
📚 Learning: 2025-09-16T08:01:11.146Z
Learnt from: justin808
Repo: shakacode/react_on_rails PR: 1770
File: lib/generators/react_on_rails/templates/base/base/app/javascript/src/HelloWorld/ror_components/HelloWorld.client.jsx:2-2
Timestamp: 2025-09-16T08:01:11.146Z
Learning: React on Rails uses webpack CSS Modules configuration with namedExports: true, which requires the import syntax `import * as style from './file.module.css'` rather than the default export pattern. This configuration enables better tree shaking and bundle size optimization for CSS modules.

Applied to files:

  • react_on_rails/Gemfile.development_dependencies
  • react_on_rails/.rubocop.yml
  • react_on_rails_pro/.rubocop.yml
  • .rubocop.yml
📚 Learning: 2025-11-25T08:05:17.804Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: The `react_on_rails_pro/` directory has its own Prettier/ESLint configuration and must be linted separately

Applied to files:

  • react_on_rails/Gemfile.development_dependencies
  • react_on_rails/.rubocop.yml
  • react_on_rails_pro/.rubocop.yml
  • .rubocop.yml
📚 Learning: 2025-11-25T08:05:17.804Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: Applies to **/*.{rb,rake} : ALWAYS run `bundle exec rubocop` and fix ALL violations before every commit/push

Applied to files:

  • react_on_rails/Gemfile.development_dependencies
  • react_on_rails/.rubocop.yml
  • react_on_rails_pro/.rubocop.yml
  • .rubocop.yml
📚 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 is handled in deeper level calls of the React on Rails Pro codebase, so it doesn't need to be validated again in the `rsc_payload_react_component` helper method.

Applied to files:

  • react_on_rails/.rubocop.yml
📚 Learning: 2025-11-25T08:05:17.804Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: ALWAYS let Prettier and RuboCop handle ALL formatting - never manually format

Applied to files:

  • react_on_rails/.rubocop.yml
  • react_on_rails_pro/.rubocop.yml
  • .rubocop.yml
📚 Learning: 2025-11-25T08:05:17.804Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: Exclude `/coverage`, `/tmp`, `/gen-examples`, `/packages/react-on-rails/lib`, `/node_modules`, `/spec/dummy/node_modules`, `/spec/dummy/tmp`, `/spec/dummy/app/assets/webpack`, `/spec/dummy/log`, `/spec/dummy/e2e/playwright-report`, `/spec/dummy/test-results` from IDE indexing

Applied to files:

  • react_on_rails/.rubocop.yml
  • .rubocop.yml
📚 Learning: 2025-11-25T08:05:17.804Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: Applies to spec/dummy/e2e/playwright/**/*.spec.js : Use Rails helpers (`appFactories`, `appEval`) in Playwright tests instead of UI-based setup to leverage factory_bot and arbitrary Ruby code execution

Applied to files:

  • react_on_rails/.rubocop.yml
📚 Learning: 2025-02-13T14:29:49.267Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1644
File: spec/react_on_rails/utils_spec.rb:218-218
Timestamp: 2025-02-13T14:29:49.267Z
Learning: In RSpec tests, prefer using local variables over constants within test blocks to avoid constant redefinition warnings and maintain better test isolation.

Applied to files:

  • react_on_rails/.rubocop.yml
  • react_on_rails_pro/.rubocop.yml
📚 Learning: 2025-11-25T08:05:17.804Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: Runtime type checking via RBS is enabled by default in test runs; disable with `DISABLE_RBS_RUNTIME_CHECKING=true` only for rapid development iterations

Applied to files:

  • react_on_rails/.rubocop.yml
📚 Learning: 2025-11-25T08:05:17.804Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: Applies to lib/tasks/*.rake : Rails::Engine rake tasks should NOT be explicitly loaded via `rake_tasks` block; instead, place them in `lib/tasks/*.rake` where Rails::Engine automatically loads them

Applied to files:

  • react_on_rails/.rubocop.yml
📚 Learning: 2024-10-08T20:53:47.076Z
Learnt from: justin808
Repo: shakacode/react_on_rails PR: 1622
File: spec/dummy/spec/rake/assets_precompile_rake_spec.rb:12-12
Timestamp: 2024-10-08T20:53:47.076Z
Learning: When stubbing environment variables in RSpec tests, use `before` and `after` hooks to ensure that the original values are restored after the tests, preventing any side effects on other tests. Example provided by justin808:
```ruby
describe "My test" do
  before do
    original_value = ENV["VARIABLE_NAME"]
    allow(ENV).to receive(:[]).with("VARIABLE_NAME").and_return("stubbed_value")
  end

  after do
    allow(ENV).to receive(:[]).with("VARIABLE_NAME").and_call_original
    ENV["VARIABLE_NAME"] = original_value
  end

  it "tests something" do
    # Your test code here
  end
end
```
This practice ensures test isolation and reliability.

Applied to files:

  • react_on_rails/.rubocop.yml
📚 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:

  • react_on_rails_pro/.rubocop.yml
⏰ 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). (8)
  • GitHub Check: rspec-package-tests (3.4, latest)
  • GitHub Check: build-dummy-app-webpack-test-bundles (3.4, 22, latest)
  • GitHub Check: examples (3.4, latest)
  • GitHub Check: build-dummy-app-webpack-test-bundles
  • GitHub Check: build
  • GitHub Check: build-dummy-app-webpack-test-bundles
  • GitHub Check: pro-lint-js-and-ruby
  • GitHub Check: claude-review
🔇 Additional comments (3)
.rubocop.yml (1)

1-99: Root configuration structure looks solid.

The shared RuboCop configuration provides a good baseline with reasonable cop settings, metrics thresholds, and RSpec configurations that both packages can inherit from.

react_on_rails/.rubocop.yml (1)

1-2: Good consolidation via inheritance.

Switching to inherit from the root configuration is a clean approach that reduces duplication while maintaining package-specific exceptions where needed.

react_on_rails_pro/.rubocop.yml (1)

1-2: Inheritance approach reduces duplication effectively.

Inheriting from the root config while maintaining only pro-specific exclusions is a clean consolidation.

@claude
Copy link

claude bot commented Dec 4, 2025

Code Review for PR #2153: Unify Rubocop config

Overview

This PR successfully centralizes RuboCop configuration using inheritance, reducing duplication across the monorepo.

✅ Strengths

  1. Excellent DRY principle - eliminates ~80 lines of duplication
  2. Proper inheritance structure using inherit_from
  3. Smart Prettier handling - root config can be formatted, Pro config kept in ignore
  4. Minimal disruption to existing rules

⚠️ Issues

1. CRITICAL: rubocop-rails-omakase dependency

Added to Gemfile but not required in root .rubocop.yml. Is this used or future prep? Please clarify.

2. Pro config: EnableNewCops vs NewCops

Line 5 of react_on_rails_pro/.rubocop.yml has EnableNewCops: true which is not a valid RuboCop setting. Should be NewCops: enable or removed since it inherits from root.

3. Pro config: ERB complexity

Dynamic git status exclusions add complexity. Consider static list unless truly necessary.

4. Minor: Stricter open-source metrics

Open-source has Max: 7 for CyclomaticComplexity vs root's 8, and Max: 4 for NestedGroups vs root's 5. If intentional, consider adding comment explaining why.

Testing Recommendations

  • bundle exec rubocop from root
  • Test from both subpackages
  • Verify pnpm run format.listDifferent handles Pro config correctly

Overall: Strong refactoring with minor issues to address. Main concern is the invalid EnableNewCops config key.

The correct RuboCop syntax is 'NewCops: enable' under AllCops, which is
already defined in the root .rubocop.yml that this config inherits from.
'EnableNewCops: true' is not a valid RuboCop configuration key and will
be silently ignored.

Co-authored-by: Ihab Adham <ihabadham@users.noreply.github.com>
@claude
Copy link

claude bot commented Dec 4, 2025

Code Review - PR #2153: Unify Rubocop Config

Summary

This PR centralizes RuboCop configuration by creating a root-level .rubocop.yml that is inherited by both react_on_rails/ and react_on_rails_pro/ packages. This is a well-executed refactoring that reduces duplication and improves maintainability.

Strengths

  1. DRY Principle Applied Successfully - Moved 99 shared config lines to root, eliminating duplication. Reduced react_on_rails/.rubocop.yml from 159 to 81 lines and react_on_rails_pro/.rubocop.yml from 113 to 33 lines. Total reduction: ~172 lines.

  2. Proper Inheritance Structure - Both packages correctly use inherit_from and package-specific overrides remain local with clear justification comments.

  3. Prettier Configuration Cleanup - Root .prettierignore correctly removed .rubocop.yml (no ERB), while Pro package added it to local .prettierignore (uses ERB templating). This distinction is intentional and correct.

  4. Dependency Management - Added rubocop-rails-omakase gem properly locked in Gemfile.lock. Good choice for Rails-focused monorepo.

Observations and Questions

1. Pro Package ERB Templating - The Pro package uses dynamic exclusions via ERB (lines 6-8). Is this approach documented? It's clever but makes config non-standard YAML. Consider adding explanatory comment or documenting in CLAUDE.md.

2. Version Consistency - Root config sets TargetRubyVersion: 3.0, but CLAUDE.md shows project supports Ruby 3.2+ (min) and 3.4 (latest). Should this be updated to 3.2?

3. Metrics Loosening - Root config has Metrics/CyclomaticComplexity Max: 8 and NestedGroups Max: 5, but react_on_rails previously had Max: 7 and Max: 4 (stricter). This loosens limits for open-source package. Is this intentional?

Security and Quality

✅ No security concerns - configuration changes only
✅ No breaking changes - inheritance works correctly
✅ CI is running - will validate config works across all test suites

Final Verdict

APPROVED with minor questions

This is high-quality refactoring that reduces maintenance burden, improves consistency, follows best practices, and maintains package-specific flexibility. Questions raised are minor clarifications, not blockers. Ready to merge once CI passes.

Suggested Follow-ups

  1. Document ERB templating pattern
  2. Consider updating TargetRubyVersion to 3.2
  3. Add note to CLAUDE.md about unified config
  4. Verify intentional metrics loosening

Great work on this refactoring! 🎉

Co-authored-by: Ihab Adham <ihabadham@users.noreply.github.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5ff29fb and 1fafb9c.

📒 Files selected for processing (1)
  • react_on_rails_pro/.rubocop.yml (1 hunks)
🧰 Additional context used
🧠 Learnings (12)
📓 Common learnings
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: Applies to **/*.{rb,rake} : ALWAYS run `bundle exec rubocop` and fix ALL violations before every commit/push
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: ALWAYS let Prettier and RuboCop handle ALL formatting - never manually format
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: The `react_on_rails_pro/` directory has its own Prettier/ESLint configuration and must be linted separately
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: Resolve merge conflicts by: resolving logical conflicts first, verifying file paths with grep, testing affected scripts, auto-fixing formatting with `rake autofix`, and testing critical scripts if build configs changed
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: Applies to lib/react_on_rails/*.rb : Create RBS signature files for new Ruby files in `lib/react_on_rails/` by adding corresponding `.rbs` file in `sig/react_on_rails/`, adding to Steepfile, and validating before committing
📚 Learning: 2025-11-25T08:05:17.804Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: Applies to **/*.{rb,rake} : ALWAYS run `bundle exec rubocop` and fix ALL violations before every commit/push

Applied to files:

  • react_on_rails_pro/.rubocop.yml
📚 Learning: 2025-11-25T08:05:17.804Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: The `react_on_rails_pro/` directory has its own Prettier/ESLint configuration and must be linted separately

Applied to files:

  • react_on_rails_pro/.rubocop.yml
📚 Learning: 2025-09-16T08:01:11.146Z
Learnt from: justin808
Repo: shakacode/react_on_rails PR: 1770
File: lib/generators/react_on_rails/templates/base/base/app/javascript/src/HelloWorld/ror_components/HelloWorld.client.jsx:2-2
Timestamp: 2025-09-16T08:01:11.146Z
Learning: React on Rails uses webpack CSS Modules configuration with namedExports: true, which requires the import syntax `import * as style from './file.module.css'` rather than the default export pattern. This configuration enables better tree shaking and bundle size optimization for CSS modules.

Applied to files:

  • react_on_rails_pro/.rubocop.yml
📚 Learning: 2025-11-25T08:05:17.804Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: Applies to lib/react_on_rails/*.rb : Create RBS signature files for new Ruby files in `lib/react_on_rails/` by adding corresponding `.rbs` file in `sig/react_on_rails/`, adding to Steepfile, and validating before committing

Applied to files:

  • react_on_rails_pro/.rubocop.yml
📚 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:

  • react_on_rails_pro/.rubocop.yml
📚 Learning: 2025-11-25T08:05:17.804Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: Applies to sig/react_on_rails/**/*.rbs : In RBS type signature files, define type signatures that correspond to Ruby files in `lib/react_on_rails/`

Applied to files:

  • react_on_rails_pro/.rubocop.yml
📚 Learning: 2025-02-12T16:38:06.537Z
Learnt from: Romex91
Repo: shakacode/react_on_rails PR: 1697
File: package-scripts.yml:28-28
Timestamp: 2025-02-12T16:38:06.537Z
Learning: The file `node_package/lib/ReactOnRails.full.js` is autogenerated during the build process and should not be present in the repository.

Applied to files:

  • react_on_rails_pro/.rubocop.yml
📚 Learning: 2025-11-25T08:05:17.804Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: Applies to /CHANGELOG.md : Update `/CHANGELOG.md` for user-visible changes (features, bug fixes, breaking changes, deprecations, performance improvements) to the open-source React on Rails gem and npm package

Applied to files:

  • react_on_rails_pro/.rubocop.yml
📚 Learning: 2025-11-25T08:05:17.804Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: ALWAYS let Prettier and RuboCop handle ALL formatting - never manually format

Applied to files:

  • react_on_rails_pro/.rubocop.yml
📚 Learning: 2025-11-25T08:05:17.804Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: Exclude `/coverage`, `/tmp`, `/gen-examples`, `/packages/react-on-rails/lib`, `/node_modules`, `/spec/dummy/node_modules`, `/spec/dummy/tmp`, `/spec/dummy/app/assets/webpack`, `/spec/dummy/log`, `/spec/dummy/e2e/playwright-report`, `/spec/dummy/test-results` from IDE indexing

Applied to files:

  • react_on_rails_pro/.rubocop.yml
📚 Learning: 2025-02-13T14:29:49.267Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1644
File: spec/react_on_rails/utils_spec.rb:218-218
Timestamp: 2025-02-13T14:29:49.267Z
Learning: In RSpec tests, prefer using local variables over constants within test blocks to avoid constant redefinition warnings and maintain better test isolation.

Applied to files:

  • react_on_rails_pro/.rubocop.yml
⏰ 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). (10)
  • GitHub Check: build-dummy-app-webpack-test-bundles (3.2, 20, minimum)
  • GitHub Check: examples (3.2, minimum)
  • GitHub Check: examples (3.4, latest)
  • GitHub Check: rspec-package-tests (3.2, minimum)
  • GitHub Check: rspec-package-tests (3.4, latest)
  • GitHub Check: pro-lint-js-and-ruby
  • GitHub Check: build
  • GitHub Check: build-dummy-app-webpack-test-bundles
  • GitHub Check: build-dummy-app-webpack-test-bundles
  • GitHub Check: claude-review
🔇 Additional comments (2)
react_on_rails_pro/.rubocop.yml (2)

24-28: Retain custom RSpec language expectations for react_on_rails testing.

The custom expectation matchers change_text_expect_dom_selector and check_match are specific to react_on_rails' testing framework and should remain in this configuration. Keeping them in the Pro package config (rather than centralizing in the root config) is appropriate since these are Pro-specific test helpers.


6-8: ERB preprocessing in RuboCop configuration is valid.

Configuration files are pre-processed using the ERB templating mechanism. This makes it possible to add dynamic content that will be evaluated when the configuration file is read. The pattern of using git status --ignored to dynamically exclude git-ignored paths is a valid example of letting RuboCop ignore all files ignored by Git, so the implementation here is correct.

Copy link
Contributor

@ihabadham ihabadham left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just some comments for failing CI

.rubocop.yml Outdated
- 'node_modules/**/*'
- 'spec/fixtures/**/*'
- 'spec/react_on_rails/dummy-for-generators/**/*'
- 'vendor/**/*'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

**/vendor/**/* should be used instead of vendor/**/* because CI installs gems to react_on_rails/vendor/bundle/ and react_on_rails_pro/vendor/bundle/. Without the **/ prefix, RuboCop scans those directories and finds .rubocop.yml files inside gems (like docile which references panolint, and cypress-on-rails which references rubocop-rails-omakase) - causing the CI failures.

@ihabadham
Copy link
Contributor

@claude can you address my review i just made by:
1- pulling locally
2- verify both claimed issues by checking the rubocop docs, and then trying to reproduce
3- if confirmed, fix both in different commits
4- push and wait for ci to pass, especially the currently lint failing ones
5- if passed, revert the commit that added rubocop-rails-omakase and push and wait for ci to pass again

if any if these steps break or behave unexpected, stop and report back

@claude
Copy link

claude bot commented Dec 4, 2025

Claude finished @ihabadham's task —— View job


Addressing Review Feedback - Status Report

Tasks Completed

Current Status: Needs Approval for Auto-Correct

Both claimed issues were VALID and have been fixed:

  1. Issue TODO for first version #1 - Fixed vendor exclusion pattern:

    • Changed vendor/**/* to **/vendor/**/* in root .rubocop.yml
    • This now properly excludes vendor directories at any depth (including react_on_rails/vendor/bundle/ and react_on_rails_pro/vendor/bundle/)
  2. Issue Make work with turbolinks and better helper #2 - Added inherit_mode merge:

    • Added inherit_mode: merge: [Exclude] to both child configs
    • Child configs now properly merge their Exclude arrays with the parent instead of replacing them

CI Results:

The "Lint JS and Ruby" job failed with 12 autocorrectable offenses:

157 files inspected, 12 offenses detected, 12 offenses autocorrectable

All 12 offenses are Lint/RedundantCopDisableDirective for Metrics/CyclomaticComplexity. This is expected because:

  • The root config changed the complexity threshold from 7 to 8
  • Methods that previously needed # rubocop:disable Metrics/CyclomaticComplexity now comply naturally
  • Their disable comments are now redundant and should be removed

Next Steps:

I need approval to run:

cd react_on_rails && bundle exec rubocop --auto-correct-all

This will remove the 12 redundant disable comments. Then I can commit, push, and wait for CI to pass before proceeding with the rubocop-rails-omakase revert test.

Commits Pushed:

  • e48275d - Fix vendor exclusion pattern to match vendor at any depth
  • d92a090 - Add inherit_mode merge for Exclude arrays in child configs

--- | Branch: alexeyr/rubocop-config

github-actions bot and others added 2 commits December 4, 2025 23:07
Change vendor/**/* to **/vendor/**/* to properly exclude vendor directories
in subdirectories like react_on_rails/vendor/bundle/ and
react_on_rails_pro/vendor/bundle/ where CI installs gems.

Co-authored-by: Ihab Adham <ihabadham@users.noreply.github.com>
Without inherit_mode merge, child Exclude arrays replace the parent's
instead of merging with them. This was causing all root exclusions
(node_modules, tmp, coverage, etc.) to be lost in the child configs.

Co-authored-by: Ihab Adham <ihabadham@users.noreply.github.com>
@ihabadham
Copy link
Contributor

All 12 offenses are Lint/RedundantCopDisableDirective for Metrics/CyclomaticComplexity. This is expected because:

  • The root config changed the complexity threshold from 7 to 8

@alexeyr-ci2 any reason for this? or just globalize the pro configs?

@claude
Copy link

claude bot commented Dec 10, 2025

Code Review - RuboCop Configuration Unification

✅ Overall Assessment

This PR successfully unifies RuboCop configuration across the monorepo by creating a shared root configuration that both react_on_rails/ and react_on_rails_pro/ inherit from. The changes are well-structured and follow best practices.


🎯 Strengths

  1. DRY Principle: Eliminates significant duplication (~200+ lines) by consolidating shared rules into a single root configuration
  2. Proper Inheritance: Both sub-packages correctly use inherit_from and inherit_mode: merge to extend the root config
  3. Code Cleanup: Removes unnecessary inline RuboCop disable comments, indicating the code now meets standard complexity metrics
  4. Prettier Integration: Root config is now formatted by Prettier (removed from root .prettierignore), while Pro package appropriately excludes it due to ERB syntax
  5. Dependency Updates: Adds missing RuboCop plugins (rubocop-minitest, rubocop-rails) that may have been indirect dependencies before

📋 Code Quality Observations

Removed RuboCop Disables - All removed disables appear justified:

  • doctor.rb: Methods like check_gem_wildcards and check_npm_wildcards have cyclomatic complexity ≤ 8 (within the Max: 8 limit)
  • switch-bundler: update_dependencies and install_dependencies appear to meet complexity requirements
  • system_checker.rb, utils.rb, version_checker.rb: Similar cleanup of unnecessary suppressions

Configuration Structure:

  • Root config sets sensible defaults (Max line length: 120, CyclomaticComplexity: 8, etc.)
  • Sub-packages only override what's specific to them (file exclusions, generator-specific overrides)
  • Good use of comments explaining why specific files are excluded

🔍 Potential Concerns

  1. New Dependencies: rubocop-minitest and rubocop-rails were added to Gemfile.lock. These should be:

    • Verified as intentional additions (not accidental)
    • Checked if they introduce new cops that might fail CI
    • Documented if they're now direct dependencies vs. transitive
  2. CyclomaticComplexity Limit: The root sets Max: 8 while the old react_on_rails/.rubocop.yml had Max: 7. This is a relaxation of the rule:

    • Verify this is intentional
    • Check if any code now passes at complexity 8 that would have failed at 7
    • Consider if this should be 7 to maintain strictness
  3. Pro Package ClassLength: The root sets Max: 150 but the old Pro config had Max: 140. Another relaxation:

    • Document if this change is intentional
    • Consider harmonizing to the stricter value
  4. ERB in Pro Config: The Pro .rubocop.yml contains ERB (<% git status ... %>):

    • Confirm this ERB is evaluated correctly
    • Verify the Prettier exclusion is necessary and sufficient

🧪 Testing Recommendations

Based on CLAUDE.md requirements:

  1. MANDATORY - Run full lint check:

    bundle exec rubocop
  2. Verify Pro package separately (has its own config):

    cd react_on_rails_pro && bundle exec rubocop
  3. Check for new violations from newly added cops:

    bundle exec rubocop --only Rails,Minitest
  4. Verify formatting:

    pnpm run format.listDifferent

🔧 Minor Suggestions

  1. Document Complexity Changes: Add a note in the PR description explaining why CyclomaticComplexity was relaxed from 7→8 and ClassLength from 140→150

  2. RSpec/NestedGroups: Root has Max: 5 but old react_on_rails had Max: 4. Document this relaxation as well

  3. Trailing Newlines: ✅ Verified - all files properly end with newlines

  4. Consistency Check: The TargetRubyVersion in root is 3.0 (as string) vs old react_on_rails had 3.0.0. Verify this doesn't affect cop behavior


📚 Documentation

  • ✅ PR description clearly states this is extracted from Add performance tests #1868
  • ⚠️ Changelog not updated - but this is acceptable per CLAUDE.md (internal refactoring, not user-facing)
  • ✅ No tests needed - this is configuration only

🚀 Recommendation

Approve with minor follow-ups:

  1. Verify CI passes with the new unified configuration
  2. Document the metric relaxations (complexity 7→8, class length 140→150, nested groups 4→5) in PR description or confirm they're intentional
  3. Confirm the new RuboCop plugin dependencies are intended

This is a solid refactoring that improves maintainability. The code quality improvements (removing unnecessary disable comments) suggest the original suppressions were overly cautious.


📊 Stats

  • Files changed: 12
  • Additions: +126
  • Deletions: -195
  • Net reduction: -69 lines (excellent!)
  • Duplication eliminated: ~80-90 lines of config per package

@claude
Copy link

claude bot commented Dec 10, 2025

Code Review - PR #2153: Unify RuboCop Config

✅ Overall Assessment

This is a well-executed refactoring that successfully centralizes RuboCop configuration across the monorepo. The changes follow best practices for inheritance-based configuration management.


🎯 Strengths

  1. Excellent DRY Principle Application

    • Eliminates ~160 lines of duplicated configuration between react_on_rails/ and react_on_rails_pro/
    • Creates a single source of truth for shared linting rules at the root
  2. Proper Inheritance Configuration

    • Correctly uses inherit_from: ../.rubocop.yml in both sub-packages
    • Uses inherit_mode: merge to extend Exclude arrays rather than replacing them
    • This is the recommended RuboCop pattern for monorepo configurations
  3. Smart Inline Comment Removal

    • Removes unnecessary # rubocop:disable Metrics/CyclomaticComplexity comments from:
      • doctor.rb (3 methods)
      • system_checker.rb (3 methods)
      • utils.rb (1 method)
      • version_checker.rb (1 method)
      • server_rendering_pool/ruby_embedded_java_script.rb (1 method)
      • bin/switch-bundler (1 location)
    • These can now be removed because the centralized config properly sets Max: 8 for cyclomatic complexity
  4. Consistent Metrics Configuration

    • Root config properly centralizes all metric thresholds:
      • Metrics/AbcSize: Max: 28
      • Metrics/CyclomaticComplexity: Max: 8
      • Metrics/MethodLength: Max: 41
      • etc.
  5. Prettier Ignore Cleanup

    • Removes .rubocop.yml from root .prettierignore (no longer using ERB there)
    • Adds it to react_on_rails_pro/.prettierignore (still uses ERB for dynamic git-ignored files)

🔍 Areas to Verify

  1. Inconsistent Metrics/CyclomaticComplexity Handling

    There's one method that still has the disable comment:

    File: react_on_rails/lib/react_on_rails/doctor.rb:564-598

    # rubocop:disable Metrics/CyclomaticComplexity
    def check_server_rendering_engine
      # ... (35 lines with case/when logic)
    end
    # rubocop:enable Metrics/CyclomaticComplexity

    Question: Why was this one kept while others were removed?

    • If this method actually exceeds the Max: 8 threshold and the others don't, the comment should stay
    • If all methods are now compliant with Max: 8, this comment should also be removed
    • Consider running RuboCop to verify which methods actually need exceptions
  2. Missing Root .prettierignore Entry?

    The root .rubocop.yml is now a pure YAML file (no ERB), but:

    • Line 37 in root config: Layout/LineLength: Max: 120
    • Prettier might still try to format it based on line length

    Recommendation: Consider if .rubocop.yml should be added back to root .prettierignore since it's a config file that benefits from manual formatting control. Check if Prettier actually modifies it.

  3. Gemfile.lock Changes

    The PR adds several new dependencies to react_on_rails/Gemfile.lock:

    • rubocop-minitest
    • rubocop-rails

    Question: Are these intentional additions? They appear in the lockfile but aren't referenced in the require: section of any RuboCop config. If they're not needed, they should be removed to avoid bloat.

  4. TargetRubyVersion Inconsistency

    • Root config: TargetRubyVersion: 3.0
    • Old react_on_rails/.rubocop.yml: had 3.0.0 (removed in this PR)

    While both are equivalent, the change is correct. Just noting for awareness.


🧪 Testing Recommendations

MANDATORY (per CLAUDE.md):

# Verify RuboCop passes with zero offenses
bundle exec rubocop

# Test from both sub-packages
cd react_on_rails && bundle exec rubocop
cd react_on_rails_pro && bundle exec rubocop

Additional verification:

# Verify the inheritance is working correctly
cd react_on_rails
bundle exec rubocop --show-cops | grep -A2 "Metrics/CyclomaticComplexity"

# Should show: Max: 8 (from root config)

📋 Code Quality

  • ✅ No security concerns
  • ✅ No performance impact (linting is development-time only)
  • ✅ No functional changes to application code
  • ✅ Proper monorepo configuration pattern
  • ⚠️ Minor inconsistencies noted above

🎓 Suggestions

  1. Document the inheritance pattern in a comment at the top of the root .rubocop.yml:

    # Root RuboCop configuration for React on Rails monorepo
    # This contains shared settings inherited by react_on_rails/ and react_on_rails_pro/
    # Each sub-package can override or extend these settings as needed

    (Actually, this is already there! Good job!)

  2. Consider a follow-up PR to:

    • Remove the one remaining # rubocop:disable Metrics/CyclomaticComplexity comment if it's no longer needed
    • Clean up the unexpected rubocop-minitest and rubocop-rails dependencies if they're not required

✅ Approval Recommendation

APPROVE with minor follow-up recommended.

This is a solid refactoring that improves maintainability. The minor issues noted are not blockers and can be addressed in a follow-up PR if needed.

The centralized configuration will make it much easier to update linting rules consistently across the monorepo in the future.


Review performed according to CLAUDE.md guidelines for React on Rails project.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
.rubocop.yml (1)

7-19: AllCops Include overrides defaults and drops subdirectory Gemfiles

By setting AllCops: Include explicitly, you replace RuboCop’s default include patterns. As written, only the root Gemfile is picked up, not react_on_rails/**/Gemfile, react_on_rails_pro/**/Gemfile, or other special files (Guardfile/Capfile, etc.). If you still want those to be linted, consider adding **/Gemfile (and any other patterns you care about) back into Include, or avoid overriding the defaults entirely.

Aside from this, the consolidated config (extensions, excludes, metrics, RSpec cops) looks consistent with the repo’s style goals.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between de91e38 and 2999433.

⛔ Files ignored due to path filters (2)
  • react_on_rails_pro/Gemfile.lock is excluded by !**/*.lock
  • react_on_rails_pro/spec/dummy/Gemfile.lock is excluded by !**/*.lock
📒 Files selected for processing (5)
  • .rubocop.yml (1 hunks)
  • Gemfile.shared_dev_dependencies (1 hunks)
  • react_on_rails/Gemfile.development_dependencies (1 hunks)
  • react_on_rails_pro/Gemfile (1 hunks)
  • react_on_rails_pro/Gemfile.development_dependencies (1 hunks)
🧰 Additional context used
🧠 Learnings (18)
📓 Common learnings
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-10T09:27:45.093Z
Learning: Applies to **/*.{rb,js,ts,jsx,tsx,json,yml,yaml,md} : ALWAYS run `bundle exec rubocop` and fix ALL violations before every commit/push
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-10T09:27:45.093Z
Learning: Applies to **/*.rb : ALWAYS let RuboCop handle ALL formatting - never manually format Ruby code
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-10T09:27:45.093Z
Learning: Applies to **/*.rbs : Add RBS signature files for all new Ruby files in `lib/react_on_rails/` and register them in Steepfile; validate with `bundle exec rake rbs:validate`
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-10T09:27:45.093Z
Learning: Applies to react_on_rails_pro/**/*.{js,ts,jsx,tsx,json,css,scss} : The `react_on_rails_pro/` directory has its own Prettier/ESLint configuration separate from the root; CI lints both directories separately
📚 Learning: 2025-12-10T09:27:45.093Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-10T09:27:45.093Z
Learning: Applies to react_on_rails_pro/**/*.{js,ts,jsx,tsx,json,css,scss} : The `react_on_rails_pro/` directory has its own Prettier/ESLint configuration separate from the root; CI lints both directories separately

Applied to files:

  • Gemfile.shared_dev_dependencies
  • .rubocop.yml
  • react_on_rails_pro/Gemfile.development_dependencies
  • react_on_rails/Gemfile.development_dependencies
  • react_on_rails_pro/Gemfile
📚 Learning: 2025-12-10T09:27:45.093Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-10T09:27:45.093Z
Learning: Applies to **/*.{rb,js,ts,jsx,tsx,json,yml,yaml,md} : ALWAYS run `bundle exec rubocop` and fix ALL violations before every commit/push

Applied to files:

  • Gemfile.shared_dev_dependencies
  • .rubocop.yml
  • react_on_rails_pro/Gemfile.development_dependencies
  • react_on_rails/Gemfile.development_dependencies
📚 Learning: 2025-12-10T09:27:45.093Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-10T09:27:45.093Z
Learning: Applies to lib/react_on_rails/**/*.rb : Engine code has limited access to host application; use `Rails.root` for host app paths and `ReactOnRails.configure` for engine configuration

Applied to files:

  • Gemfile.shared_dev_dependencies
  • .rubocop.yml
  • react_on_rails_pro/Gemfile.development_dependencies
  • react_on_rails/Gemfile.development_dependencies
  • react_on_rails_pro/Gemfile
📚 Learning: 2025-02-12T16:38:06.537Z
Learnt from: Romex91
Repo: shakacode/react_on_rails PR: 1697
File: package-scripts.yml:28-28
Timestamp: 2025-02-12T16:38:06.537Z
Learning: The file `node_package/lib/ReactOnRails.full.js` is autogenerated during the build process and should not be present in the repository.

Applied to files:

  • Gemfile.shared_dev_dependencies
  • .rubocop.yml
  • react_on_rails_pro/Gemfile.development_dependencies
  • react_on_rails/Gemfile.development_dependencies
  • react_on_rails_pro/Gemfile
📚 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:

  • Gemfile.shared_dev_dependencies
  • .rubocop.yml
  • react_on_rails_pro/Gemfile.development_dependencies
  • react_on_rails/Gemfile.development_dependencies
  • react_on_rails_pro/Gemfile
📚 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:

  • Gemfile.shared_dev_dependencies
  • react_on_rails/Gemfile.development_dependencies
📚 Learning: 2025-12-10T09:27:45.093Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-10T09:27:45.093Z
Learning: Applies to lib/generators/react_on_rails/**/*.rb : Generators run in host app context, not engine context; do not assume host app structure (e.g., `app/javascript/` may not exist in older apps)

Applied to files:

  • Gemfile.shared_dev_dependencies
  • .rubocop.yml
  • react_on_rails_pro/Gemfile.development_dependencies
  • react_on_rails/Gemfile.development_dependencies
  • react_on_rails_pro/Gemfile
📚 Learning: 2025-12-10T09:27:45.093Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-10T09:27:45.093Z
Learning: Applies to **/*.rbs : Add RBS signature files for all new Ruby files in `lib/react_on_rails/` and register them in Steepfile; validate with `bundle exec rake rbs:validate`

Applied to files:

  • Gemfile.shared_dev_dependencies
  • .rubocop.yml
  • react_on_rails_pro/Gemfile.development_dependencies
  • react_on_rails/Gemfile.development_dependencies
  • react_on_rails_pro/Gemfile
📚 Learning: 2025-12-10T09:27:45.093Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-10T09:27:45.093Z
Learning: Applies to **/*.rb : ALWAYS let RuboCop handle ALL formatting - never manually format Ruby code

Applied to files:

  • .rubocop.yml
  • react_on_rails_pro/Gemfile.development_dependencies
  • react_on_rails/Gemfile.development_dependencies
📚 Learning: 2025-12-10T09:27:45.093Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-10T09:27:45.093Z
Learning: Applies to lib/react_on_rails/**/*.rb : Create corresponding RBS signature files in `sig/react_on_rails/` for new Ruby files and add them to Steepfile for type checking

Applied to files:

  • .rubocop.yml
  • react_on_rails_pro/Gemfile.development_dependencies
  • react_on_rails/Gemfile.development_dependencies
  • react_on_rails_pro/Gemfile
📚 Learning: 2025-09-16T08:01:11.146Z
Learnt from: justin808
Repo: shakacode/react_on_rails PR: 1770
File: lib/generators/react_on_rails/templates/base/base/app/javascript/src/HelloWorld/ror_components/HelloWorld.client.jsx:2-2
Timestamp: 2025-09-16T08:01:11.146Z
Learning: React on Rails uses webpack CSS Modules configuration with namedExports: true, which requires the import syntax `import * as style from './file.module.css'` rather than the default export pattern. This configuration enables better tree shaking and bundle size optimization for CSS modules.

Applied to files:

  • .rubocop.yml
  • react_on_rails_pro/Gemfile.development_dependencies
  • react_on_rails/Gemfile.development_dependencies
  • react_on_rails_pro/Gemfile
📚 Learning: 2025-12-10T09:27:45.093Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-10T09:27:45.093Z
Learning: Applies to **/*.{rb,js,ts,jsx,tsx,json,yml,yaml,md} : ALWAYS ensure files end with a newline character before committing

Applied to files:

  • .rubocop.yml
📚 Learning: 2025-12-10T09:27:45.093Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-10T09:27:45.093Z
Learning: Applies to spec/dummy/**/*.{spec,test}.{js,ts} : Playwright E2E tests use `cypress-on-rails` gem for Rails integration; use helpers like `app('clean')`, `appEval()`, and `appFactories()` for test setup instead of UI automation

Applied to files:

  • .rubocop.yml
  • react_on_rails_pro/Gemfile
📚 Learning: 2025-12-10T09:27:45.093Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-10T09:27:45.093Z
Learning: Applies to spec/dummy/e2e/playwright/app_commands/**/*.rb : Create custom app commands for Playwright E2E tests in this directory using the `command` syntax provided by `cypress-on-rails` gem

Applied to files:

  • .rubocop.yml
📚 Learning: 2025-12-10T09:27:45.093Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-10T09:27:45.093Z
Learning: Applies to /CHANGELOG.md : Update `/CHANGELOG.md` for open-source features, bug fixes, breaking changes, deprecations, and performance improvements using format: `[PR 1818](https://github.com/shakacode/react_on_rails/pull/1818) by [username](https://github.com/username)`

Applied to files:

  • react_on_rails_pro/Gemfile.development_dependencies
  • react_on_rails/Gemfile.development_dependencies
📚 Learning: 2025-12-10T09:27:45.093Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-10T09:27:45.093Z
Learning: Use RBS (Ruby Signature) with Steep for static type checking; enable runtime type checking by default during test runs (can be disabled with `DISABLE_RBS_RUNTIME_CHECKING=true`)

Applied to files:

  • react_on_rails_pro/Gemfile.development_dependencies
  • react_on_rails/Gemfile.development_dependencies
📚 Learning: 2024-07-27T10:08:35.868Z
Learnt from: theforestvn88
Repo: shakacode/react_on_rails PR: 1620
File: spec/dummy/client/app/startup/HelloTurboStream.jsx:3-3
Timestamp: 2024-07-27T10:08:35.868Z
Learning: The `RailsContext` import in `spec/dummy/client/app/startup/HelloTurboStream.jsx` is used later in the project, as clarified by the user theforestvn88.

Applied to files:

  • react_on_rails_pro/Gemfile
⏰ 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). (12)
  • GitHub Check: build-dummy-app-webpack-test-bundles (3.2, 20, minimum)
  • GitHub Check: build-dummy-app-webpack-test-bundles (3.4, 22, latest)
  • GitHub Check: rspec-package-tests (3.4, latest)
  • GitHub Check: rspec-package-tests (3.2, minimum)
  • GitHub Check: examples (3.2, minimum)
  • GitHub Check: examples (3.4, latest)
  • GitHub Check: pro-lint-js-and-ruby
  • GitHub Check: build-dummy-app-webpack-test-bundles
  • GitHub Check: build
  • GitHub Check: build-dummy-app-webpack-test-bundles
  • GitHub Check: precompile-check
  • GitHub Check: claude-review
🔇 Additional comments (4)
react_on_rails_pro/Gemfile.development_dependencies (1)

4-6: Clarifying comment about shared dev dependencies looks good

The note about loading shared dev dependencies via the main Gemfile (due to Gemfile.loader’s use of eval and __dir__) is clear and should help prevent future confusion. No changes needed.

Gemfile.shared_dev_dependencies (1)

1-10: Centralized RuboCop dev dependencies look consistent

Defining rubocop, rubocop-performance, and rubocop-rspec once in this shared file under :development, :test is a clean way to keep linting tool versions in sync between react_on_rails and react_on_rails_pro.

Please just double‑check that these pinned versions match what CI currently expects so Bundler/lockfiles don’t drift after merge.

react_on_rails_pro/Gemfile (1)

8-11: Ordering and path for shared dev deps eval look correct

Loading ../Gemfile.shared_dev_dependencies here (before Gemfile.loader) aligns with the __dir__ comment and should keep shared RuboCop tooling available for the pro app without changing runtime dependencies.

Worth a quick Bundler run in CI to confirm there are no surprises in group resolution, but the structure itself looks sound.

react_on_rails/Gemfile.development_dependencies (1)

3-3: Shared dev deps inclusion from engine Gemfile.development_dependencies LGTM

Pulling in ../Gemfile.shared_dev_dependencies at the top centralizes RuboCop-related tooling while keeping the existing development/test groups intact. This should reduce version skew between the engine and the pro app.

No changes requested; just ensure CI/Bundler runs pick up the new shared file as expected.

@claude
Copy link

claude bot commented Dec 10, 2025

Code Review: Unify RuboCop Config

Thank you for this PR! This is a well-structured refactoring that centralizes RuboCop configuration across the monorepo. Here's my detailed review:


Strengths

  1. DRY Principle Applied Correctly

    • Centralized shared RuboCop configuration eliminates duplication between open-source and Pro packages
    • Proper use of inherit_from and inherit_mode to merge excludes rather than replace them
    • Shared dev dependencies in Gemfile.shared_dev_dependencies ensures version consistency
  2. Good Configuration Structure

    • Root .rubocop.yml contains shared rules
    • Package-specific configs only contain exceptions/overrides
    • ERB syntax in Pro's config is now properly excluded from Prettier via .prettierignore
  3. Reduced Inline Directives

    • Successfully removed many unnecessary rubocop:disable comments from source files
    • Files like doctor.rb, system_checker.rb, utils.rb, etc. are cleaner without excessive inline disables
  4. Proper Documentation

    • Clear comments explaining inheritance structure
    • Good rationale for exceptions (e.g., "Generator complexity justified")

⚠️ Minor Concerns

  1. Incomplete Inline Directive Cleanup

    There are still many rubocop:disable comments in the codebase that could potentially be addressed by the centralized config:

    • helper.rb: Lines 3-4, 271 (ModuleLength, MethodLength, AbcSize, CyclomaticComplexity)
    • packs_generator.rb: Lines 7, 66 (ClassLength, CyclomaticComplexity)
    • dev/server_manager.rb: Multiple instances (lines 151, 245, 269, 298, 318, 334, 364, 398, 628)
    • doctor.rb: Lines 11, 37, 394

    Recommendation: While not critical for this PR, consider a follow-up to evaluate if these should be:

    • Added to the centralized config's Exclude sections
    • Refactored to meet the metrics
    • Kept as intentional exceptions with justifying comments
  2. Prettier Ignore Consistency

    The root .prettierignore removed the specific .rubocop.yml entry and relies on the broader *.yml pattern, while Pro's .prettierignore explicitly adds .rubocop.yml back with a comment about ERB.

    Question: Is the ERB syntax only used in Pro's config? If so, this is fine. If ERB might be added to the root config later, consider adding a comment there too.

  3. Path Structure Comment Accuracy

    In react_on_rails_pro/Gemfile.development_dependencies, line 5 says:

    "# NOTE: Shared dev dependencies (rubocop, etc.) are loaded via eval_gemfile in the main Gemfile, not here."

    This is accurate and explains why the Pro package loads shared deps differently. Good documentation! ✅


🔍 Testing Recommendations

Before merging, please verify:

  1. RuboCop runs successfully from both package directories:

    # From root
    bundle exec rubocop
    
    # From react_on_rails/
    cd react_on_rails && bundle exec rubocop
    
    # From react_on_rails_pro/
    cd react_on_rails_pro && bundle exec rubocop
  2. No new offenses introduced:
    Compare the offense count before/after to ensure the centralized config doesn't inadvertently allow new violations

  3. Verify CI passes:
    Especially the pro-lint-js-and-ruby job which runs RuboCop on Pro package

  4. Check Prettier still ignores RuboCop configs:

    pnpm run format.listDifferent

🎯 Summary

This is a high-quality refactoring that:

  • ✅ Eliminates configuration duplication
  • ✅ Maintains proper inheritance hierarchy
  • ✅ Reduces inline disable comments
  • ✅ Follows monorepo best practices

Recommendation: Approve with minor suggestions for follow-up cleanup.

The core change is solid. The remaining inline directives can be addressed in a future PR if desired, but they don't block this one.


📝 Optional Follow-up Work

  1. Audit remaining rubocop:disable comments and either refactor code or document why exceptions are needed
  2. Consider adding more comprehensive Exclude patterns to root config for common complex files
  3. Document the RuboCop configuration strategy in CONTRIBUTING.md or similar

Great work on improving the codebase structure! 🚀

@alexeyr-ci2 alexeyr-ci2 force-pushed the alexeyr/rubocop-config branch from 085b946 to a04fa6a Compare December 10, 2025 14:20
@ihabadham ihabadham self-requested a review December 10, 2025 18:12
# Keep in sync with https://github.com/shakacode/react_on_rails/blob/master/Gemfile.development_dependencies
# frozen_string_literal: true

# NOTE: Shared dev dependencies (rubocop, etc.) are loaded via eval_gemfile in
Copy link
Contributor

@ihabadham ihabadham Dec 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couldn't we fix Gemfile.loader instead? Changing eval(base_deps) to eval(base_deps, binding, filepath) would preserve __dir__, and we wouldn't have this here look inconsistent between ror and rorp

…ution

Changed eval() to instance_eval(content, filepath) which preserves __dir__
in evaluated content (matching Bundler's internal eval_gemfile pattern).

This allows eval_gemfile calls to work correctly inside loaded files,
so shared dev dependencies can now be loaded from Gemfile.development_dependencies
where they logically belong, instead of requiring a workaround in the main Gemfile.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@coderabbitai coderabbitai bot added the full-ci label Dec 10, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
react_on_rails_pro/Gemfile.loader (1)

8-16: Minor optimization opportunity: redundant path expansion.

File.expand_path is called twice for each path—once in the existence check and once for assignment. This could be streamlined:

-override_deps_path = if ENV["CI"] == "true" && File.exist?(File.expand_path("./Gemfile.ci", __dir__))
+ci_path = File.expand_path("./Gemfile.ci", __dir__)
+local_path = File.expand_path("./Gemfile.local", __dir__)
+
+override_deps_path = if ENV["CI"] == "true" && File.exist?(ci_path)
   # In CI environment, use CI dependencies
-  File.expand_path("./Gemfile.ci", __dir__)
-elsif File.exist?(File.expand_path("./Gemfile.local", __dir__))
+  ci_path
+elsif File.exist?(local_path)
   # In non-CI environment, use local dependencies if they exist
-  File.expand_path("./Gemfile.local", __dir__)
+  local_path
 end

Not critical—current code is functionally correct.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a04fa6a and d110e35.

📒 Files selected for processing (2)
  • react_on_rails_pro/Gemfile.development_dependencies (1 hunks)
  • react_on_rails_pro/Gemfile.loader (2 hunks)
🧰 Additional context used
🧠 Learnings (13)
📓 Common learnings
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-10T09:27:45.093Z
Learning: Applies to **/*.{rb,js,ts,jsx,tsx,json,yml,yaml,md} : ALWAYS run `bundle exec rubocop` and fix ALL violations before every commit/push
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-10T09:27:45.093Z
Learning: Applies to react_on_rails_pro/**/*.{js,ts,jsx,tsx,json,css,scss} : The `react_on_rails_pro/` directory has its own Prettier/ESLint configuration separate from the root; CI lints both directories separately
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-10T09:27:45.093Z
Learning: Applies to **/*.rbs : Add RBS signature files for all new Ruby files in `lib/react_on_rails/` and register them in Steepfile; validate with `bundle exec rake rbs:validate`
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-10T09:27:45.093Z
Learning: Applies to **/*.rb : ALWAYS let RuboCop handle ALL formatting - never manually format Ruby code
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-10T09:27:45.093Z
Learning: Applies to lib/react_on_rails/**/*.rb : Engine code has limited access to host application; use `Rails.root` for host app paths and `ReactOnRails.configure` for engine configuration
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.
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-10T09:27:45.093Z
Learning: Applies to lib/react_on_rails/**/*.rb : Create corresponding RBS signature files in `sig/react_on_rails/` for new Ruby files and add them to Steepfile for type checking
📚 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:

  • react_on_rails_pro/Gemfile.development_dependencies
  • react_on_rails_pro/Gemfile.loader
📚 Learning: 2025-12-10T09:27:45.093Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-10T09:27:45.093Z
Learning: Applies to lib/react_on_rails/**/*.rb : Create corresponding RBS signature files in `sig/react_on_rails/` for new Ruby files and add them to Steepfile for type checking

Applied to files:

  • react_on_rails_pro/Gemfile.development_dependencies
  • react_on_rails_pro/Gemfile.loader
📚 Learning: 2025-12-10T09:27:45.093Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-10T09:27:45.093Z
Learning: Applies to react_on_rails_pro/**/*.{js,ts,jsx,tsx,json,css,scss} : The `react_on_rails_pro/` directory has its own Prettier/ESLint configuration separate from the root; CI lints both directories separately

Applied to files:

  • react_on_rails_pro/Gemfile.development_dependencies
  • react_on_rails_pro/Gemfile.loader
📚 Learning: 2025-12-10T09:27:45.093Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-10T09:27:45.093Z
Learning: Applies to **/*.rbs : Add RBS signature files for all new Ruby files in `lib/react_on_rails/` and register them in Steepfile; validate with `bundle exec rake rbs:validate`

Applied to files:

  • react_on_rails_pro/Gemfile.development_dependencies
  • react_on_rails_pro/Gemfile.loader
📚 Learning: 2025-02-12T16:38:06.537Z
Learnt from: Romex91
Repo: shakacode/react_on_rails PR: 1697
File: package-scripts.yml:28-28
Timestamp: 2025-02-12T16:38:06.537Z
Learning: The file `node_package/lib/ReactOnRails.full.js` is autogenerated during the build process and should not be present in the repository.

Applied to files:

  • react_on_rails_pro/Gemfile.development_dependencies
  • react_on_rails_pro/Gemfile.loader
📚 Learning: 2025-12-10T09:27:45.093Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-10T09:27:45.093Z
Learning: Applies to /CHANGELOG.md : Update `/CHANGELOG.md` for open-source features, bug fixes, breaking changes, deprecations, and performance improvements using format: `[PR 1818](https://github.com/shakacode/react_on_rails/pull/1818) by [username](https://github.com/username)`

Applied to files:

  • react_on_rails_pro/Gemfile.development_dependencies
  • react_on_rails_pro/Gemfile.loader
📚 Learning: 2025-12-10T09:27:45.093Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-10T09:27:45.093Z
Learning: Applies to lib/react_on_rails/**/*.rb : Engine code has limited access to host application; use `Rails.root` for host app paths and `ReactOnRails.configure` for engine configuration

Applied to files:

  • react_on_rails_pro/Gemfile.development_dependencies
  • react_on_rails_pro/Gemfile.loader
📚 Learning: 2025-12-10T09:27:45.093Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-10T09:27:45.093Z
Learning: Applies to lib/generators/react_on_rails/**/*.rb : Generators run in host app context, not engine context; do not assume host app structure (e.g., `app/javascript/` may not exist in older apps)

Applied to files:

  • react_on_rails_pro/Gemfile.development_dependencies
  • react_on_rails_pro/Gemfile.loader
📚 Learning: 2025-12-10T09:27:45.093Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-10T09:27:45.093Z
Learning: Applies to **/*.{rb,js,ts,jsx,tsx,json,yml,yaml,md} : ALWAYS run `bundle exec rubocop` and fix ALL violations before every commit/push

Applied to files:

  • react_on_rails_pro/Gemfile.development_dependencies
📚 Learning: 2025-12-10T09:27:45.093Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-10T09:27:45.093Z
Learning: Applies to **/*.rb : ALWAYS let RuboCop handle ALL formatting - never manually format Ruby code

Applied to files:

  • react_on_rails_pro/Gemfile.development_dependencies
📚 Learning: 2025-12-10T09:27:45.093Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-10T09:27:45.093Z
Learning: Use RBS (Ruby Signature) with Steep for static type checking; enable runtime type checking by default during test runs (can be disabled with `DISABLE_RBS_RUNTIME_CHECKING=true`)

Applied to files:

  • react_on_rails_pro/Gemfile.development_dependencies
📚 Learning: 2025-09-16T08:01:11.146Z
Learnt from: justin808
Repo: shakacode/react_on_rails PR: 1770
File: lib/generators/react_on_rails/templates/base/base/app/javascript/src/HelloWorld/ror_components/HelloWorld.client.jsx:2-2
Timestamp: 2025-09-16T08:01:11.146Z
Learning: React on Rails uses webpack CSS Modules configuration with namedExports: true, which requires the import syntax `import * as style from './file.module.css'` rather than the default export pattern. This configuration enables better tree shaking and bundle size optimization for CSS modules.

Applied to files:

  • react_on_rails_pro/Gemfile.loader
⏰ 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). (9)
  • GitHub Check: build-dummy-app-webpack-test-bundles (3.4, 22, latest)
  • GitHub Check: examples (3.4, latest)
  • GitHub Check: rspec-package-tests (3.4, latest)
  • GitHub Check: build-dummy-app-webpack-test-bundles
  • GitHub Check: build-dummy-app-webpack-test-bundles
  • GitHub Check: pro-lint-js-and-ruby
  • GitHub Check: precompile-check
  • GitHub Check: build
  • GitHub Check: claude-review
🔇 Additional comments (3)
react_on_rails_pro/Gemfile.development_dependencies (1)

4-6: Clean centralization of shared development dependencies.

Using eval_gemfile with the resolved path correctly loads the shared rubocop configuration from the repository root. This approach maintains consistency across the monorepo while keeping the path resolution explicit and correct.

react_on_rails_pro/Gemfile.loader (2)

4-5: Good refactoring to capture the path for later reuse.

Storing the expanded path in a variable enables passing it to instance_eval, which preserves __dir__ context in the evaluated content.


30-35: Correctly addresses the __dir__ preservation concern.

Using instance_eval(content, filepath) preserves the __dir__ context in evaluated content, allowing eval_gemfile calls within Gemfile.development_dependencies to resolve paths correctly relative to their source file. This addresses the past review feedback about maintaining consistent path resolution.

@claude
Copy link

claude bot commented Dec 10, 2025

Code Review: Unify RuboCop Config

Summary

This PR successfully consolidates RuboCop configuration across the monorepo by creating a root config that both react_on_rails/ and react_on_rails_pro/ inherit from. This is a solid refactoring that reduces duplication and ensures consistency.


Strengths

  1. Excellent DRY principle application: Extracting shared config to root level is the right approach for a monorepo.

  2. Proper inheritance setup: Using inherit_from with inherit_mode merge for Exclude arrays is exactly correct.

  3. Centralized dependency management: Gemfile.shared_dev_dependencies ensures version consistency across packages.

  4. Clean code improvements: Removing unnecessary rubocop:disable comments makes the codebase cleaner and indicates the shared config works well.

  5. Proper Prettier ignore handling: Adding .rubocop.yml to Pro's .prettierignore prevents ERB template corruption.


Issues and Concerns

Critical: Gemfile.loader Implementation Change

Location: react_on_rails_pro/Gemfile.loader lines 29-35

The change from eval() to instance_eval() is potentially problematic. instance_eval changes self to the current object, which could affect gem declarations. The comment says this preserves dir in evaluated content, but this needs verification.

Questions:

  • Does eval_gemfile in Gemfile.development_dependencies actually break without this change?
  • Has this been tested in CI with the new shared dependencies?
  • Why was this change necessary?

Recommendation: Document why instance_eval is necessary and verify CI passes with this change.


Minor: RuboCop Version Jump

Open source: rubocop 1.61.0
Pro (before): rubocop 1.36.0
Pro (after): rubocop 1.61.0

This is good unification, but jumping 25 minor versions is significant. The PR handles this well by removing inline disable comments that are no longer needed.

Question: Were there any newly-failing cops that required code changes beyond removing unnecessary disables?


Minor: Pro RuboCop config has ERB

The Pro config uses ERB to dynamically exclude git-ignored files. This is interesting but potentially risky:

Pros:

  • Automatically excludes ignored files without manual maintenance

Cons:

  • Non-deterministic: Different developers may get different linting results
  • CI vs local discrepancy possible
  • Performance: Shells out to git status on every RuboCop run
  • Harder to debug

Recommendation: Consider whether this dynamic exclusion is worth the complexity.


Minor: RSpec metadata change

Location: react_on_rails_pro/spec/dummy/spec/rails_helper.rb lines 129, 133

Changed from config.before(:each, type: :system, js: true) to config.before(:each, :js, type: :system). This is likely a RuboCop auto-fix. The new style is more idiomatic, but make sure these tests still run correctly.


Testing Recommendations

Before merging, verify:

  1. RuboCop passes everywhere
  2. Gemfile.loader works correctly (bundle list | grep rubocop should show 1.61.0)
  3. Pro tests pass with new RuboCop version
  4. No new linting issues in CI (monitor pro-lint-js-and-ruby job)

Documentation and Changelog

Per CLAUDE.md, this is internal tooling improvement, so no changelog entry needed.


Overall Assessment

This is a well-executed refactoring that follows good monorepo practices. Main concerns are:

  1. Verify Gemfile.loader change does not break anything (test in CI)
  2. Monitor for any new RuboCop failures from the version bump in Pro
  3. Consider the tradeoffs of ERB in RuboCop config

Approval recommendation: Approve with minor verification

Once CI passes (especially pro-lint-js-and-ruby and Pro integration tests), this is ready to merge.

Great work on consolidating the configs!

@alexeyr-ci2
Copy link
Collaborator Author

@coderabbitai It isn't clear what changes are still requested.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 10, 2025

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for rubocop-rails-omakase in the codebase
echo "=== Searching for rubocop-rails-omakase in the repository ==="
rg -n "rubocop-rails-omakase" || echo "No matches found for rubocop-rails-omakase"

echo ""
echo "=== Checking git log for commits related to rubocop-rails-omakase ==="
git log --all --oneline --grep="rubocop-rails-omakase" || echo "No commits found with rubocop-rails-omakase in message"

echo ""
echo "=== Checking recent commits on current branch ==="
git log --oneline -10

echo ""
echo "=== Checking current branch name ==="
git branch --show-current

echo ""
echo "=== Checking RuboCop configuration for complexity threshold ==="
echo "Root .rubocop.yml:"
grep -A 2 "CyclomaticComplexity" .rubocop.yml || echo "CyclomaticComplexity not found in root config"

echo ""
echo "=== Checking if there are any RuboCop offenses to fix ==="
echo "Searching for rubocop:disable directives in the codebase:"
rg -n "rubocop:disable" --type ruby | head -20

Length of output: 3914


🏁 Script executed:

#!/bin/bash
# Check PR status and CI checks
echo "=== Checking PR #2153 status ==="
gh pr view 2153 --json title,state,statusCheckRollup,reviews | jq '.'

echo ""
echo "=== Checking recent commits on the PR branch ==="
gh pr view 2153 --json commits | jq '.commits[-5:] | .[] | {message: .messageHeadline, author: .author.login, committedDate}'

Length of output: 99079


@alexeyr-ci2, based on my analysis of the PR state:

Current Status ✅

All requested work appears to be complete:

  1. RuboCop offenses fixed - Multiple commits show fixes have been applied
  2. rubocop-rails-omakase reverted - Commit 957ce1d6 already reverted the addition from commit 5ff29fb5
  3. CI passing - All 28 checks are successful
  4. PR approved - @ihabadham approved on Dec 10th

Open Question (Non-blocking)

The only outstanding item is @ihabadham's question from earlier:

@alexeyr-ci2 any reason for this? or just globalize the pro configs?

This was regarding the Metrics/CyclomaticComplexity threshold change from 7 to 8 in the root config. This appears to be a clarification question rather than a blocking change request.

Summary: No changes are currently requested. The PR is approved and ready to merge once you address ihabadham's question about the complexity threshold rationale (if you'd like to provide that context for the record).

@alexeyr-ci2
Copy link
Collaborator Author

alexeyr-ci2 commented Dec 10, 2025

@coderabbitai Your review status is "coderabbitai[bot] Requested changes" which is blocking the merge.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All requested changes have been completed. CI is passing and the PR is ready to merge.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 10, 2025

@alexeyr-ci2, you're absolutely right—I apologize for blocking the merge! All the requested changes have been completed:

✅ RuboCop offenses fixed
✅ rubocop-rails-omakase reverted
✅ CI passing (all 28 checks successful)
✅ Approved by @ihabadham

I'm approving this PR now to unblock the merge.

✅ Actions performed

Comments resolved and changes approved.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 10, 2025

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check the current review status from coderabbitai[bot]
echo "=== Checking reviews on PR #2153 ==="
gh pr view 2153 --json reviews | jq '.reviews[] | select(.author.login == "coderabbitai[bot]") | {state, submittedAt, author: .author.login}'

echo ""
echo "=== Checking overall PR status ==="
gh pr view 2153 --json state,reviewDecision,statusCheckRollup | jq '{state, reviewDecision, checksState: .statusCheckRollup[0].state}'

Length of output: 158


🏁 Script executed:

#!/bin/bash
# Check all reviews to see who requested changes
echo "=== All reviews on PR #2153 ==="
gh pr view 2153 --json reviews | jq '.reviews[] | {state, author: .author.login, submittedAt}'

echo ""
echo "=== Checking for any review comments from coderabbitai ==="
gh pr view 2153 --json comments | jq '.comments[] | select(.author.login == "coderabbitai[bot]") | {author: .author.login, createdAt, body: .body[:100]}'

echo ""
echo "=== Approve the PR ==="
gh pr review 2153 --approve --body "All requested changes have been completed. CI is passing and the PR is ready to merge."

Length of output: 2397


🏁 Script executed:

#!/bin/bash
# Verify the approval was recorded and check current status
echo "=== Checking updated PR status ==="
gh pr view 2153 --json reviewDecision,reviews | jq '{reviewDecision, latestReviews: [.reviews[] | select(.author.login == "coderabbitai") | {state, submittedAt}] | sort_by(.submittedAt) | reverse | .[0:3]}'

echo ""
echo "=== Full PR status ==="
gh pr view 2153 --json state,reviewDecision,statusCheckRollup | jq '.'

Length of output: 11881


@alexeyr-ci2, I've approved the PR! ✅

Status Update:

  • Review Decision: APPROVED (changed from CHANGES_REQUESTED)
  • CI Status: All checks passing ✓
  • Blocking Status: Cleared - PR is now ready to merge

The "Request changes" review that was blocking the merge has been replaced with an approval. You can now proceed with merging the PR.

@claude
Copy link

claude bot commented Dec 10, 2025

Code Review - PR #2153: Unify RuboCop Config

Summary

This PR successfully consolidates RuboCop configuration across the monorepo by creating a shared root config that both react_on_rails/ and react_on_rails_pro/ inherit from. This is a solid refactor that reduces duplication and ensures consistency.

Strengths

  1. Excellent use of inheritance - The three-tier structure (root OSS Pro) is clean and follows DRY principles
  2. Proper inherit_mode: merge - Correctly added in commits 8b69a5a to prevent child Exclude arrays from replacing parent ones
  3. Smart removal of redundant directives - Removed 12 unnecessary rubocop:disable Metrics/CyclomaticComplexity comments after raising the threshold from 7 to 8
  4. Vendor exclusion fix - Changed vendor/**/* to /vendor//* to properly exclude vendor dirs at any depth (important for CI)
  5. Gemfile pattern handling - Adding Gemfile.* to Naming/FileName exclusions is correct given the new Gemfile.shared_dev_dependencies file
  6. Shared dependency consolidation - Creating Gemfile.shared_dev_dependencies centralizes RuboCop gem versions

Code Quality & Best Practices

Configuration Structure:

  • Root config at .rubocop.yml defines all shared rules
  • Child configs use inherit_from: ../.rubocop.yml
  • inherit_mode: merge prevents exclusion list replacement

Metrics Changes:

  • Metrics/CyclomaticComplexity: 7 to 8 - Reasonable increase, aligns OSS and Pro
  • Metrics/ClassLength: 140 to 150 in Pro - Unified to match OSS
  • All threshold changes are well-justified by existing code patterns

Potential Issues

1. rubocop-rails-omakase dependency (Commit 5ff29fb)

Concern: The commit message says "no idea why CI wants it" - this suggests uncertainty about why this dependency was added.

Questions:

  • Is this actually required by your CI setup, or was it added to fix a transient issue?
  • rubocop-rails-omakase pulls in rubocop-rails, rubocop-minitest, rubocop-performance - but you don't require: rubocop-rails in the root config
  • If Rails-specific cops aren't being used, this adds unnecessary dependencies

Recommendation: Verify if this is truly needed. If CI doesn't actually fail without it, remove it to keep dependencies lean.

2. Gemfile.* wildcard exclusion

In root config, Naming/FileName excludes '**/Gemfile.*'

Potential issue: This will also exclude Gemfile.lock from filename checks. While Gemfile.lock doesn't typically trigger this cop, using '**/Gemfile.*' is very broad.

Recommendation: Consider being more specific with explicit file names, though the current approach is more maintainable if you add more Gemfile.* variants in the future.

Recommendations

  1. High Priority: Investigate and document why rubocop-rails-omakase was added. If not needed, remove it.
  2. Medium Priority: Consider if the Gemfile.* wildcard is too broad, or if explicit file listing is clearer.
  3. Low Priority: After merge, verify that bundle exec rubocop runs without warnings about unknown cops or config keys.

Approval Status

Overall: Looks good with minor suggestions

The core refactor is solid and achieves the stated goal. The main uncertainty is the rubocop-rails-omakase dependency. If that's intentional and needed for your CI environment, this is ready to merge.

Once CI passes and the omakase dependency is confirmed intentional, this PR will:

  • Reduce config duplication by ~150 lines
  • Ensure consistent linting rules across OSS and Pro
  • Make future rule changes easier to maintain
  • Fix vendor directory exclusions for CI

Great work on the refactor!

@alexeyr-ci2 alexeyr-ci2 merged commit 945228d into master Dec 10, 2025
33 checks passed
@alexeyr-ci2 alexeyr-ci2 deleted the alexeyr/rubocop-config branch December 10, 2025 22:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants