Skip to content

Conversation

@ihabadham
Copy link
Collaborator

@ihabadham ihabadham commented Jan 4, 2026

Summary

Fixes #2278

When Shakapacker was already installed before running the React on Rails generator, the precompile_hook setting in shakapacker.yml was not being configured, even though the bin/shakapacker-precompile-hook script was copied correctly.

Impact: This caused deployment failures because the hook wouldn't run during rails assets:precompile, resulting in missing component bundles in production.

Changes

  • Restructured copy_packer_config to always call configure_precompile_hook_in_shakapacker at the end, regardless of which code path is taken
  • Added configure_precompile_hook_in_shakapacker method that uses gsub_file to surgically update the YAML without destroying comments
  • Bonus fix: Changed configure_rspack_in_shakapacker to use gsub_file instead of YAML.dump, which was destroying all comments and file structure
  • Added specs to verify precompile_hook configuration when Shakapacker is pre-installed

Why gsub_file instead of YAML.dump?

YAML.dump destroys the configuration file:

  • Removes ALL comments (critical documentation for users)
  • Flattens YAML anchors (&default, <<: *default) into duplicated content
  • Changes formatting and structure

Using Thor's gsub_file (following Rails/Shakapacker best practices) preserves comments and structure while making surgical updates.

Test plan

  • Added 3 new specs for the "when Shakapacker was just installed" scenario
  • Manually tested with fresh Rails app - precompile_hook now configured correctly
  • Verified comments and YAML structure are preserved
  • RuboCop passes

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • New Features

    • Added precompile hook configuration support for Shakapacker 9.0+
  • Improvements

    • Enhanced Shakapacker configuration installation to preserve existing comments and YAML structure
    • Improved handling of Rspack configuration updates during setup
    • Refined configuration file processing to maintain formatting during generation

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

Fixes #2278

When Shakapacker was already installed before running the React on Rails
generator, the precompile_hook setting in shakapacker.yml was not being
configured, even though the bin/shakapacker-precompile-hook script was
copied correctly. This caused deployment failures because the hook
wouldn't run during `rails assets:precompile`.

Changes:
- Restructured copy_packer_config to always call
  configure_precompile_hook_in_shakapacker at the end
- Added configure_precompile_hook_in_shakapacker method that uses
  gsub_file to surgically update the YAML without destroying comments
- Fixed configure_rspack_in_shakapacker to use gsub_file instead of
  YAML.dump, which was destroying all comments and file structure
- Added specs to verify precompile_hook configuration when Shakapacker
  is pre-installed

The fix uses Thor's gsub_file method (following Rails/Shakapacker best
practices) to preserve comments and YAML structure, unlike YAML.dump
which strips all comments and flattens anchor/alias references.

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

Co-Authored-By: Claude <noreply@anthropic.com>
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 4, 2026

Walkthrough

The PR adds a new method to configure the precompile_hook in shakapacker.yml during generator execution and modifies the packer config logic to template the configuration and apply both rspack and precompile_hook settings when Shakapacker is freshly installed, addressing issue #2278.

Changes

Cohort / File(s) Summary
Generator Implementation
react_on_rails/lib/generators/react_on_rails/base_generator.rb
Adds configure_precompile_hook_in_shakapacker method to insert precompile_hook configuration into shakapacker.yml for Shakapacker 9.0+. Modifies copy_packer_config to template the config when marker file exists and always apply both rspack and precompile_hook settings. Reworks configure_rspack_in_shakapacker to use gsub_file for in-place YAML modification while preserving structure.
Test Coverage
react_on_rails/spec/react_on_rails/generators/install_generator_spec.rb
Adds test context verifying precompile_hook configuration, YAML anchor/comment preservation, and marker file cleanup when Shakapacker is freshly installed by the generator.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

  • #2278: Generator doesn't configure precompile_hook in shakapacker.yml when Shakapacker is pre-installed — this PR directly addresses the issue by adding the configure_precompile_hook_in_shakapacker method and ensuring it's called during config initialization.

Possibly related PRs

Suggested labels

bug, review-needed

Suggested reviewers

  • justin808
  • alexeyr-ci2

Poem

🐰 A hook now hops where configs brew,
Shakapacker's precompile too!
With comments safe and markers gone,
The generator marches on—
One less path for bundles true! ✨

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 title clearly and concisely describes the main fix: configuring precompile_hook when Shakapacker is pre-installed, which aligns with the primary objective stated in the PR summary.
Linked Issues check ✅ Passed The PR fully addresses issue #2278 by implementing configure_precompile_hook_in_shakapacker method, updating copy_packer_config to always call it, modifying configure_rspack_in_shakapacker to use gsub_file, and adding comprehensive test coverage.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing the precompile_hook configuration issue: modifications to base_generator.rb and new test specs are focused on the stated objectives with no extraneous changes.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch ihabadham/fix/precompile-hook-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 Jan 4, 2026

PR Review - Code Quality Analysis

✅ Overall Assessment: EXCELLENT

This PR effectively fixes issue #2278 with a clean, well-tested solution. The code quality is high and follows best practices.


🎯 Strengths

1. Architecture & Design ⭐⭐⭐⭐⭐

  • Excellent fix location: Moving configure_precompile_hook_in_shakapacker to run unconditionally at the end of copy_packer_config ensures it handles ALL scenarios (fresh install, pre-installed, user declined overwrite)
  • Consistent pattern: The rspack configuration was also improved to use gsub_file instead of YAML.dump, maintaining consistency
  • Smart guard clauses: The method properly checks Shakapacker version (9.0+), file existence, and doesn't overwrite existing configurations

2. Regex Pattern Quality ⭐⭐⭐⭐⭐

# Excellent - captures indentation and handles optional quotes
/^(\s*)assets_bundler:\s*["']?webpack["']?\s*$/

# Good - specific to Shakapacker's default format
/^(\s*)#\s*precompile_hook:\s*~\s*$/

# Smart check - avoids overwriting existing active config
/^\s+precompile_hook:\s*['"][^'"]+['"]/)

3. Test Coverage ⭐⭐⭐⭐⭐

  • Comprehensive scenario testing: 3 new specs cover the pre-installed Shakapacker case
  • Tests verify preservation: YAML anchors, comments, and structure are all validated
  • Tests the actual bug: Ensures precompile_hook is configured when marker file exists

4. Comment Preservation ⭐⭐⭐⭐⭐

The shift from YAML.dump to gsub_file is brilliant:

  • Preserves user documentation in comments
  • Maintains YAML anchors (&default, <<: *default)
  • Keeps file formatting intact

🔍 Minor Suggestions for Consideration

1. Regex Edge Case: Indentation Consistency

The precompile_hook regex expects the comment to be at root level:

/^(\s*)#\s*precompile_hook:\s*~\s*$/

Potential issue: In Shakapacker's default config, this line appears INDENTED under default::

default: &default
  source_path: app/javascript
  # precompile_hook: ~

Question: Does your regex handle this indented case? The ^ anchor requires the line to start at column 0 (after optional whitespace), but the comment is actually indented with 2 spaces in real Shakapacker configs.

Test to verify:

content = "  # precompile_hook: ~"
content.match?(/^(\s*)#\s*precompile_hook:\s*~\s*$/)  # Should this match?

Recommendation: The regex DOES capture leading whitespace with (\s*), so it should work correctly. However, consider adding a test comment in your spec to confirm this works with indented lines as found in real Shakapacker configs.

2. Safety Check Documentation

The safety check is excellent:

return if content.match?(/^\s+precompile_hook:\s*['"][^'"]+['"]/)

But there's a subtle difference between the two regexes:

  • Replacement regex: ^(\s*)# - captures ANY whitespace (0 or more)
  • Safety check regex: ^\s+ - requires AT LEAST 1 whitespace

Question: Is this intentional? Should the safety check also use \s* to catch root-level configs?

Edge case: If someone has this at root level (unusual but possible):

precompile_hook: 'some-custom-hook'

Your safety check would MISS this (because it requires \s+, not \s*), and you might try to replace a non-existent commented line.

Recommendation: Change to ^\s*precompile_hook: for consistency, or document why root-level configs are intentionally not checked.

3. Informative Logging Enhancement

Current logging is good but could be more informative:

puts Rainbow("✅ Configured precompile_hook in shakapacker.yml").green

Suggestion: Add context about WHICH scenario happened:

if content.match?(/^(\s*)#\s*precompile_hook:\s*~\s*$/)
  puts Rainbow("✅ Configured precompile_hook in shakapacker.yml").green
else
  puts Rainbow("ℹ️  precompile_hook already configured in shakapacker.yml").blue
end

This helps users understand whether their config was modified.


🔒 Security & Safety

No security concerns

  • File operations are local to generator context
  • Regex patterns are specific and safe (no ReDoS risk)
  • Proper guard clauses prevent unintended overwrites

📊 Performance

Excellent performance characteristics

  • Early returns prevent unnecessary file operations
  • Single file read + gsub is optimal
  • No performance concerns

🧪 Test Coverage Assessment

Well Covered

  • Pre-installed Shakapacker scenario
  • Comment preservation
  • YAML anchor preservation
  • Marker file cleanup

💭 Consider Adding (Low Priority)

  1. Test with indented # precompile_hook: ~ to confirm regex works
  2. Test behavior when precompile_hook already exists (should skip)
  3. Test Shakapacker < 9.0 (should early return)
  4. Test when file doesn't exist (should early return)

Note: Some of these may be implicitly covered by existing integration tests.


📝 Code Style & Best Practices

Follows all CLAUDE.md guidelines:

  • Uses gsub_file for surgical updates (Rails best practice)
  • Preserves file structure and comments
  • Proper guard clauses
  • Clear method naming
  • Comprehensive test coverage

Matches project conventions:

  • Consistent with configure_rspack_in_shakapacker pattern
  • Uses Rainbow for colored output
  • Follows Thor generator patterns

🎯 Verdict

Status: ✅ APPROVE with minor suggestions

This PR is well-architected and thoroughly tested. The minor suggestions above are optional refinements, not blockers. The core fix is solid.

Recommendations before merge:

  1. ✅ Verify the indentation regex works with real Shakapacker configs (likely already does)
  2. ⚠️ Consider harmonizing the safety check regex (\s* vs \s+)
  3. 💡 Optional: Add more informative logging

Great work on this fix! The move to gsub_file for both rspack AND precompile_hook is a significant improvement that will prevent future issues.


Review completed by: Claude Code Agent 🤖

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/lib/generators/react_on_rails/base_generator.rb (1)

314-333: Implementation is correct; consider edge case handling.

The method correctly handles the standard Shakapacker 9.x config format. One minor consideration: if the # precompile_hook: ~ placeholder line doesn't exist in the file (custom configs or future Shakapacker versions), the gsub_file will silently do nothing.

This is likely acceptable since:

  1. The version guard limits this to Shakapacker 9.0+
  2. Custom configs may already have precompile_hook configured differently

If explicit feedback is desired when no substitution occurs, you could check the return value or content before/after.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 619cb78 and c72ae1e.

📒 Files selected for processing (2)
  • react_on_rails/lib/generators/react_on_rails/base_generator.rb
  • react_on_rails/spec/react_on_rails/generators/install_generator_spec.rb
🧰 Additional context used
📓 Path-based instructions (1)
**/*.rb

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.rb: Run bundle exec rubocop and fix ALL violations before every commit/push
Run bundle exec rubocop (MANDATORY) before every commit to ensure zero offenses

Files:

  • react_on_rails/lib/generators/react_on_rails/base_generator.rb
  • react_on_rails/spec/react_on_rails/generators/install_generator_spec.rb
🧠 Learnings (17)
📓 Common learnings
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-19T18:57:59.314Z
Learning: Shakapacker configuration should be tested by creating debug scripts in dummy app root (debug-webpack-rules.js, debug-webpack-with-config.js) to inspect webpack rules before committing configuration changes
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-19T18:57:59.314Z
Learning: Applies to {package.json,webpack.config.js,packages/*/package.json,react_on_rails_pro/package.json} : When resolving merge conflicts in build configuration files, verify file paths are correct by running `grep -r 'old/path' .` and test affected scripts like `pnpm run prepack` before continuing the merge
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-19T18:57:59.314Z
Learning: Applies to /{CHANGELOG.md,CHANGELOG_PRO.md} : Use format `[PR 1818](https://github.com/shakacode/react_on_rails/pull/1818) by [username](https://github.com/username)` in changelog entries (no hash in PR number)
📚 Learning: 2025-12-19T18:57:59.314Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-19T18:57:59.314Z
Learning: Applies to /CHANGELOG_PRO.md : Update `/CHANGELOG_PRO.md` for user-visible changes in the Pro-only react_on_rails_pro gem and npm packages

Applied to files:

  • react_on_rails/lib/generators/react_on_rails/base_generator.rb
📚 Learning: 2025-12-19T18:57:59.314Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-19T18:57:59.314Z
Learning: Applies to /CHANGELOG.md : Update `/CHANGELOG.md` for user-visible changes in the open-source react_on_rails gem and npm package (features, bug fixes, breaking changes, deprecations, performance improvements)

Applied to files:

  • react_on_rails/lib/generators/react_on_rails/base_generator.rb
📚 Learning: 2025-12-19T18:57:59.314Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-19T18:57:59.314Z
Learning: Applies to sig/react_on_rails/**/*.rbs : RBS signatures in `sig/react_on_rails/` should be added for new Ruby files in `lib/react_on_rails/`, included in Steepfile, validated with `bundle exec rake rbs:validate`, and type-checked with `bundle exec rake rbs:steep`

Applied to files:

  • react_on_rails/lib/generators/react_on_rails/base_generator.rb
  • react_on_rails/spec/react_on_rails/generators/install_generator_spec.rb
📚 Learning: 2025-12-19T18:57:59.314Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-19T18:57:59.314Z
Learning: Shakapacker configuration should be tested by creating debug scripts in dummy app root (debug-webpack-rules.js, debug-webpack-with-config.js) to inspect webpack rules before committing configuration changes

Applied to files:

  • react_on_rails/lib/generators/react_on_rails/base_generator.rb
  • react_on_rails/spec/react_on_rails/generators/install_generator_spec.rb
📚 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/lib/generators/react_on_rails/base_generator.rb
📚 Learning: 2025-07-08T05:57:29.630Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1745
File: node_package/src/RSCRequestTracker.ts:8-14
Timestamp: 2025-07-08T05:57:29.630Z
Learning: The global `generateRSCPayload` function in React on Rails Pro (RORP) is provided by the framework during rendering requests, not implemented in application code. The `declare global` statements are used to document the expected interface that RORP will inject at runtime.

Applied to files:

  • react_on_rails/lib/generators/react_on_rails/base_generator.rb
📚 Learning: 2025-04-26T21:55:55.874Z
Learnt from: alexeyr-ci2
Repo: shakacode/react_on_rails PR: 1732
File: spec/dummy/client/app-react16/startup/ReduxSharedStoreApp.client.jsx:40-44
Timestamp: 2025-04-26T21:55:55.874Z
Learning: In the react_on_rails project, files under `app-react16` directories are copied/moved to corresponding `/app` directories during the conversion process (removing the `-react16` suffix), which affects their relative import paths at runtime.

Applied to files:

  • react_on_rails/lib/generators/react_on_rails/base_generator.rb
📚 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/lib/generators/react_on_rails/base_generator.rb
📚 Learning: 2025-12-19T18:57:59.314Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-19T18:57:59.314Z
Learning: Applies to **/config/webpack/**/*.js : Use `namedExport: false` and `exportLocalsConvention: 'camelCase'` for CSS Modules loader options in Shakapacker 9.0+ if existing code uses `import styles from './file.module.css'` pattern

Applied to files:

  • react_on_rails/lib/generators/react_on_rails/base_generator.rb
📚 Learning: 2025-12-19T18:57:59.314Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-19T18:57:59.314Z
Learning: In IDE configuration, exclude these directories to prevent slowdowns: /coverage, /tmp, /gen-examples, /packages/react-on-rails/lib, /node_modules, /react_on_rails/spec/dummy/node_modules, /react_on_rails/spec/dummy/tmp, /react_on_rails/spec/dummy/app/assets/webpack, /react_on_rails/spec/dummy/log, /react_on_rails/spec/dummy/e2e/playwright-report, /react_on_rails/spec/dummy/test-results

Applied to files:

  • react_on_rails/lib/generators/react_on_rails/base_generator.rb
  • react_on_rails/spec/react_on_rails/generators/install_generator_spec.rb
📚 Learning: 2025-12-19T18:57:59.314Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-19T18:57:59.314Z
Learning: Applies to {package.json,webpack.config.js,packages/*/package.json,react_on_rails_pro/package.json} : When resolving merge conflicts in build configuration files, verify file paths are correct by running `grep -r 'old/path' .` and test affected scripts like `pnpm run prepack` before continuing the merge

Applied to files:

  • react_on_rails/lib/generators/react_on_rails/base_generator.rb
  • react_on_rails/spec/react_on_rails/generators/install_generator_spec.rb
📚 Learning: 2025-12-19T18:57:59.314Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-19T18:57:59.314Z
Learning: For infrastructure/config changes, perform comprehensive local testing including: finding all affected files with grep, testing build pipeline, running relevant specs, and linting everything before pushing

Applied to files:

  • react_on_rails/lib/generators/react_on_rails/base_generator.rb
📚 Learning: 2025-12-19T18:57:59.314Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-19T18:57:59.314Z
Learning: Applies to **/*.rb : Run `bundle exec rubocop` and fix ALL violations before every commit/push

Applied to files:

  • react_on_rails/lib/generators/react_on_rails/base_generator.rb
📚 Learning: 2025-12-19T18:57:59.314Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-19T18:57:59.314Z
Learning: Applies to react_on_rails/spec/dummy/e2e/playwright/e2e/**/*.spec.js : Use Playwright E2E tests in `react_on_rails/spec/dummy/e2e/playwright/` for React component integration testing. Tests automatically start Rails server on port 5017 before running

Applied to files:

  • react_on_rails/spec/react_on_rails/generators/install_generator_spec.rb
📚 Learning: 2025-12-19T18:57:59.314Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-19T18:57:59.314Z
Learning: Applies to react_on_rails/spec/dummy/e2e/playwright/app_commands/**/*.rb : Create custom Rails app commands in `e2e/playwright/app_commands/` directory with .rb files for reusable helpers in Playwright tests

Applied to files:

  • react_on_rails/spec/react_on_rails/generators/install_generator_spec.rb
📚 Learning: 2025-02-18T13:08:01.477Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1644
File: lib/react_on_rails/helper.rb:190-197
Timestamp: 2025-02-18T13:08:01.477Z
Learning: RSC support validation in React on Rails Pro is handled through a chain of validations:
1. Pro version check in `run_stream_inside_fiber`
2. RSC support check during pack generation via `ReactOnRailsPro.configuration.enable_rsc_support`
3. RSC support validation during component registration
This makes additional validation in the helper methods unnecessary.

Applied to files:

  • react_on_rails/spec/react_on_rails/generators/install_generator_spec.rb
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: rspec-package-tests (3.4, latest)
  • GitHub Check: examples (3.4, latest)
  • GitHub Check: Greptile Review
  • GitHub Check: claude-review
🔇 Additional comments (3)
react_on_rails/lib/generators/react_on_rails/base_generator.rb (2)

92-112: LGTM - Control flow correctly addresses the root cause of issue #2278.

The restructured logic ensures configure_precompile_hook_in_shakapacker is called unconditionally at the end, covering all scenarios: fresh Shakapacker install, pre-installed Shakapacker, or when user declines config overwrite.


299-312: Good refactor - gsub_file preserves YAML comments and anchors.

The regex correctly captures leading whitespace and handles both quoted ("webpack") and unquoted values, ensuring indentation is preserved in the replacement.

react_on_rails/spec/react_on_rails/generators/install_generator_spec.rb (1)

162-234: Comprehensive test coverage for issue #2278.

The test correctly simulates the scenario where Shakapacker was pre-installed by:

  1. Creating the marker file and realistic shakapacker.yml with commented placeholder
  2. Verifying the placeholder is replaced while preserving the example comment
  3. Confirming YAML anchors (&default, <<: *default) and comments are preserved
  4. Ensuring marker file cleanup

This provides good regression coverage for the fix.

@greptile-apps
Copy link

greptile-apps bot commented Jan 4, 2026

Greptile Summary

Fixed critical deployment issue where precompile_hook was not configured in shakapacker.yml when Shakapacker was pre-installed before running the React on Rails generator.

Key Changes:

  • Restructured copy_packer_config to ensure configure_precompile_hook_in_shakapacker is always called, regardless of whether Shakapacker was just installed or pre-existing
  • Added new configure_precompile_hook_in_shakapacker method that uses gsub_file to surgically replace the commented placeholder # precompile_hook: ~ with the active configuration
  • Improved configure_rspack_in_shakapacker to use gsub_file instead of YAML.dump, preserving comments and YAML anchors
  • Added comprehensive test coverage for the "Shakapacker pre-installed" scenario

Impact:
This fix ensures the bin/shakapacker-precompile-hook script is properly configured in all installation scenarios, preventing production deployment failures where component bundles would be missing.

Confidence Score: 5/5

  • This PR is safe to merge with high confidence
  • The changes are well-structured with excellent test coverage. The fix addresses a real production issue (deployment failures) with a targeted solution. The use of gsub_file over YAML.dump is a significant improvement that preserves file structure. The implementation includes proper version checks, guards against re-configuration, and handles all edge cases (fresh install, pre-installed, user-declined overwrite).
  • No files require special attention

Important Files Changed

Filename Overview
react_on_rails/lib/generators/react_on_rails/base_generator.rb Restructured copy_packer_config to always configure precompile_hook for Shakapacker 9.0+; improved configure_rspack_in_shakapacker to use gsub_file to preserve YAML structure and comments
react_on_rails/spec/react_on_rails/generators/install_generator_spec.rb Added comprehensive test suite for precompile_hook configuration when Shakapacker is pre-installed, verifying both functionality and preservation of YAML structure

Sequence Diagram

sequenceDiagram
    participant User
    participant Generator as ReactOnRails Generator
    participant FileSystem as File System
    participant Shakapacker as Shakapacker Config

    User->>Generator: rails generate react_on_rails:install
    
    alt Shakapacker pre-installed
        Note over Generator: .shakapacker_just_installed exists
        Generator->>FileSystem: Check for marker file
        FileSystem-->>Generator: File exists
        Generator->>FileSystem: Delete marker file
        Note over Generator: Skip copying shakapacker.yml
    else Fresh install
        Generator->>FileSystem: Copy shakapacker.yml from template
        Note over Shakapacker: precompile_hook already configured in template
    end
    
    alt rspack option enabled
        Generator->>Shakapacker: configure_rspack_in_shakapacker()
        Shakapacker->>Shakapacker: gsub_file: assets_bundler → "rspack"
    end
    
    Generator->>Shakapacker: configure_precompile_hook_in_shakapacker()
    
    alt Shakapacker < 9.0.0
        Note over Generator: Skip (not supported)
    else Shakapacker >= 9.0.0
        Shakapacker->>Shakapacker: Check for existing active hook
        
        alt Hook already configured
            Note over Generator: Skip (already set)
        else Hook commented out
            Shakapacker->>Shakapacker: gsub_file: # precompile_hook: ~ → precompile_hook: 'bin/...'
            Note over Shakapacker: Preserves comments and YAML anchors
        end
    end
    
    Generator->>FileSystem: Copy bin/shakapacker-precompile-hook
    Note over FileSystem: Hook script ready to use
Loading

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.

Generator doesn't configure precompile_hook in shakapacker.yml when Shakapacker is pre-installed

2 participants