Skip to content

Fix install generator --pretend side effects and crash#2536

Merged
justin808 merged 10 commits intomasterfrom
codex/fix-2490-pretend-generator
Mar 8, 2026
Merged

Fix install generator --pretend side effects and crash#2536
justin808 merged 10 commits intomasterfrom
codex/fix-2490-pretend-generator

Conversation

@justin808
Copy link
Copy Markdown
Member

@justin808 justin808 commented Mar 5, 2026

Summary

Fixes rails g react_on_rails:install --pretend so it behaves like a real dry run.

  • Skip automatic Shakapacker installation when running in --pretend mode (prevents real bundle add/install and rails shakapacker:install side effects)
  • Skip raw File.chmod in add_bin_scripts during --pretend (prevents Errno::ENOENT crash when files are not created)
  • Add regression tests for both code paths

Fixes #2490

Testing

  • bundle exec rspec react_on_rails/spec/react_on_rails/generators/install_generator_spec.rb
  • bundle exec rspec react_on_rails/spec/react_on_rails/generators/install_generator_spec.rb:1019 react_on_rails/spec/react_on_rails/generators/install_generator_spec.rb:1032
  • bundle exec rubocop react_on_rails/lib/generators/react_on_rails/install_generator.rb react_on_rails/spec/react_on_rails/generators/install_generator_spec.rb

Note

Low Risk
Small, well-scoped changes limited to generator side effects and tests; main risk is inadvertently skipping required setup outside --pretend, but behavior is gated on the option.

Overview
Fixes react_on_rails:install to behave like a real dry-run under --pretend by skipping automatic Shakapacker installation (avoids running bundle add/install and rails shakapacker:install) and avoiding File.chmod on bin scripts when files aren’t created.

Adds regression specs covering both pretend-mode paths (Shakapacker install skip message + no chmod).

Written by Cursor Bugbot for commit 206004e. Configure here.

Summary by CodeRabbit

  • Bug Fixes

    • Install generator's --pretend flag now performs a safe dry-run, skipping real installs and executable-permission changes to avoid side effects.
  • Tests

    • Added tests confirming pretend mode skips installation steps, chmods, config/type file creation, and emits pretend-status messages.
  • Documentation

    • Changelog entry describing the install generator's dry-run (--pretend) semantics.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 5, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds pretend-mode guards and option propagation to the install and base generators so shell commands, raw File.chmod calls, and several install-related creation steps are skipped and report pretend-status messages when --pretend is used; tests and changelog updated to reflect the dry-run semantics.

Changes

Cohort / File(s) Summary
Changelog
CHANGELOG.md
Added entry documenting that the install generator's --pretend performs a safe dry run and skips actual Shakapacker installation and raw chmod operations.
Generator code
react_on_rails/lib/generators/react_on_rails/base_generator.rb, react_on_rails/lib/generators/react_on_rails/install_generator.rb
Propagated options[:pretend] to sub-generators and added guards/early-exits to skip executing shell commands, avoid raw File.chmod on files that may not exist in pretend mode, and bypass certain install/file-creation steps; emit pretend-status messages.
Specs / Tests
react_on_rails/spec/react_on_rails/generators/base_generator_spec.rb, react_on_rails/spec/react_on_rails/generators/install_generator_spec.rb
Added tests asserting pretend-mode behavior: shell commands and chmod are not executed, TS/CSS type generation and tsconfig writes are skipped, and pretend-status messages are emitted.

Sequence Diagram

sequenceDiagram
    participant User
    participant Generator
    participant ShellCmd
    participant FileSystem

    User->>Generator: run generator (rails g react_on_rails:install [--pretend])
    
    rect rgba(100,150,255,0.5)
    Note over Generator: Normal mode (no --pretend)
    Generator->>ShellCmd: run bundle add / bundle install / rails shakapacker:install
    ShellCmd->>FileSystem: modify Gemfile, install gems, create shakapacker files
    Generator->>FileSystem: File.chmod bin scripts
    Generator-->>User: report installation complete
    end

    rect rgba(255,150,100,0.5)
    Note over Generator: Pretend mode (--pretend)
    Generator->>Generator: check options[:pretend]
    Generator-->>ShellCmd: skip shell commands (pretend)
    Generator-->>FileSystem: skip file writes & File.chmod (pretend)
    Generator-->>User: emit pretend-status messages / show preview
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

  • #2422 — Tests/changes touch ensure_shakapacker_installed; this PR's pretend guards relate to install flow and may overlap with post-install handling discussed in that issue.

Poem

🐰 I hopped through lines with gentle paws,
Skipping installs and chmods because,
When --pretend whispers soft and light,
I show the plan and do not bite.
A safe dry-run — hop, preview, delight!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ 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%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ 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 accurately summarizes the main changes: fixing --pretend mode side effects and crashes in the install generator, which is the primary focus of all code modifications.
Linked Issues check ✅ Passed The PR fully addresses issue #2490: guards shell commands with pretend checks [ensure_shakapacker_installed], guards File.chmod with pretend checks [add_bin_scripts], and includes comprehensive regression tests for both pretend-mode behaviors.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing --pretend behavior: propagating pretend option through generators, adding pretend guards to side-effect operations, and adding related test coverage. No extraneous modifications detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch codex/fix-2490-pretend-generator

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.

@justin808 justin808 self-assigned this Mar 5, 2026
@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Mar 5, 2026

Greptile Summary

This PR fixes two --pretend (dry-run) mode bugs in InstallGenerator. It adds an early return inside ensure_shakapacker_installed when options[:pretend] is true so that no real bundle add/bundle install/rails shakapacker:install commands are executed, and it guards the raw File.chmod call in add_bin_scripts with unless options[:pretend] to prevent an Errno::ENOENT crash when the bin files were never actually written. Two focused regression specs are added to cover both paths.

  • ensure_shakapacker_installed: Early return with a say_status notification when --pretend is active, preventing all four real side-effect methods from being called.
  • add_bin_scripts: File.chmod is now skipped in pretend mode; the preceding directory and gsub_file calls are Thor generator actions that already natively respect --pretend.
  • Tests: New describe "--pretend mode behavior" block with unit-level specs for both changed methods, using appropriate stubs and send to access private methods.

Confidence Score: 5/5

  • This PR is safe to merge — changes are minimal, targeted, and do not alter any non-pretend-mode behavior.
  • Both fixes are single-line or short guard additions that only activate when options[:pretend] is true, leaving the normal execution path completely unchanged. The regression tests correctly exercise both code paths. No new dependencies or public API changes are introduced.
  • No files require special attention.

Important Files Changed

Filename Overview
react_on_rails/lib/generators/react_on_rails/install_generator.rb Adds two targeted --pretend guards: an early return in ensure_shakapacker_installed to skip real side-effect commands, and an unless options[:pretend] guard on File.chmod to prevent an Errno::ENOENT crash. Both changes are minimal, correct, and well-placed.
react_on_rails/spec/react_on_rails/generators/install_generator_spec.rb Adds a new --pretend mode behavior describe block with two regression tests: one verifying that no Shakapacker installation methods are invoked (and say_status is called), and one verifying that File.chmod is not called. Tests use appropriate stubbing for the unit-level isolation.

Sequence Diagram

sequenceDiagram
    participant User
    participant InstallGenerator
    participant FileSystem as FileSystem / Bundler

    User->>InstallGenerator: rails g react_on_rails:install --pretend

    InstallGenerator->>InstallGenerator: ensure_shakapacker_installed()
    InstallGenerator->>InstallGenerator: shakapacker_configured? → false
    InstallGenerator->>InstallGenerator: options[:pretend]? → true
    InstallGenerator-->>User: say_status(:pretend, "Skipping...")
    Note over FileSystem: bundle add / bundle install / rails shakapacker:install — NOT run

    InstallGenerator->>InstallGenerator: add_bin_scripts()
    InstallGenerator->>InstallGenerator: directory(...) — Thor pretend-aware, logs only
    InstallGenerator->>InstallGenerator: Dir.chdir / Dir.glob → collect filenames
    InstallGenerator->>InstallGenerator: options[:pretend]? → skip File.chmod
    Note over FileSystem: No files created, no chmod executed
Loading

Last reviewed commit: b0c71a5

@justin808 justin808 added P1 Target this sprint bug release:16.4.0-must-have Must-have for 16.4.0: critical bug/perf/usability runtime-fix User-facing behavior fix labels Mar 5, 2026
@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Mar 5, 2026

Review: Fix install generator --pretend side effects and crash

The fix is well-scoped and correctly addresses the two reported issues from #2490. Guarding raw Ruby file operations with options[:pretend] is the right pattern when Thor actions cannot be used.

What is done well

  • The ordering in ensure_shakapacker_installed is correct: returning early if Shakapacker is already configured before checking options[:pretend], so pretend mode only intercepts the install path.
  • File.chmod is a raw Ruby call that completely bypasses Thor's pretend mechanism, so the unless options[:pretend] guard is necessary and correct.
  • Tests are unit-level and targeted, directly exercising the private methods rather than running the full generator.

Potential issues / follow-ups

Issue 1 - Other raw file operations are still not pretend-safe (pre-existing, worth tracking)

The same class has additional raw file/dir operations not guarded by options[:pretend]:

  • Line 347: File.write in finalize_shakapacker_setup. Safe for this PR because it is only reachable via ensure_shakapacker_installed, which now returns early in pretend mode. Fragile if the call chain changes later.
  • Line 426: FileUtils.mkdir_p for app/javascript/types
  • Line 446: File.write for app/javascript/types/css-modules.d.ts
  • Line 477: File.write for tsconfig.json

These are pre-existing issues but would still cause real filesystem side effects under --pretend. Worth a follow-up issue.

Issue 2 - add_bin_scripts test does not stub use_rsc?

The test does not stub use_rsc? or gsub_file. Because the generator is initialized without --rsc, use_rsc? returns false and the gsub_file branch is skipped today. Explicitly stubbing use_rsc? to return false would make the test intent clearer and prevent future breakage if default option handling changes.

Issue 3 - Dir.glob is globally mocked in the chmod test

allow(Dir).to receive(:glob).with('*') applies globally for the test duration. Likely fine in practice but broader than needed.


Overall this is a correct, minimal fix. The issues above are minor or pre-existing and should not block merging.

Comment thread react_on_rails/lib/generators/react_on_rails/install_generator.rb Outdated
@justin808 justin808 force-pushed the codex/fix-2490-pretend-generator branch from b0c71a5 to b8ee23e Compare March 5, 2026 08:12
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b8ee23ec46

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread react_on_rails/lib/generators/react_on_rails/install_generator.rb
@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Mar 5, 2026

Review: Fix install generator --pretend side effects and crash

This is a well-scoped, correct fix. The crashes and side effects in --pretend mode are real bugs and the guards are placed appropriately.

Overall assessment

The core changes are sound:

  • ensure_shakapacker_installed: pretend guard correctly placed after shakapacker_configured? check and before destructive commands.
  • add_bin_scripts: File.chmod guard is correct — Thor's directory/gsub_file handle pretend natively, but File.chmod does not.
  • create_css_module_types / create_typescript_config: FileUtils/File calls are correctly guarded.

Minor inconsistencies

  1. Inconsistent pretend feedback across methods. ensure_shakapacker_installed emits a yellow say_status message in pretend mode. But create_typescript_config returns silently when tsconfig.json does not exist, giving the user no indication of what would have been created. The pattern from ensure_shakapacker_installed is better UX and worth applying consistently.

  2. create_css_module_types prints the activity message before the pretend guard. The puts Rainbow line fires before return if options[:pretend], so the user sees a start message but no completion and no pretend annotation. This can look like the method crashed silently. The guard (or a pretend-aware message) should come first.

  3. add_bin_scripts test accesses the real template directory. The spec stubs directory and use_rsc? but lets Dir.chdir(template_bin_path) / Dir.glob hit the filesystem. This works because the templates are present in the repo, but it couples the unit test to the layout. Not a blocker.

None of these are regressions — the actual bugs (crash and side effects) are fixed correctly.

Comment thread react_on_rails/lib/generators/react_on_rails/install_generator.rb Outdated
Comment thread react_on_rails/lib/generators/react_on_rails/install_generator.rb Outdated
@justin808 justin808 force-pushed the codex/fix-2490-pretend-generator branch from 3f8001d to 8ef0385 Compare March 5, 2026 08:38
@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Mar 5, 2026

Review Summary

The core fix is well-scoped and correct — adding unless options[:pretend] guards to File.chmod calls in both generators eliminates the Errno::ENOENT crash, and the early return in ensure_shakapacker_installed prevents real bundle/install side-effects. The tests cover the new code paths.

A few issues worth addressing:


Bug: install_typescript_dependencies still runs in pretend mode

When using --typescript --pretend, install_typescript_dependencies (install_generator.rb:416–420) still calls add_typescript_dependencies, which delegates to add_packages / add_npm_dependencies and executes real npm/yarn/pnpm commands. The other two TypeScript helpers (create_css_module_types, create_typescript_config) were guarded, but this one was missed.

# invoke_generators (line ~118)
if options.typescript?
  install_typescript_dependencies   # ← no pretend guard, runs npm install
  create_css_module_types           # ← guarded ✓
  create_typescript_config          # ← guarded ✓
end

Recommend adding the same guard to install_typescript_dependencies, or centralising the check at the call site in invoke_generators.


Minor: create_typescript_config checks file existence before the pretend check (install_generator.rb:456–464)

def create_typescript_config
  if File.exist?("tsconfig.json")   # runs in pretend mode too
    puts Rainbow("⚠️  tsconfig.json already exists, skipping creation").yellow
    return
  end

  if options[:pretend]
    say_status :pretend, "Would create tsconfig.json ...", :yellow
    return
  end

In pretend mode with no existing tsconfig.json this is fine. But if tsconfig.json exists and you're in pretend mode, the user sees the "already exists" message rather than any pretend-mode indicator. More importantly, the live File.exist? call happens on every pretend run. Swapping the order (pretend check first, then existence check) would be cleaner and consistent with create_css_module_types.


Nit: test for create_css_module_types stubs methods that the code under test never reaches

it "does not create css module type files in pretend mode" do
  allow(FileUtils).to receive(:mkdir_p)   # ← unreachable in pretend mode
  allow(File).to receive(:write)          # ← unreachable in pretend mode
  ...
end

The method returns before FileUtils.mkdir_p or File.write are called, so the allow stubs are unnecessary. Removing them (and keeping only the negative not_to have_received assertions, which can be dropped since the call path is unreachable) would make the test intention clearer. Minor — not a correctness issue.


Overall this is a good, minimal fix for a real user-facing crash. The install_typescript_dependencies gap is the only functional concern worth addressing before merge.

Comment thread react_on_rails/lib/generators/react_on_rails/install_generator.rb
Comment thread react_on_rails/lib/generators/react_on_rails/install_generator.rb Outdated
Comment thread react_on_rails/lib/generators/react_on_rails/install_generator.rb
@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Mar 5, 2026

Review Summary

The fix is well-scoped and correctly addresses the reported --pretend side effects. A few notes:

What's good

  • All three raw File.chmod calls that bypass Thor's pretend mode are now guarded correctly (base_generator.rb and install_generator.rb).
  • Skipping ensure_shakapacker_installed in pretend mode prevents the real bundle add / bundle install / rails shakapacker:install execution and the resulting .shakapacker_just_installed marker file from ever being written.
  • The new guards on create_css_module_types and create_typescript_config close two more pretend-mode gaps for TypeScript setups.
  • Test coverage is solid — unit tests for each code path, with correct use of expect(...).not_to receive / not_to have_received assertions.

Minor issues

create_typescript_config guard ordering (install_generator.rb)
The File.exist?("tsconfig.json") check (a read-only operation, so safe in pretend mode) runs before the pretend guard. As a result, when running --pretend with an existing tsconfig, the user sees the puts "⚠️ tsconfig.json already exists…" message instead of a say_status :pretend one. Semantics are correct, but the output style is inconsistent with the rest of the pretend output. Low priority.

Pre-existing gap: handle_custom_webpack_config (base_generator.rb, line 215)
FileUtils.cp(webpack_config_path, backup_path) is a raw file-system call with no pretend guard. This code path is only reached when the user explicitly answers "yes" to the interactive prompt, but in pretend mode that still creates a real backup file. This was not introduced by this PR, but it's now the most visible remaining gap. Worth a follow-up issue/PR.

Verdict

The core bug fix is correct and complete for the reported crash and side effects. The pre-existing webpack-config gap is out of scope here. Approving with the minor notes above for follow-up.

Honor --pretend by skipping automatic shakapacker installation commands and raw chmod calls that can crash when files are not written in dry-run mode. Add focused regression specs for both paths.
Document the install generator dry-run fix in Unreleased with PR reference.
Address review feedback by making the add_bin_scripts test explicit about non-RSC behavior and removing global Dir stubs. Also guard TypeScript file writes in pretend mode to prevent dry-run filesystem side effects.
Prevent pretend-mode chmod crash in BaseGenerator, add pretend status messages for TypeScript file generation, and add regression specs covering these paths.
@justin808 justin808 force-pushed the codex/fix-2490-pretend-generator branch from 8ef0385 to 6c9af04 Compare March 6, 2026 04:34
@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Mar 6, 2026

Overall: Good, well-scoped fix for the reported --pretend crash. The core changes are correct and test coverage is reasonable.

What works well: Guards on File.chmod in both install_generator.rb and base_generator.rb directly fix the Errno::ENOENT crash. The ensure_shakapacker_installed pretend guard prevents bundle add/install and rails shakapacker:install side effects. Guards on create_css_module_types and create_typescript_config prevent raw File.write/FileUtils.mkdir_p calls in pretend mode.

One gap: install_typescript_dependencies is not guarded. In invoke_generators (~line 132), when --pretend --typescript is passed, install_typescript_dependencies executes before create_css_module_types and create_typescript_config. The latter two are now guarded but install_typescript_dependencies is not — it calls add_typescript_dependencies -> add_packages -> add_npm_dependencies, which runs real npm/yarn commands. This is the same class of side effect as the Shakapacker installation that is correctly skipped. See inline comment.

Pre-existing issue (out of scope): handle_custom_webpack_config in base_generator.rb line 223 has FileUtils.cp(webpack_config_path, backup_path) without a pretend guard — worth a follow-up.

Comment thread react_on_rails/lib/generators/react_on_rails/install_generator.rb
add_typescript_dependencies
end

def create_css_module_types
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

These two methods (create_css_module_types and create_typescript_config) use raw FileUtils.mkdir_p and File.write instead of Thor actions like empty_directory and create_file. The pretend guard here fixes the crash, but it produces a static status message rather than Thor's built-in "would create ..." output that users expect from a dry run.

Converting to Thor actions would make --pretend work natively without any explicit guard:

def create_css_module_types
  say Rainbow("📝 Creating CSS module type definitions...").yellow
  empty_directory "app/javascript/types"
  create_file "app/javascript/types/css-modules.d.ts", css_module_types_content
end

Not a blocker for this PR (the guard is correct as-is), but worth a follow-up since this is the root cause of why the guard is needed at all.

end

def setup_react_dependencies
if options[:pretend]
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The same if options[:pretend] / say_status / return pattern now appears 6+ times in this file and once in base_generator.rb. Consider extracting a private helper to eliminate the repetition:

def skip_in_pretend_mode!(message)
  return false unless options[:pretend]
  say_status :pretend, "#{message} in --pretend mode", :yellow
  true
end

Then each guard becomes a single line, e.g.:

def setup_react_dependencies
  return if skip_in_pretend_mode!("Skipping React dependency setup")
  setup_js_dependencies
end

install_generator.send(:create_typescript_config)
end

it "forwards pretend mode to base and react_no_redux generators" do
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The TypeScript install branch (install_typescript_dependencies, create_css_module_types, create_typescript_config) is skipped here because install_generator has no typescript: true, but this is implicit. Adding a negative expectation would make the test intent explicit and guard against accidental regressions if the default ever changes:

expect(install_generator).not_to receive(:install_typescript_dependencies)

@justin808 justin808 merged commit ba332de into master Mar 8, 2026
40 checks passed
@justin808 justin808 deleted the codex/fix-2490-pretend-generator branch March 8, 2026 02:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug P1 Target this sprint release:16.4.0-must-have Must-have for 16.4.0: critical bug/perf/usability runtime-fix User-facing behavior fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

rails g react_on_rails:install --pretend runs shell commands for real and crashes

1 participant