Skip to content

Conversation

ihabadham
Copy link
Contributor

@ihabadham ihabadham commented Sep 29, 2025

Summary

Fixes an optimization gap in the RSpec helper where server bundle staleness was not detected when using private SSR directories (introduced in PR #1798).

  • Issue: Default webpack_generated_files: ['manifest.json'] configuration only monitored client assets, missing server bundle changes in private ssr-generated/ directory
  • Impact: Tests could run with stale server-side code, leading to incorrect test results
  • Solution: Enhanced ensure_webpack_generated_files_exists to automatically include server bundles and other critical files in monitoring list

Root Cause

PR #1798 moved server bundles to private directories for security, but the RSpec helper optimization continued monitoring only manifest.json by default. This created a gap where:

  1. Server bundle changes in ssr-generated/server-bundle.js
  2. Client assets remain fresh in public/packs-test/manifest.json
  3. RSpec helper reports "no rebuild needed" ❌
  4. Tests run with stale server-side code

Why this worked before: Prior to PR #1798, both client and server bundles were co-located in the same public/packs/ directory, so the RSpec helper's fallback logic would detect server bundle staleness even when only monitoring manifest.json.

Fix Details

Before:

def ensure_webpack_generated_files_exists
  return unless webpack_generated_files.empty?  # ❌ Never runs with default config
  # ...
end

After:

def ensure_webpack_generated_files_exists
  all_required_files = [
    "manifest.json",
    server_bundle_js_file,
    rsc_bundle_js_file,
    react_client_manifest_file,
    react_server_client_manifest_file
  ].compact_blank

  if webpack_generated_files.empty?
    self.webpack_generated_files = all_required_files
  else
    missing_files = all_required_files.reject { |file| webpack_generated_files.include?(file) }
    self.webpack_generated_files += missing_files if missing_files.any?
  end
end

Testing

  • ✅ Comprehensive test coverage added for all scenarios
  • ✅ Verified fix resolves gap with test apps
  • ✅ Backward compatibility maintained
  • ✅ Works across different directory configurations

Test plan

  • RSpec helper correctly detects server bundle staleness with default config
  • Cross-directory monitoring works (client in public/, server in ssr-generated/)
  • Existing configurations continue working unchanged
  • Edge cases handled (nil values, custom configurations)

Fixes #1822

🤖 Generated with Claude Code


This change is Reviewable

Summary by CodeRabbit

  • Bug Fixes

    • More reliable auto-inclusion of required Webpack assets without duplicates.
    • Preserves custom-configured files while adding only missing essentials.
    • Correctly handles absent server bundle or manifests (no nil entries added).
    • Includes RSC bundle when configured.
    • Improves server bundle monitoring behavior for faster RSpec runs.
  • Tests

    • Added comprehensive coverage for asset inclusion, duplication prevention, custom configurations, RSC support, and monitoring across multiple directory setups.

When server bundles are configured for private directories but
webpack_generated_files is set to default ['manifest.json'], the server
bundle was not being monitored for staleness during RSpec test runs.

This change enhances ensure_webpack_generated_files_exists to automatically
include server bundles and other configured bundle files in the monitoring
list.

Fixes #1822
Tests cover various scenarios including:
- Auto-inclusion with default manifest.json configuration
- Empty configuration population
- Duplicate prevention
- Custom file preservation
- Edge cases with nil values
- RSC bundle support
- Server bundle monitoring for RSpec optimization

These tests prevent regression of the optimization gap fix and ensure
the Smart Auto-Inclusion logic works correctly across different
configuration scenarios.
Copy link
Contributor

coderabbitai bot commented Sep 29, 2025

Walkthrough

Refactors configuration to always compute required webpack-generated files and to populate or extend the webpack_generated_files list accordingly. Adds a comprehensive spec suite covering empty/prepopulated lists, optional bundles/manifests, nil handling, and RSpec server-bundle monitoring across directory variants.

Changes

Cohort / File(s) Summary
Configuration logic
lib/react_on_rails/configuration.rb
Reworks ensure_webpack_generated_files_exists to build a full required file set, initialize when empty, or append only missing files when prepopulated. No changes to signatures or other config logic.
Tests for configuration
spec/react_on_rails/configuration_spec.rb
Adds tests validating population behavior with default manifest, pre-existing entries, custom files, nil server/react manifests, inclusion of RSC bundle, and RSpec monitoring of server-bundle across paths.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Test/Runtime as Caller
  participant Config as Configuration

  Note over Caller,Config: Ensuring webpack-generated files list

  Caller->>Config: ensure_webpack_generated_files_exists()
  Config->>Config: Build all_required_files (server bundle, RSC, manifests)
  alt webpack_generated_files empty
    Config->>Config: Set webpack_generated_files = all_required_files
  else prepopulated
    Config->>Config: Compute missing_files = all_required_files - existing
    alt missing_files present
      Config->>Config: Append missing_files (no duplicates)
    else none missing
      Config->>Config: No changes
    end
  end
  Config-->>Caller: Updated webpack_generated_files
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Suggested labels

bug

Suggested reviewers

  • justin808
  • AbanoubGhadban

Poem

A nibble of code, a hop through the trails,
I gathered the bundles and followed the rails.
No dupes in my basket, just files that belong—
Manifest whispers, “you’re doing it strong.”
With specs in the meadow, I thump in delight—
All deps accounted, the builds are just right. 🐇✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The pull request title clearly and concisely describes the primary change of addressing an RSpec helper optimization gap for private SSR directories without unnecessary detail or noise.
Linked Issues Check ✅ Passed The updates to ensure_webpack_generated_files_exists and the accompanying comprehensive tests directly address verifying RSpec helper behavior with private SSR directory server bundles and ensure detection of stale bundles, fully satisfying the objectives outlined in issue #1822.
Out of Scope Changes Check ✅ Passed All modifications are confined to the configuration method and its tests related to webpack_generated_files and do not introduce unrelated functionality, keeping the changes squarely within the scope defined by the linked issue.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/webpack-generated-files-server-bundle

Tip

👮 Agentic pre-merge checks are now available in preview!

Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.

  • Built-in checks – Quickly apply ready-made checks to enforce title conventions, require pull request descriptions that follow templates, validate linked issues for compliance, and more.
  • Custom agentic checks – Define your own rules using CodeRabbit’s advanced agentic capabilities to enforce organization-specific policies and workflows. For example, you can instruct CodeRabbit’s agent to verify that API documentation is updated whenever API schema files are modified in a PR. Note: Upto 5 custom checks are currently allowed during the preview period. Pricing for this feature will be announced in a few weeks.

Please see the documentation for more information.

Example:

reviews:
  pre_merge_checks:
    custom_checks:
      - name: "Undocumented Breaking Changes"
        mode: "warning"
        instructions: |
          Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).

Please share your feedback with us on this Discord post.


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.

@coderabbitai coderabbitai bot added the bug label Sep 29, 2025
Copy link

claude bot commented Sep 29, 2025

Code Review for PR #1838: Fix RSpec helper optimization gap with private SSR directories

Summary

This PR successfully addresses a critical gap in the RSpec helper optimization that emerged after PR #1798's security improvements. The fix ensures server bundles in private directories are properly monitored during test runs, preventing tests from running with stale server-side code.

Strengths

  1. Root Cause Analysis: Excellent identification of the issue - the default webpack_generated_files: ['manifest.json'] configuration was insufficient after server bundles moved to private directories.

  2. Backward Compatibility: The solution maintains full backward compatibility while fixing the gap:

    • Existing configurations continue working unchanged
    • Custom configurations are preserved and augmented
    • No breaking changes for current users
  3. Comprehensive Test Coverage: Outstanding test suite covering:

    • Default configuration scenarios
    • Custom file configurations
    • Edge cases (nil values, RSC bundles)
    • Cross-directory monitoring scenarios
    • Deduplication logic
  4. Clean Implementation: The refactored ensure_webpack_generated_files_exists method is more robust and maintainable than the previous version.

🎯 Code Quality

The implementation follows Ruby best practices:

  • Proper use of compact_blank to handle nil values
  • Efficient deduplication logic using reject and conditional appending
  • Clear variable naming (all_required_files, missing_files)
  • Maintains single responsibility principle

Security Considerations

The fix properly maintains the security improvements from PR #1798:

  • Server bundles remain in private directories
  • No exposure of sensitive server-side code to public directories
  • Monitoring logic doesn't compromise the security architecture

📊 Performance

  • Minimal overhead: The additional file checks during test setup have negligible performance impact
  • Smart deduplication: Prevents redundant file monitoring
  • Efficient array operations: Uses appropriate Ruby methods for filtering and appending

🔍 Potential Enhancements (Optional for future PRs)

  1. Logging: Consider adding debug logging when files are automatically added to webpack_generated_files to help developers understand what's being monitored

  2. Documentation: While the PR description is excellent, consider adding a comment in the code explaining why this automatic inclusion is necessary

Testing Verification

The test suite thoroughly validates:

  • Server bundle detection with default configuration ✓
  • Cross-directory monitoring (client in public/, server in ssr-generated/) ✓
  • Deduplication of entries ✓
  • Preservation of custom configurations ✓
  • Handling of nil/unconfigured values ✓

🎖️ Overall Assessment

APPROVED - This is a well-crafted fix that elegantly solves the optimization gap without introducing complexity or breaking changes. The comprehensive test coverage ensures reliability, and the implementation maintains the security improvements from PR #1798.

The PR demonstrates excellent engineering practices:

  • Clear problem identification
  • Minimal, focused solution
  • Comprehensive testing
  • Backward compatibility
  • Security awareness

Great work on identifying and fixing this subtle but important issue! 🚀

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

🧹 Nitpick comments (2)
lib/react_on_rails/configuration.rb (1)

323-336: Make list-building nil-safe and dedupe via set-union; also simplify control flow

Current code raises if webpack_generated_files is nil, and duplicates persist if pre-seeded by users. Prefer treating nil as empty, removing duplicates, and appending missing in one step.

Apply:

-      all_required_files = [
-        "manifest.json",
-        server_bundle_js_file,
-        rsc_bundle_js_file,
-        react_client_manifest_file,
-        react_server_client_manifest_file
-      ].compact_blank
-
-      if webpack_generated_files.empty?
-        self.webpack_generated_files = all_required_files
-      else
-        missing_files = all_required_files.reject { |file| webpack_generated_files.include?(file) }
-        self.webpack_generated_files += missing_files if missing_files.any?
-      end
+      required = [
+        "manifest.json",
+        server_bundle_js_file,
+        rsc_bundle_js_file,
+        react_client_manifest_file,
+        react_server_client_manifest_file
+      ].compact_blank
+
+      current = Array(webpack_generated_files)
+      self.webpack_generated_files =
+        if current.blank?
+          required
+        else
+          current | required
+        end
spec/react_on_rails/configuration_spec.rb (1)

528-673: Strong coverage of required-file population; add two edge tests

The scenarios look solid and align with the new behavior. Consider adding:

  • A case where webpack_generated_files is nil (ensure nil-safety).
  • A case where webpack_generated_files contains duplicates (ensure de-dup).

Example additions:

+      context "when webpack_generated_files is nil" do
+        it "treats nil as empty and populates required files" do
+          config.webpack_generated_files = nil
+          config.server_bundle_js_file = "server-bundle.js"
+          config.send(:ensure_webpack_generated_files_exists)
+          expect(config.webpack_generated_files).to eq(%w[
+            manifest.json
+            server-bundle.js
+            react-client-manifest.json
+            react-server-client-manifest.json
+          ])
+        end
+      end
+
+      context "when webpack_generated_files has duplicates" do
+        it "does not keep duplicate entries after ensuring required files" do
+          config.webpack_generated_files = %w[manifest.json manifest.json server-bundle.js]
+          config.send(:ensure_webpack_generated_files_exists)
+          expect(config.webpack_generated_files.count("manifest.json")).to eq(1)
+        end
+      end
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e4a9a64 and 7bfe46b.

📒 Files selected for processing (2)
  • lib/react_on_rails/configuration.rb (1 hunks)
  • spec/react_on_rails/configuration_spec.rb (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
{Gemfile,Rakefile,config.ru,**/*.{rb,rake,gemspec,ru}}

📄 CodeRabbit inference engine (CLAUDE.md)

{Gemfile,Rakefile,config.ru,**/*.{rb,rake,gemspec,ru}}: All Ruby code must pass RuboCop with zero offenses before commit/push
RuboCop is the sole authority for Ruby file formatting; never manually format Ruby files

Files:

  • spec/react_on_rails/configuration_spec.rb
  • lib/react_on_rails/configuration.rb
🧠 Learnings (2)
📓 Common learnings
Learnt from: justin808
PR: shakacode/react_on_rails#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.
📚 Learning: 2025-09-16T08:01:11.146Z
Learnt from: justin808
PR: shakacode/react_on_rails#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:

  • lib/react_on_rails/configuration.rb
🧬 Code graph analysis (1)
spec/react_on_rails/configuration_spec.rb (1)
lib/react_on_rails/test_helper/webpack_assets_status_checker.rb (1)
  • include (11-101)
⏰ 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.2, latest)
  • GitHub Check: rspec-package-tests (3.4, latest)
  • GitHub Check: rspec-package-tests (3.2, minimum)
  • GitHub Check: rspec-package-tests (3.4, minimum)
  • GitHub Check: claude-review
  • GitHub Check: build
  • GitHub Check: build-dummy-app-webpack-test-bundles (3.2, 20)
  • GitHub Check: build-and-test

Comment on lines +323 to +330
all_required_files = [
"manifest.json",
server_bundle_js_file,
rsc_bundle_js_file,
react_client_manifest_file,
react_server_client_manifest_file
].compact_blank

Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

🧩 Analysis chain

Confirm ActiveSupport availability for compact_blank (or require the extension)

Array#compact_blank is from ActiveSupport core extensions. If the gem supports older Rails/AS versions, this will break unless the extension is loaded.

Run to verify dependency floor and usage:


🏁 Script executed:

#!/bin/bash
# Check declared minimum Rails/AS and usages of compact_blank
fd -a '*.gemspec' | xargs -I{} rg -n 'add_(runtime_)?dependency.*(rails|activesupport)' {}
rg -n 'compact_blank' -g '!**/tmp/**'

Length of output: 437


🏁 Script executed:

#!/bin/bash
# Correct search for gemspec dependencies on rails/activesupport
echo "Searching gemspec dependencies..."
fd --extension gemspec --exec rg -n "add_(runtime_)?dependency.*(rails|activesupport)" {}

echo "Searching for .compact_blank usage..."
rg -nP "\.compact_blank" -g "!**/tmp/**"

echo "Searching for explicit requires of ActiveSupport core extensions..."
rg -n "require.*active_support/core_ext" -g "!**/tmp/**"

Length of output: 537


#!/bin/bash
echo "Locate `.compact_blank` in configuration:"
rg --no-ignore -nP "\.compact_blank" lib/react_on_rails/configuration.rb

echo -e "\nInspect top of configuration file for requires:"
sed -n '1,50p' lib/react_on_rails/configuration.rb

echo -e "\nSearch for any ActiveSupport core_ext requires across lib/:"
rg --no-ignore -n "require .*active_support/core_ext" -g "lib/**"

Require ActiveSupport or replace compact_blank in configuration.rb
Ensure compact_blank is available on Rails <6.1 by adding

require 'active_support/core_ext/enumerable'

at the top of lib/react_on_rails/configuration.rb—or replace .compact_blank with .reject(&:blank?) to maintain compatibility with Rails 5.2–6.0.

🤖 Prompt for AI Agents
In lib/react_on_rails/configuration.rb around lines 323 to 330 the call to
.compact_blank may not exist on Rails < 6.1; either add a require for
ActiveSupport by adding require 'active_support/core_ext/enumerable' at the top
of the file, or replace .compact_blank with .reject(&:blank?) on that
all_required_files array to restore compatibility with Rails 5.2–6.0.

@ihabadham ihabadham requested a review from justin808 September 29, 2025 16:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Need to test out rspec helper with new private ssr files directory
1 participant