Fix duplicate rake task execution by removing explicit task loading#2052
Fix duplicate rake task execution by removing explicit task loading#2052
Conversation
|
Warning Rate limit exceeded@justin808 has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 27 minutes and 28 seconds before requesting another review. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📒 Files selected for processing (3)
WalkthroughThree Rake task files receive file-level load guards to prevent multiple evaluations during Rails initialization. Each file now returns early if its corresponding guard constant is already defined, then sets that constant to prevent future re-loads. Changes
Estimated code review effort🎯 1 (Trivial) | ⏱️ ~3 minutes
Possibly related PRs
Suggested labels
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Code Review - PR #2052SummaryThis PR fixes a critical issue where rake tasks were being executed multiple times when Rails Engine's ✅ Strengths
🔍 Code Quality & Best PracticesPositive:
Considerations:
🐛 Potential IssuesNo major bugs identified, but some edge cases to consider:
⚡ Performance ConsiderationsExcellent:
🔒 Security ConcernsNo security issues identified.
🧪 Test CoverageSuggestions:
📋 Additional Recommendations
✅ Final VerdictAPPROVED ✨ This is a well-implemented fix for a real performance issue. The code is clean, consistent, and follows Ruby best practices. The only suggestion is to add an automated test to prevent regression. Score:
Overall: Excellent work! 🚀 Review generated with assistance from Claude Code |
Rails Engine automatically loads all .rake files from lib/tasks/ directory via its run_tasks_blocks method. The explicit load calls in the rake_tasks block caused each task file to be loaded twice: 1. Once via explicit load in rake_tasks block (Railtie layer) 2. Once via automatic loading by Rails::Engine This resulted in tasks having duplicate action blocks, causing: - react_on_rails:assets:webpack to run webpack build twice - react_on_rails:generate_packs to run twice - react_on_rails:locale to compile locales twice The fix removes the explicit load calls and relies on Rails Engine's standard auto-loading behavior from lib/tasks/*.rake, which already works correctly for doctor.rake. Verified that all tasks (assets:webpack, generate_packs, locale, doctor) load correctly with exactly 1 action block each. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
0fd87c9 to
7996fc4
Compare
|
/run-skipped-ci |
|
🚀 Full CI Mode Enabled Failed to trigger:
Note: Added the To disable full CI mode, use the View progress in the Actions tab. |
Code Review - PR 2052Recommendation: ✅ APPROVE (pending CI verification) SummaryThis PR fixes a critical performance bug where rake tasks were executing twice. The solution correctly removes explicit load calls and relies on Rails Engine automatic task loading from lib/tasks/*.rake. ✅ Strengths1. Root Cause Analysis - Excellent
2. Solution is Correct and Idiomatic
3. Excellent Documentation
⚡ Performance Impact✅ Significant performance improvement:
Estimated impact: ~50% reduction in asset compilation time during deployment 🧪 Test Coverage RecommendationCurrent tests in spec/react_on_rails/engine_spec.rb cover version validation, package.json detection, and generator detection, but have no tests for rake task loading. Suggestion: Consider adding a regression test to verify each task loads with exactly 1 action block. This would prevent future regressions. 🎯 Best Practices Alignment✅ Rails Conventions
✅ Code Simplicity
✅ Documentation
🚨 Questions
📋 Pre-Merge Checklist
Overall: High-Quality Fix
Great work on the thorough investigation and clean solution! 🚀 Review performed using React on Rails CLAUDE.md conventions |
Add comprehensive tests to verify Rails::Engine properly loads rake tasks from lib/tasks/ without needing explicit rake_tasks block: 1. Verifies engine.rb does NOT have a rake_tasks block - This prevents duplicate task execution (PR #1770 bug) - Ensures we rely on Rails::Engine automatic loading 2. Verifies all expected task files exist in lib/tasks/ - assets.rake, generate_packs.rake, locale.rake, doctor.rake - Confirms files are in the standard location for automatic loading Update .rubocop.yml to exclude engine_spec.rb from ModuleLength check as the comprehensive test suite requires many examples to properly validate Rails::Engine behavior. These tests catch the duplicate loading bug that occurred in PR #1770 and was fixed in PR #2052. See RAKE_TASK_DUPLICATE_ANALYSIS.md for complete historical context. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
… rake task loading (#2067) ## Summary Adds comprehensive documentation about Rails Engine development and unit tests to prevent the duplicate rake task bug that occurred in PR #1770 and was fixed in PR #2052. ## Changes ### 1. Documentation (CLAUDE.md) Added new section "Rails Engine Development Nuances" covering: - **Automatic Rake Task Loading**: Rails::Engine automatically loads `lib/tasks/*.rake` files - no `rake_tasks` block needed - **Engine Initializers and Hooks**: Proper use of `config.to_prepare` and `initializer` blocks - **Engine vs Application Code**: Different contexts and what code runs where - **Testing Engines**: Dummy app vs unit tests - **Common Pitfalls**: Path resolution, autoloading, configuration ### 2. Analysis Document (RAKE_TASK_DUPLICATE_ANALYSIS.md) Complete analysis of why PR #1770 added the problematic `rake_tasks` block: - Context of the massive 97-file Generator Overhaul - Why explicit loading was added (ensuring task availability for new file-system auto-registration) - How it caused 2x slower builds for 2 months - Lessons for code reviews, testing, and documentation ### 3. Unit Tests (spec/react_on_rails/engine_spec.rb) Two new tests to catch this bug: - Verifies `engine.rb` does NOT have a `rake_tasks` block - Verifies all task files exist in the standard `lib/tasks/` location Updated `.rubocop.yml` to exclude engine_spec.rb from ModuleLength check. ## Why This Matters The Rails Engine nuances documented here are **not well documented** in general Rails guides, leading to bugs like: - PR #1770: Duplicate rake task execution causing 2x slower builds - Confusion about where code runs (engine vs host app) - Generator failures in different app configurations ## Testing - ✅ Unit tests pass and verify no `rake_tasks` block exists - ✅ RuboCop passes with exclusion for comprehensive test module - ✅ All files end with newlines ## References - **Bug introduced**: PR #1770 - "Generator Overhaul & Developer Experience Enhancement" - **Bug fixed**: PR #2052 - "Fix duplicate rake task execution by removing explicit task loading" - **Historical analysis**: See `RAKE_TASK_DUPLICATE_ANALYSIS.md` - **Rails Engine Guide**: https://guides.rubyonrails.org/engines.html 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude <[email protected]>
…se-otp-timing * origin/master: (27 commits) Fix doctor command false version mismatch for beta/prerelease versions (#2064) Fix beta/RC version handling in generator (#2066) Document Rails Engine development nuances and add tests for automatic rake task loading (#2067) Add /run-skipped-tests as alias for /run-skipped-ci (#XXXX) (#2068) Fix: Add Rails 5.2-6.0 compatibility for compact_blank (#2058) Break CI circular dependency with non-docs change (#2065) Fix CI safety check to evaluate latest workflow attempt (#2062) Fix yalc publish (#2054) Add Shakapacker 9.0+ private_output_path integration for server bundles (#2028) Consolidate all beta versions into v16.2.0.beta.10 (#2057) Improve reliability of CI debugging scripts (#2056) Clarify monorepo changelog structure in documentation (#2055) Bump version to 16.2.0.beta.10 Bump version to 16.2.0.beta.9 Fix duplicate rake task execution by removing explicit task loading (#2052) Simplify precompile hook and restore Pro dummy app to async loading (#2053) Add Shakapacker precompile hook with ReScript support to Pro dummy app (#1977) Guard master docs-only pushes and ensure full CI runs (#2042) Refactor: Extract JS dependency management into shared module (#2051) Add workflow to detect invalid CI command attempts (#2037) ... # Conflicts: # rakelib/release.rake
## Summary Closes #2081 This adds a new GitHub Actions workflow that runs `RAILS_ENV=production bin/rake assets:precompile` on the dummy app and checks the output for known failure patterns that have been encountered in the past. ## Failure Patterns Detected The workflow checks for: - **Duplicate webpack compilations** - indicates rake tasks running twice (like the issue fixed in PR #2052) - **Duplicate rake task execution** - e.g., `generate_packs` running multiple times - **Module not found / cannot resolve errors** - missing dependencies - **Webpack compilation errors** - build failures - **Ruby errors** - NameError, LoadError, NoMethodError, SyntaxError - **Asset pipeline errors** - Sprockets file not found, undeclared assets - **Memory issues** - JavaScript heap out of memory, killed processes - **High warning counts** - triggers a warning annotation if >10 warnings found ## Features - Uses the same change detection as other CI jobs (skips for docs-only changes) - Uploads precompile output as an artifact for debugging when failures occur - Provides clear error annotations in GitHub Actions UI - Runs on PRs and master pushes ## Test plan - [ ] CI workflow passes on this PR - [ ] Verify the workflow runs and captures output correctly - [ ] Manually test by introducing a known failure (e.g., duplicate task execution) to verify detection works 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Added an automated assets precompile check in CI that conditionally runs on relevant pushes and manual triggers, captures precompile output, scans for failure/warning patterns, and uploads logs as an artifact. * Introduced a standalone validation utility to analyze precompile output and fail CI on known error patterns. * **Tests / CI** * Improved package linking in CI to preserve local linked packages and made installs tolerant of minimum-dependency matrix runs by conditionally relaxing lockfile enforcement. <sub>✏️ Tip: You can customize this high-level summary in your review settings.</sub> <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude <[email protected]>
…ands Primary install paths now use unversioned commands (e.g., `bundle add react_on_rails --strict`) matching what the generator and create-react-on-rails-app already do. Manual pin sections retain versioned examples with a "check the changelog" note, updated from 16.4.0 to 16.5.1. Troubleshooting fix commands now use `<VERSION>` placeholders so they never go stale. Also fixes two incorrect minimum version claims: - i18n.md: precompile_hook + bin/dev was introduced in 16.2.0, not 16.4.0 - troubleshooting-build-errors.md: duplicate rake task fix was PR #2052 in 16.2.0, not 16.4.0 Closes #2871 Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
…ands (#2893) ## Summary - Primary install commands switched to unversioned (e.g., `bundle add react_on_rails_pro`) - Manual pin and upgrade sections use `<VERSION>` placeholders instead of hardcoded version numbers - Troubleshooting fix commands use `<VERSION>` placeholders with instructions to check the error message - Upgrade docs reference the `react_on_rails:sync_versions` rake task for post-upgrade version verification - Two incorrect minimum version claims corrected (16.4.0 → 16.2.0) ## Why Hardcoded versions across docs go stale every release with no automation to update them. The runtime `VersionChecker` (since 2018) catches gem/npm mismatches with a hard error, and all automated install paths (generator, `create-react-on-rails-app`) already handle version sync dynamically. ## Changes **Switched to unversioned** (3 files): - `docs/pro/react-server-components/create-without-ssr.md` — primary RSC install commands - `docs/oss/building-features/testing-configuration.md` — Gemfile example - `docs/oss/api-reference/generator-details.md` — Pro prerequisites **Switched to `<VERSION>` placeholders** (4 files): - `docs/pro/upgrading-to-pro.md` — CLI commands are unversioned; only the manual Gemfile edit uses `<VERSION>` - `docs/pro/updating.md` — migration guide diffs use `<VERSION>` for manual file edits - `docs/oss/getting-started/installation-into-an-existing-rails-app.md` — optional manual pin section - `docs/oss/migrating/rsc-troubleshooting.md` — fix commands reference error message output **Corrected minimum version claims** (2 files): - `docs/oss/building-features/i18n.md` — precompile_hook + bin/dev works since 16.2.0 (`bin/dev` runs the hook via `Open3.capture3`, not the `load` path fixed in 16.4.0) - `docs/oss/deployment/troubleshooting-build-errors.md` — duplicate rake task fix was PR #2052 in 16.2.0 ## Test plan - [ ] `grep -rn "16\.4\.0" docs/ --include="*.md"` shows only legitimate references (historical entries, minimum requirements) - [ ] `grep -rn "16\.5\.1" docs/ --include="*.md"` shows no matches in changed files - [ ] Markdown link check passes (CI) - [ ] No install commands still hardcode a specific version Closes #2871 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Replaced hardcoded 16.4.0 examples with unpinned installs or <VERSION> placeholders and point readers to the CHANGELOG for the correct version. * Simplified Pro install/upgrade guidance and added a post-upgrade step to sync gem/npm versions. * Lowered recommended minimum React on Rails guidance from 16.4.0+ to 16.2.0+ for select configurations. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
…ands (#2893) ## Summary - Primary install commands switched to unversioned (e.g., `bundle add react_on_rails_pro`) - Manual pin and upgrade sections use `<VERSION>` placeholders instead of hardcoded version numbers - Troubleshooting fix commands use `<VERSION>` placeholders with instructions to check the error message - Upgrade docs reference the `react_on_rails:sync_versions` rake task for post-upgrade version verification - Two incorrect minimum version claims corrected (16.4.0 → 16.2.0) ## Why Hardcoded versions across docs go stale every release with no automation to update them. The runtime `VersionChecker` (since 2018) catches gem/npm mismatches with a hard error, and all automated install paths (generator, `create-react-on-rails-app`) already handle version sync dynamically. ## Changes **Switched to unversioned** (3 files): - `docs/pro/react-server-components/create-without-ssr.md` — primary RSC install commands - `docs/oss/building-features/testing-configuration.md` — Gemfile example - `docs/oss/api-reference/generator-details.md` — Pro prerequisites **Switched to `<VERSION>` placeholders** (4 files): - `docs/pro/upgrading-to-pro.md` — CLI commands are unversioned; only the manual Gemfile edit uses `<VERSION>` - `docs/pro/updating.md` — migration guide diffs use `<VERSION>` for manual file edits - `docs/oss/getting-started/installation-into-an-existing-rails-app.md` — optional manual pin section - `docs/oss/migrating/rsc-troubleshooting.md` — fix commands reference error message output **Corrected minimum version claims** (2 files): - `docs/oss/building-features/i18n.md` — precompile_hook + bin/dev works since 16.2.0 (`bin/dev` runs the hook via `Open3.capture3`, not the `load` path fixed in 16.4.0) - `docs/oss/deployment/troubleshooting-build-errors.md` — duplicate rake task fix was PR #2052 in 16.2.0 ## Test plan - [ ] `grep -rn "16\.4\.0" docs/ --include="*.md"` shows only legitimate references (historical entries, minimum requirements) - [ ] `grep -rn "16\.5\.1" docs/ --include="*.md"` shows no matches in changed files - [ ] Markdown link check passes (CI) - [ ] No install commands still hardcode a specific version Closes #2871 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Replaced hardcoded 16.4.0 examples with unpinned installs or <VERSION> placeholders and point readers to the CHANGELOG for the correct version. * Simplified Pro install/upgrade guidance and added a post-upgrade step to sync gem/npm versions. * Lowered recommended minimum React on Rails guidance from 16.4.0+ to 16.2.0+ for select configurations. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
…ands (#2893) ## Summary - Primary install commands switched to unversioned (e.g., `bundle add react_on_rails_pro`) - Manual pin and upgrade sections use `<VERSION>` placeholders instead of hardcoded version numbers - Troubleshooting fix commands use `<VERSION>` placeholders with instructions to check the error message - Upgrade docs reference the `react_on_rails:sync_versions` rake task for post-upgrade version verification - Two incorrect minimum version claims corrected (16.4.0 → 16.2.0) ## Why Hardcoded versions across docs go stale every release with no automation to update them. The runtime `VersionChecker` (since 2018) catches gem/npm mismatches with a hard error, and all automated install paths (generator, `create-react-on-rails-app`) already handle version sync dynamically. ## Changes **Switched to unversioned** (3 files): - `docs/pro/react-server-components/create-without-ssr.md` — primary RSC install commands - `docs/oss/building-features/testing-configuration.md` — Gemfile example - `docs/oss/api-reference/generator-details.md` — Pro prerequisites **Switched to `<VERSION>` placeholders** (4 files): - `docs/pro/upgrading-to-pro.md` — CLI commands are unversioned; only the manual Gemfile edit uses `<VERSION>` - `docs/pro/updating.md` — migration guide diffs use `<VERSION>` for manual file edits - `docs/oss/getting-started/installation-into-an-existing-rails-app.md` — optional manual pin section - `docs/oss/migrating/rsc-troubleshooting.md` — fix commands reference error message output **Corrected minimum version claims** (2 files): - `docs/oss/building-features/i18n.md` — precompile_hook + bin/dev works since 16.2.0 (`bin/dev` runs the hook via `Open3.capture3`, not the `load` path fixed in 16.4.0) - `docs/oss/deployment/troubleshooting-build-errors.md` — duplicate rake task fix was PR #2052 in 16.2.0 ## Test plan - [ ] `grep -rn "16\.4\.0" docs/ --include="*.md"` shows only legitimate references (historical entries, minimum requirements) - [ ] `grep -rn "16\.5\.1" docs/ --include="*.md"` shows no matches in changed files - [ ] Markdown link check passes (CI) - [ ] No install commands still hardcode a specific version Closes #2871 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Replaced hardcoded 16.4.0 examples with unpinned installs or <VERSION> placeholders and point readers to the CHANGELOG for the correct version. * Simplified Pro install/upgrade guidance and added a post-upgrade step to sync gem/npm versions. * Lowered recommended minimum React on Rails guidance from 16.4.0+ to 16.2.0+ for select configurations. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
Summary
Fixes duplicate rake task execution by removing explicit task loading from the Engine's
rake_tasksblock. Rails Engine automatically loads all.rakefiles fromlib/tasks/, making the explicitloadcalls redundant and causing duplicate execution.Root Cause
Rails Engine inherits from Railtie, which means rake tasks are processed through two separate layers:
Rails::Railtie#run_tasks_blocks): Executes therake_tasksblockRails::Engine#run_tasks_blocks): Auto-loads alllib/tasks/*.rakefilesThe Problem
The Engine had explicit
loadcalls in itsrake_tasksblock:During a single
Rails.application.load_taskscall:rake_tasksblock → loads each file oncelib/tasks/→ loads each file againResult: Each task file loaded twice, creating tasks with 2 action blocks instead of 1.
Trace Evidence
Impact of the Bug
When a task with multiple action blocks executes, Rake runs all blocks sequentially:
react_on_rails:assets:webpack→ Webpack build runs twicereact_on_rails:generate_packs→ Pack generation runs twicereact_on_rails:locale→ Locale compilation runs twiceload_taskscalls (tests) → Multiplies duplication (4x, 6x, etc.)This significantly slowed down asset compilation and wasted CI time.
Solution
Removed the explicit
loadcalls and rely on Rails Engine's standard auto-loading:This follows Rails conventions and matches how
doctor.rakealready worked (it was never explicitly loaded but functioned correctly).Verification
✅ All tasks load with exactly 1 action block:
✅ Manual duplicate load test confirms fix:
Files Changed
lib/react_on_rails/engine.rb- Removedrake_tasksblock with explicit loads, added explanatory commentlib/tasks/*.rake- No changes (kept clean, removed guards from initial approach)Why This Fix Is Better Than Guards
Initial approach considered: Add guard constants to each rake file to skip on duplicate load
Final approach: Remove the explicit loads entirely
✅ Works
❌ Maintenance overhead
❌ Files still loaded twice
✅ Cleaner code
✅ Follows Rails conventions
✅ Files loaded once
Breaking Changes
None. This is an internal loading behavior change with no user-facing impact.
Related
This same pattern appears in many Rails engines that explicitly load tasks. The proper approach is to:
lib/tasks/*.rakerake_tasks do ... load ... endfor Engine classes🤖 Generated with Claude Code