Skip to content

Avoid full locale default obsolete scans - #4398

Merged
justin808 merged 4 commits into
mainfrom
codex/g4-4345-locales
Jul 2, 2026
Merged

Avoid full locale default obsolete scans#4398
justin808 merged 4 commits into
mainfrom
codex/g4-4345-locales

Conversation

@justin808

@justin808 justin808 commented Jul 2, 2026

Copy link
Copy Markdown
Member

Rationale

Fixes #4345. Locale generation only needs to distinguish current generated default.js output from obsolete legacy react-intl output, but the obsolete check read the whole file eagerly.

Changes

  • Stream default.js line by line instead of reading the whole file.
  • Regenerate when the legacy react-intl/defineMessages import is found, including after comment, pragma, or custom content.
  • Stop scanning once the current generated const defaultLocale = marker is reached.
  • Add regression coverage for current generated files and legacy imports after custom content.

Validation

  • PR_BATCH_SKILL_DIR=.agents/skills/pr-batch .agents/skills/pr-batch/bin/pr-security-preflight --repo shakacode/react_on_rails 4345
  • .agents/bin/agent-workflow-seam-doctor
  • (cd react_on_rails && bundle exec rspec spec/react_on_rails/locales_to_js_spec.rb) (14 examples after review-fix coverage)
  • (cd react_on_rails && RUBYOPT=-W0 BUNDLE_GEMFILE=../Gemfile bundle exec rubocop lib/react_on_rails/locales/to_js.rb spec/react_on_rails/locales_to_js_spec.rb)
  • git diff --check origin/main...HEAD && git diff --check
  • codex review --base origin/main returned no actionable findings before hosted review-fix pushes.
  • git push -u origin codex/g4-4345-locales and later review-fix pushes passed branch RuboCop and markdown-links.

Codex Decision Log

  • Non-blocking: Changelog classification for merge-ledger closeout.
    • Decision: not_user_visible.
    • Why: The change preserves generated locale output and legacy migration behavior while reducing obsolete-check I/O.
    • Review later: None.

@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: bfe84502-c1f8-4d54-b0ae-58d6dd05db93

📥 Commits

Reviewing files that changed from the base of the PR and between a6c5867 and 5f7a331.

📒 Files selected for processing (2)
  • react_on_rails/lib/react_on_rails/locales/to_js.rb
  • react_on_rails/spec/react_on_rails/locales_to_js_spec.rb
👮 Files not reviewed due to content moderation or server errors (2)
  • react_on_rails/lib/react_on_rails/locales/to_js.rb
  • react_on_rails/spec/react_on_rails/locales_to_js_spec.rb

Warning

Walkthrough skipped

File diffs could not be summarized.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/g4-4345-locales

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.

@justin808

Copy link
Copy Markdown
Member Author

+ci-status

@justin808

Copy link
Copy Markdown
Member Author

+ci-run-hosted

@greptile-apps

greptile-apps Bot commented Jul 2, 2026

Copy link
Copy Markdown

Greptile Summary

This PR narrows locale obsolete detection for generated JavaScript files. The main changes are:

  • Adds an anchored legacy react-intl import matcher.
  • Reads only the first nonblank line of default.js during obsolete checks.
  • Adds a spec that keeps modern generated files from being fully scanned or regenerated.

Confidence Score: 5/5

This looks safe to merge after considering the narrow legacy-file edge case.

  • The canonical legacy generated file still starts with the import this matcher detects.
  • A customized or post-processed legacy file with a nonblank prefix can be skipped, but that depends on extra file changes outside the standard generator output.
  • No blocking issues were found in the changed code.

Important Files Changed

Filename Overview
react_on_rails/lib/react_on_rails/locales/to_js.rb Changes the obsolete check to inspect only the first nonblank line, which avoids full-file scans but can miss legacy imports hidden behind custom prefixes.
react_on_rails/spec/react_on_rails/locales_to_js_spec.rb Adds coverage for the intended modern-file behavior where later defineMessages text does not force regeneration.

Reviews (1): Last reviewed commit: "Avoid full locale default obsolete scan" | Re-trigger Greptile

Comment thread react_on_rails/lib/react_on_rails/locales/to_js.rb Outdated
@justin808
justin808 force-pushed the codex/g4-4345-locales branch from c889da5 to faa56a0 Compare July 2, 2026 10:12
@justin808

Copy link
Copy Markdown
Member Author

Current-head rebase validation for faa56a04aab6a0bb1c9c48ffafaeabc30f7f6f39 on origin/main a6c5867d9e0bba84592b9ead412cee7217b4ec4f:

  • cd react_on_rails && bundle exec rspec spec/react_on_rails/locales_to_js_spec.rb -> 12 examples, 0 failures
  • cd react_on_rails && RUBYOPT=-W0 BUNDLE_GEMFILE=../Gemfile bundle exec rubocop lib/react_on_rails/locales/to_js.rb spec/react_on_rails/locales_to_js_spec.rb -> no offenses
  • git diff --check origin/main...HEAD -> pass
  • git push --force-with-lease origin codex/g4-4345-locales -> pre-push branch lint passed

@justin808

Copy link
Copy Markdown
Member Author

+ci-status

@justin808

Copy link
Copy Markdown
Member Author

+ci-run-hosted

@justin808

Copy link
Copy Markdown
Member Author

Address-review status

Scan scope: full PR review history after claude-review remained pending for the 180-second bounded wait.

Mattered

  • Greptile P2 on prefixed legacy react-intl imports was addressed in f41644c82 with a focused regression test.

Optional

  • None.

Skipped

  • None.

Non-cutoff status only because claude-review was still pending when triage proceeded. The next review pass must use check all reviews.

@justin808

Copy link
Copy Markdown
Member Author

+ci-status

@justin808

Copy link
Copy Markdown
Member Author

+ci-run-hosted

@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

CI Status

Head SHA: f41644c82d3d
Changed files: 2
Docs-only heuristic (matches ci-changes-detector metadata paths): no
ready-for-hosted-ci label: absent
force-full-hosted-ci label: absent
Current hosted-CI waiver: not present for this SHA

Only the required gate is active unless hosted CI is requested.

@claude

claude Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Review summary

Small, well-tested fix that stops generated_files_obsolete? from reading and regex-scanning the entire default.js file, and instead inspects only the first significant (non-blank) line(s). The two new specs (legacy-with-preamble, current-format-not-fully-read) clearly document the intended behavior change, and the underlying template (template_default in base.rb) never emits a preamble, so the common case is unaffected.

One inline note on GENERATED_PREAMBLE_LINE (react_on_rails/lib/react_on_rails/locales/to_js.rb) — worth a look.

Missing CHANGELOG entry: This is a user-visible bug fix (stale/legacy default.js locale files could previously fail to regenerate correctly, or get incorrectly flagged, depending on file content past the first line). Per AGENTS.md ("Update /CHANGELOG.md for user-visible changes only (features, bug fixes, breaking changes, deprecations, performance improvements)"), this looks like it qualifies and I don't see an entry added for it (nor a reference to #4345) in CHANGELOG.md's [Unreleased] section.

Nothing else stood out — no security implications, and the Errno::ENOENT rescue / obsolete? contract in base.rb are preserved correctly.

Comment thread react_on_rails/lib/react_on_rails/locales/to_js.rb Outdated
Comment thread react_on_rails/lib/react_on_rails/locales/to_js.rb Outdated
@justin808

Copy link
Copy Markdown
Member Author

+ci-status

@justin808

Copy link
Copy Markdown
Member Author

Address-review status

Scan scope: full PR review history after claude-review remained pending for the 180-second bounded wait.

Mattered

  • Duplicate Claude comments on GENERATED_PREAMBLE_LINE breadth were addressed in 5b00ab048 by narrowing detection to line comments plus explicit use strict / use client directives.

Optional

  • None.

Skipped

  • None.

Non-cutoff status only because claude-review was still pending when triage proceeded. The next review pass must use check all reviews.

@justin808

Copy link
Copy Markdown
Member Author

+ci-run-hosted

Comment thread react_on_rails/lib/react_on_rails/locales/to_js.rb Outdated
@claude

claude Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Review

This PR fixes the generated_files_obsolete? check in Locales::ToJs so it no longer reads the entire default.js file and scans for a legacy react-intl import on every line (the old regex used an unanchored ^, so it could match the import string anywhere in the file, including inside generated translation content). The new version streams the file with File.foreach, inspects only the leading significant line(s) (tolerating a comment/"use strict" preamble on older legacy templates) via LEGACY_DEFAULT_IMPORT/GENERATED_PREAMBLE_LINE, and bails out as soon as it sees real content that isn't the legacy import. Good regression coverage was added, including a test that asserts File.read is never called for a current-format file.

Correctness: I traced the logic against the actual generator template in base.rb#template_default (which never emits a comment/use strict preamble) and against the new legacy-preamble test case — both classify correctly. No file-handle leak from the early return inside the File.foreach block (Ruby's IO.foreach closes the file in an ensure regardless of non-local exits), and the regexes are simple/linear with no ReDoS risk. obsolete?/generated_files_obsolete? have no other callers, so no cross-file breakage.

Minor nit (left inline): the \*/ alternative in GENERATED_PREAMBLE_LINE's alternation is unreachable — \* already matches any line \*/ would match, since Ruby/Onigmo alternation is ordered and stops at the first successful alternative. Not a bug, just dead code that can be dropped.

Overall this is a solid, well-tested fix with no functional issues found.

Comment thread react_on_rails/lib/react_on_rails/locales/to_js.rb
Comment thread react_on_rails/lib/react_on_rails/locales/to_js.rb Outdated
@claude

claude Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Review summary

Solid, well-scoped fix: switches the default.js obsolete-check from a full File.read + unanchored match? scan to a File.foreach line-by-line scan that anchors detection to the file's leading content, plus good regression coverage (including a spec that asserts File.read is never called on default.js).

I verified the core logic against the actual template history (base.rb::template_default, before/after PR #4146):

  • Current template's first line is const defaultLocale = ...; → correctly short-circuits to "not obsolete" on line 1, no full read.
  • Legacy (pre-Fix RSC-safe locale default messages output #4146) template's first line is literally import { defineMessages } from 'react-intl'; → correctly detected as obsolete on line 1.

So the primary real-world upgrade path (old gem version → new) is handled correctly and gets faster. Left two inline comments on to_js.rb:

  1. Detection is now narrower than before: the old unanchored scan found the legacy import anywhere in the file; the new line-by-line scan stops at the first line that isn't blank/comment/pragma/the import itself, so a legacy import preceded by any other content (not just the exact templates this gem generates) would now silently be treated as "up to date" and never get migrated. Low real-world likelihood given the known template shapes, but a silent-failure mode worth confirming is intentional.
  2. Speculative preamble handling: the // comment / 'use client'/'use strict' pragma matching doesn't correspond to any preamble this gem's generator has ever actually produced (per git history of template_default). Worth a short comment explaining the real-world case it's guarding against, or simplifying it away.

Also: no CHANGELOG.md entry. Per .claude/docs/changelog-guidelines.md, bug fixes and performance improvements should get one — this fixes #4345 and changes the runtime behavior/perf of locale generation's obsolete check, so it likely qualifies for a #### Fixed entry similar to the #4146 one.

No security concerns (pure local file-generation logic, no external input). No other correctness issues found in the regex anchoring, blank-line handling, or Errno::ENOENT rescue path.

@justin808

Copy link
Copy Markdown
Member Author

Review-fix update for PR #4398 after current-head Claude comments.

Handled threads:

  • PRRT_kwDOAnNnU86N3r61 / comment 3512504727: fixed by preserving legacy-import detection through custom content until the current generated const defaultLocale = marker; added focused regression coverage.
  • PRRT_kwDOAnNnU86N3sE2 / comment 3512505526: fixed by removing the preamble-specific regex and documenting the simpler behavior through code shape plus tests.

Validation on pushed commit 5f7a3317a:

  • cd react_on_rails && bundle exec rspec spec/react_on_rails/locales_to_js_spec.rb
  • cd react_on_rails && RUBYOPT=-W0 BUNDLE_GEMFILE=../Gemfile bundle exec rubocop lib/react_on_rails/locales/to_js.rb spec/react_on_rails/locales_to_js_spec.rb
  • git diff --check origin/main...HEAD && git diff --check
  • pre-commit and pre-push hooks

This is a non-cutoff status because a new push requeued current-head hosted gates/review.

@justin808

Copy link
Copy Markdown
Member Author

+ci-status

@justin808

Copy link
Copy Markdown
Member Author

+ci-run-hosted

@github-actions github-actions Bot added the ready-for-hosted-ci Run optimized hosted GitHub CI for this PR label Jul 2, 2026
@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Hosted CI Requested

Triggered 9 workflow(s) for 5f7a3317a3c1.
Mode: optimized hosted CI (path-selected by script/ci-changes-detector).
Added ready-for-hosted-ci, so future commits will keep running optimized hosted CI until +ci-stop-hosted is used.

View progress in the Actions tab.

1 similar comment
@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Hosted CI Requested

Triggered 9 workflow(s) for 5f7a3317a3c1.
Mode: optimized hosted CI (path-selected by script/ci-changes-detector).
Added ready-for-hosted-ci, so future commits will keep running optimized hosted CI until +ci-stop-hosted is used.

View progress in the Actions tab.

@justin808
justin808 added this pull request to the merge queue Jul 2, 2026
Merged via the queue into main with commit 900c454 Jul 2, 2026
114 checks passed
@justin808
justin808 deleted the codex/g4-4345-locales branch July 2, 2026 22:11
justin808 added a commit that referenced this pull request Jul 2, 2026
…nsport

* origin/main:
  Avoid full locale default obsolete scans (#4398)
justin808 added a commit that referenced this pull request Jul 3, 2026
…cache-4317

* origin/main:
  Preserve streaming LoadError during dependency failures (#4388)
  Wire eslint-rules RuleTester suite into a runner, CI, and knip (#4409) (#4433)
  Handle fire-and-forget RSCRoute retry failures (#4378)
  Fix visible hydration cleanup for detached roots (#4374)
  Avoid full locale default obsolete scans (#4398)
  Document RSC public-page validation and sidecar patterns (#4387)

# Conflicts:
#	CHANGELOG.md
justin808 added a commit that referenced this pull request Jul 3, 2026
…derer-shutdown-restart

* origin/main:
  Preserve streaming LoadError during dependency failures (#4388)
  Wire eslint-rules RuleTester suite into a runner, CI, and knip (#4409) (#4433)
  Handle fire-and-forget RSCRoute retry failures (#4378)
  Fix visible hydration cleanup for detached roots (#4374)
  Avoid full locale default obsolete scans (#4398)
justin808 added a commit that referenced this pull request Jul 3, 2026
* origin/main:
  Preserve streaming LoadError during dependency failures (#4388)
  Wire eslint-rules RuleTester suite into a runner, CI, and knip (#4409) (#4433)
  Handle fire-and-forget RSCRoute retry failures (#4378)
  Fix visible hydration cleanup for detached roots (#4374)
  Avoid full locale default obsolete scans (#4398)
  Document RSC public-page validation and sidecar patterns (#4387)
  Remove dead methods; prune always-false Rails<5.0 spec branches (#4418) (#4431)
justin808 added a commit that referenced this pull request Jul 3, 2026
…-4364

* origin/main: (24 commits)
  Preserve streaming LoadError during dependency failures (#4388)
  Wire eslint-rules RuleTester suite into a runner, CI, and knip (#4409) (#4433)
  Handle fire-and-forget RSCRoute retry failures (#4378)
  Fix visible hydration cleanup for detached roots (#4374)
  Avoid full locale default obsolete scans (#4398)
  Document RSC public-page validation and sidecar patterns (#4387)
  Remove dead methods; prune always-false Rails<5.0 spec branches (#4418) (#4431)
  Drop deprecation-tombstone config options for 17.0.0 (#4419) (#4432)
  Add mechanical parity guards for Ruby↔TS protocol constants (#4412) (#4427)
  Move Node tsconfigs from @tsconfig/node14 to @tsconfig/node18 (#4410) (#4429)
  [Pro] Remove unused addressable and rainbow runtime deps from gemspec (#4416) (#4422)
  Delete finished #3313 Prism Gemfile-rewriter spike (#4421)
  Extract generator scan/tracking helpers (#4405) (#4430)
  Extract install_dependency_group helper in JsDependencyManager (#4403) (#4424)
  Remove obsolete Ruby<2.6 YAML-aliases capability shim (#4417) (#4428)
  Remove inert config.server_render_method option (#4415) (#4423)
  Prune stale knip ignores and enforce binaries in CI (#4408) (#4425)
  Extract shared redux_store kwargs validator (#4402) (#4420)
  Avoid caching async props prerender streams (#4376)
  Release incremental render context on setup failure (#4383)
  ...

# Conflicts:
#	CHANGELOG.md
@justin808 justin808 mentioned this pull request Jul 7, 2026
4 tasks
justin808 added a commit that referenced this pull request Jul 7, 2026
## Summary

Stamps the `17.0.0.rc.7` changelog header and adds the user-visible
entries merged into `release/17.0.0` since `v17.0.0.rc.6` that were not
yet reflected in `CHANGELOG.md`:

- **Fixed**: OSS renders no longer compute/emit Pro-only
generated-stylesheet metadata (#4395)
- **Fixed**: `create_render_options` no longer mutates the caller's
options hash (#4396)
- **Fixed**: locale-file regeneration check no longer reads the whole
file and correctly detects a legacy import after custom content (#4398)
- **Changed**: `[Pro]` removed unused `addressable`/`rainbow` runtime
gem dependencies (#4422)
- **Fixed**: `[Pro]` static RSC payload script stripping is robust to
generated body-shape changes (#4477)
- Updated the existing `create-react-on-rails-app` chalk→picocolors
entry to also credit the color-fallback-parity follow-up (#4473)
- Updated the existing Pro-by-default `create-react-on-rails-app` entry
to also credit the matching `prompts.yml` AI-agent prompt update (#4232)

Ran the classification-sweep helper over
`v17.0.0.rc.6..origin/release/17.0.0` (175 merged PRs, no `UNKNOWN`
rows) and cross-checked every PR number against the current changelog to
find the gaps above; everything else in range was either already
documented or is internal/docs/CI/release-process and intentionally
excluded per the changelog policy.

## Test plan

- [x] `bundle exec rake "update_changelog[rc]"` computed and stamped
`17.0.0.rc.7` from git tags, updated compare links
- [x] Verified `[unreleased]` and `[17.0.0.rc.7]` compare links anchor
correctly
- [x] Verified `CHANGELOG.md` ends with a trailing newline
- [x] Pre-commit/pre-push hooks (prettier, trailing-newlines,
markdown-links) passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-for-hosted-ci Run optimized hosted GitHub CI for this PR

Projects

None yet

1 participant