diff --git a/.claude/commands/update-changelog.md b/.claude/commands/update-changelog.md index 78c1cbd106..a7dcaa8c5f 100644 --- a/.claude/commands/update-changelog.md +++ b/.claude/commands/update-changelog.md @@ -5,7 +5,6 @@ You are helping to add an entry to the CHANGELOG.md file for the React on Rails ## Critical Requirements 1. **User-visible changes only**: Only add changelog entries for user-visible changes: - - New features - Bug fixes - Breaking changes @@ -118,13 +117,11 @@ When a new version is released: ### For Regular Changelog Updates 1. **ALWAYS fetch latest changes first**: - - **CRITICAL**: Run `git fetch origin master` to ensure you have the latest commits - The workspace may be behind origin/master, causing you to miss recently merged PRs - After fetching, use `origin/master` for all comparisons, NOT local `master` branch 2. **Determine the correct version tag to compare against**: - - First, check the tag dates: `git log --tags --simplify-by-decoration --pretty="format:%ai %d" | head -10` - Find the latest version tag and its date - Compare origin/master branch date to the tag date @@ -132,7 +129,6 @@ When a new version is released: - **CRITICAL**: Always use `git log TAG..BRANCH` to find commits that are in the tag but not in the branch, as the tag may be ahead 3. **Check commits and version boundaries**: - - **IMPORTANT**: Use `origin/master` in all commands below, not local `master` - Run `git log --oneline LAST_TAG..origin/master` to see commits since the last release - Also check `git log --oneline origin/master..LAST_TAG` to see if the tag is ahead of origin/master @@ -148,20 +144,17 @@ When a new version is released: 5. **Read the current CHANGELOG.md** to understand the existing structure and formatting. 6. **Determine where entries should go**: - - If the latest version tag is NEWER than origin/master branch, move entries from "Unreleased" to that version section - If origin/master is ahead of the latest tag, add new entries to "Unreleased" - Always verify the version date in CHANGELOG.md matches the actual tag date 7. **Add or move entries** to the appropriate section under appropriate category headings. - - **CRITICAL**: When moving entries from "Unreleased" to a version section, merge them with existing entries under the same category heading - **NEVER create duplicate section headings** (e.g., don't create two "### Fixed" sections) - If the version section already has a category heading (e.g., "### Fixed"), add the moved entries to that existing section - Maintain the category order as defined above 8. **Verify formatting**: - - Bold description with period - Proper PR link (NO hash symbol) - Proper author link @@ -181,12 +174,10 @@ When a new version is released: When releasing from beta to a stable version (e.g., v16.1.0-beta.3 → v16.1.0): 1. **Remove all beta version labels** from the changelog: - - Change `### [v16.1.0-beta.1]`, `### [v16.1.0-beta.2]`, etc. to a single `### [v16.1.0]` section - Combine all beta entries into the stable release section 2. **Consolidate duplicate entries**: - - If bug fixes or changes were made to features introduced in earlier betas, keep only the final state - Remove redundant changelog entries for fixes to beta features - Keep the most recent/accurate description of each change diff --git a/.rubocop.yml b/.rubocop.yml index 0c1270fd09..b99e570aff 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -25,6 +25,7 @@ AllCops: - '**/node_modules/**/*' - '**/public/**/*' - '**/tmp/**/*' + - 'bin/*' # Shell scripts - 'coverage/**/*' - 'gen-examples/examples/**/*' - 'node_modules/**/*' diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c6d318fd4..06370fbc60 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,7 +38,6 @@ Changes since the last non-beta release. #### Changed - **Shakapacker 9.0.0 Upgrade**: Upgraded Shakapacker from 8.2.0 to 9.0.0 with Babel transpiler configuration for compatibility. Key changes include: - - Configured `javascript_transpiler: babel` in shakapacker.yml (Shakapacker 9.0 defaults to SWC which has PropTypes handling issues) - Added precompile hook support via `bin/shakapacker-precompile-hook` for ReScript builds and pack generation - Configured CSS Modules to use default exports (`namedExport: false`) for backward compatibility with existing `import styles from` syntax @@ -100,7 +99,6 @@ To migrate to React on Rails Pro: **Note:** If you're not using any of the Pro-only methods listed above, no changes are required. - **Pro-Specific Configurations Moved to Pro Gem**: The following React Server Components (RSC) configurations have been moved from `ReactOnRails.configure` to `ReactOnRailsPro.configure`: - - `rsc_bundle_js_file` - Path to the RSC bundle file - `react_server_client_manifest_file` - Path to the React server client manifest - `react_client_manifest_file` - Path to the React client manifest @@ -126,7 +124,6 @@ To migrate to React on Rails Pro: See the [React on Rails Pro Configuration docs](https://github.com/shakacode/react_on_rails/blob/master/react_on_rails_pro/docs/configuration.md) for more details. - **Streaming View Helpers Moved to Pro Gem**: The following view helpers have been removed from the open-source gem and are now only available in React on Rails Pro: - - `stream_react_component` - Progressive SSR using React 18+ streaming - `rsc_payload_react_component` - RSC payload rendering @@ -151,12 +148,10 @@ To migrate to React on Rails Pro: #### New Features - **Server Bundle Security**: Added new configuration options for enhanced server bundle security and organization: - - `server_bundle_output_path`: Configurable directory (relative to the Rails root) for server bundle output (default: "ssr-generated"). If set to `nil`, the server bundle will be loaded from the same public directory as client bundles. [PR 1798](https://github.com/shakacode/react_on_rails/pull/1798) by [justin808](https://github.com/justin808) - `enforce_private_server_bundles`: When enabled, ensures server bundles are only loaded from private directories outside the public folder (default: false for backward compatibility) [PR 1798](https://github.com/shakacode/react_on_rails/pull/1798) by [justin808](https://github.com/justin808) - **Improved Bundle Path Resolution**: Bundle path resolution for server bundles now works as follows: - - If `server_bundle_output_path` is set, the server bundle is loaded from that directory. - If `server_bundle_output_path` is not set, the server bundle falls back to the client bundle directory (typically the public output path). - If `enforce_private_server_bundles` is enabled: @@ -268,7 +263,6 @@ See [Release Notes](docs/release-notes/16.0.0.md) for complete migration guide. - **`defer_generated_component_packs` deprecated** → use `generated_component_packs_loading_strategy` - Migration: - - `defer_generated_component_packs: true` → `generated_component_packs_loading_strategy: :defer` - `defer_generated_component_packs: false` → `generated_component_packs_loading_strategy: :sync` - Recommended: `generated_component_packs_loading_strategy: :async` for best performance @@ -677,7 +671,6 @@ for details. - Removal of config.symlink_non_digested_assets_regex as it's no longer needed with rails/webpacker. If any business needs this, we can move the code to a separate gem. - Added configuration option `same_bundle_for_client_and_server` with default `false` because - 1. Production applications would typically have a server bundle that differs from the client bundle 2. This change only affects trying to use HMR with react_on_rails with rails/webpacker. @@ -1395,13 +1388,11 @@ No changes. - Added automatic compilation of assets at precompile is now done by ReactOnRails. Thus, you don't need to provide your own `assets.rake` file that does the precompilation. [#398](https://github.com/shakacode/react_on_rails/pull/398) by [robwise](https://github.com/robwise), [jbhatab](https://github.com/jbhatab), and [justin808](https://github.com/justin808). - **Migration to v6** - - Do not run the generator again if you've already run it. - See [shakacode/react-webpack-rails-tutorial/pull/287](https://github.com/shakacode/react-webpack-rails-tutorial/pull/287) for an example of upgrading from v5. - To configure the asset compilation you can either - 1. Specify a `config/react_on_rails` setting for `build_production_command` to be nil to turn this feature off. 2. Specify the script command you want to run to build your production assets, and remove your `assets.rake` file. diff --git a/CLAUDE.md b/CLAUDE.md index c22696b637..0aa9397c6d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -10,6 +10,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co 2. **ALWAYS ensure files end with a newline character** 3. **NEVER push without running full lint check first** 4. **ALWAYS let Prettier and RuboCop handle ALL formatting - never manually format** +5. **ALWAYS run `yarn run eslint --report-unused-disable-directives` before committing** - This matches CI's exact ESLint check These requirements are non-negotiable. CI will fail if not followed. @@ -37,6 +38,7 @@ Pre-commit hooks automatically run: - All tests: `rake` (default task runs lint and all tests except examples) - **Linting** (MANDATORY BEFORE EVERY COMMIT): - **REQUIRED**: `bundle exec rubocop` - Must pass with zero offenses + - **REQUIRED**: `yarn run eslint --report-unused-disable-directives` - Must pass (matches CI exactly) - All linters: `rake lint` (runs ESLint and RuboCop) - ESLint only: `yarn run lint` or `rake lint:eslint` - RuboCop only: `rake lint:rubocop` @@ -48,6 +50,169 @@ Pre-commit hooks automatically run: - **⚠️ MANDATORY BEFORE GIT PUSH**: `bundle exec rubocop` and fix ALL violations + ensure trailing newlines - Never run `npm` commands, only equivalent Yarn Classic ones +### Replicating CI Failures Locally + +**CRITICAL: NEVER wait for CI to verify fixes. Always replicate failures locally first.** + +#### Switch Between CI Configurations (🔥 NEW!) + +The project tests against two configurations: +- **Latest**: Ruby 3.4, Node 22, Shakapacker 9.3.0, React 19 (runs on all PRs) +- **Minimum**: Ruby 3.2, Node 20, Shakapacker 8.2.0, React 18 (runs only on master) + +```bash +# Check your current configuration +bin/ci-switch-config status + +# Switch to minimum dependencies (for debugging minimum CI failures) +bin/ci-switch-config minimum + +# Switch back to latest dependencies +bin/ci-switch-config latest +``` + +**See `SWITCHING_CI_CONFIGS.md` for detailed usage and troubleshooting.** + +#### Re-run Failed CI Jobs (🔥 NEW - Most Efficient!) + +```bash +# Automatically detects and re-runs only the failed CI jobs +bin/ci-rerun-failures + +# Search recent commits for failures (when current commit is clean/in-progress) +bin/ci-rerun-failures --previous + +# Or for a specific PR number +bin/ci-rerun-failures 1964 +``` + +This script: +- ✨ **Fetches actual CI failures** from GitHub using `gh` CLI +- 🎯 **Runs only what failed** - no wasted time on passing tests +- ⏳ **Waits for in-progress CI** - offers to poll until completion +- 🔍 **Searches previous commits** - finds failures before your latest push +- 📋 **Shows you exactly what will run** before executing +- 🚀 **Maps CI jobs to local commands** automatically + +**Example output:** +``` +Failed CI jobs: + ✗ dummy-app-integration-tests (3.4, 22, latest) + ✗ dummy-app-integration-tests (3.2, 20, minimum) + +Will run the following commands: + • dummy-app-integration-tests: bundle exec rake run_rspec:all_dummy + +💡 Tip: For RSpec failures, you can run specific failing examples: + 1. Go to the failed job on GitHub Actions + 2. Copy the 'Failed examples:' section + 3. Run: pbpaste | bin/ci-run-failed-specs +``` + +#### Run Only Failed Examples (Even More Targeted!) + +When RSpec tests fail, run just those specific examples: + +```bash +# Copy failure output from GitHub Actions, then: +pbpaste | bin/ci-run-failed-specs + +# Or pass spec paths directly: +bin/ci-run-failed-specs './spec/system/integration_spec.rb[1:1:1:1]' + +# Or from a file: +bin/ci-run-failed-specs < failures.txt +``` + +This script: +- 🎯 **Runs only failing examples** - not the entire test suite +- 📋 **Parses RSpec output** - extracts spec paths automatically +- 🔄 **Deduplicates** - removes duplicate specs +- 📁 **Auto-detects directory** - runs from spec/dummy when needed + +#### Smart Test Detection + +```bash +# Runs tests based on your code changes +bin/ci-local + +# Run all CI checks +bin/ci-local --all + +# Fast mode - skips slow tests +bin/ci-local --fast +``` + +#### Manual Test Commands + +When you need to run specific test suites manually: + +```bash +# All dummy app tests (matches CI most closely) +bundle exec rake run_rspec:all_dummy +``` + +This automatically builds TypeScript, generates packs, builds webpack, and runs tests. + +#### Faster Iteration for Specific Tests + +```bash +# Run from project root +rake node_package # 1. Build TypeScript and link via yalc + +# Run from spec/dummy directory +cd spec/dummy +bin/shakapacker-precompile-hook # 2. Run precompile tasks (generate packs, ReScript, etc.) +RAILS_ENV=test bin/shakapacker # 3. Build webpack +DISABLE_TURBOLINKS=TRUE bundle exec rspec './spec/system/integration_spec.rb[1:1:1:1]' +``` + +**Note**: Always run `bin/shakapacker-precompile-hook` before `bin/shakapacker` to ensure component packs are generated and any compilation tasks (ReScript, etc.) are completed. The hook handles all precompile steps that newer Shakapacker versions run automatically. + +**⚠️ Known Issue**: System tests may fail locally on Ruby 3.4.3 + OpenSSL 3.6 with SSL certificate errors. This is an environment issue, not a code issue. See `spec/dummy/TESTING_LOCALLY.md` for details. **Use CI as the source of truth for system tests.** + +**Note**: System tests may fail locally with SSL/environment issues but pass in CI. When in doubt, rely on `rake run_rspec:all_dummy`. + +#### Common Test Tasks + +```bash +# All dummy app tests (with and without turbolinks) +bundle exec rake run_rspec:all_dummy + +# Only tests without turbolinks (matches one CI job) +bundle exec rake run_rspec:dummy_no_turbolinks + +# Gem-only tests (fast, no webpack needed) +bundle exec rake run_rspec:gem + +# Everything except generated examples +bundle exec rake all_but_examples +``` + +#### Debugging Component Registration Issues + +When you see "Could not find component registered with name X": + +1. **Check generated packs exist**: + ```bash + ls -la spec/dummy/client/app/packs/generated/ + ls -la spec/dummy/client/app/generated/ + ``` + +2. **Verify webpack output**: + ```bash + ls -la spec/dummy/public/webpack/test/js/ + ``` + +3. **Check script loading in HTML**: Inspect the page source for `