Skip to content

Generator inherits BUNDLE_GEMFILE from parent process, causing 'injected gems' conflicts #2287

@ihabadham

Description

@ihabadham

A bug is a crash or incorrect behavior. If you have a debugging or troubleshooting question, please open a discussion.

Environment

  1. Ruby version: 3.2+ (tested on 3.3.7 and CI Ubuntu 22.04)
  2. Rails version: 7.x
  3. Shakapacker/Webpacker version: 8.x / 9.x
  4. React on Rails version: master (16.2.0.rc.0)

Expected behavior

When running the install generator via bundle exec rails g react_on_rails:install, the generator's internal bundle add shakapacker command should operate on the target app's Gemfile, not inherit the parent process's Bundler context.

Actual behavior

The generator's system("bundle add shakapacker --strict") call (and other bundle commands) inherit BUNDLE_GEMFILE from the parent process. This causes:

  1. In tests: The error appears repeatedly in CI logs:

    [!] There was an error parsing `injected gems`: You cannot specify the same gem twice with different version requirements.
    You specified: shakapacker (= 9.4.0) and shakapacker (>= 0). Gem already added.
     #  from .../dummy-for-generators/injected gems:1
    
  2. In production: If a user runs the generator via bundle exec rails g react_on_rails:install from within another bundled context, the same conflict can occur.

Evidence in CI

This error appears in master CI runs, e.g.:

Search for "injected gems" in the logs to see multiple occurrences.

Root cause

In lib/generators/react_on_rails/install_generator.rb, lines 355, 366, and 373:

success = system("bundle add shakapacker --strict")  # line 355
bundle_success = system("bundle install")            # line 366
success = system("bundle exec rails shakapacker:install")  # line 373

These system() calls inherit the environment, including BUNDLE_GEMFILE which points to the outer project's Gemfile when running via bundle exec.

Proposed fix

Wrap bundle commands in Bundler.with_unbundled_env to isolate them:

success = Bundler.with_unbundled_env { system("bundle add shakapacker --strict") }

This pattern is already used elsewhere in the codebase:

  • lib/react_on_rails/dev/process_manager.rb (lines 135-138)
  • lib/react_on_rails/dev/pack_generator.rb (lines 178-181)
  • rakelib/task_helpers.rb (lines 34-36, 89)

Small, reproducible repo

Not needed - reproducible in the main repo:

cd react_on_rails
bundle exec ruby -e "
  puts 'BUNDLE_GEMFILE inherited by child processes:'
  puts ENV['BUNDLE_GEMFILE']
  puts
  puts 'With Bundler.with_unbundled_env:'
  Bundler.with_unbundled_env { puts ENV['BUNDLE_GEMFILE'].inspect }
"

Output shows BUNDLE_GEMFILE points to outer project, but with_unbundled_env correctly clears it to nil.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions