Skip to content

Conversation

@colby-swandale
Copy link
Member

Some Bundler tests currently spawn a subshell to invoke RubyGems. We're moving away from this pattern to speed up the test suite.

This PR refactors those tests to call the RubyGems API directly instead.

The ultimate prize is replacing the bundler and bundle helpers in the test suite entirely, but this serves as a good stepping stone towards that.

Copilot AI review requested due to automatic review settings December 15, 2025 11:35
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR refactors Bundler tests to invoke the RubyGems API directly instead of spawning subshells, improving test suite performance. The primary change removes the gem_command helper method and replaces all its usages with direct API calls to RubyGems classes.

  • Removes the gem_command helper that spawned subshells for gem operations
  • Refactors install_gem to use Gem::Installer.at API directly
  • Adds uninstall_gem and installed_gems_list helper methods that call RubyGems APIs

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
bundler/spec/support/helpers.rb Removes gem_command method; refactors install_gem to use Gem::Installer.at; adds new uninstall_gem and installed_gems_list helper methods for direct API calls
bundler/spec/support/builders.rb Replaces gem build subshell command with direct Gem::Package.build API call
bundler/spec/install/gems/compact_index_spec.rb Updates test to use new uninstall_gem helper instead of gem_command
bundler/spec/commands/clean_spec.rb Updates tests to use new installed_gems_list helper instead of gem_command :list
bundler/spec/commands/check_spec.rb Updates test to use new uninstall_gem helper instead of gem_command
bundler/spec/bundler/gem_helper_spec.rb Updates test to use new installed_gems_list helper instead of gem_command :list

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +359 to +376
# Temporarily set GEM_HOME for the command
old_gem_home = ENV["GEM_HOME"]
ENV["GEM_HOME"] = gem_home
Gem.clear_paths

begin
require "rubygems/commands/list_command"

# Capture output from the list command
output_io = StringIO.new
cmd = Gem::Commands::ListCommand.new
cmd.ui = Gem::StreamUI.new(StringIO.new, output_io, StringIO.new, false)
cmd.invoke
output = output_io.string.strip
ensure
ENV["GEM_HOME"] = old_gem_home
Gem.clear_paths
end
Copy link

Copilot AI Dec 15, 2025

Choose a reason for hiding this comment

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

The installed_gems_list method manually saves and restores ENV["GEM_HOME"], but this codebase has an established pattern for temporary environment variable modifications using the without_env_side_effects helper (see lines 393-415). Using this helper would be more consistent with the codebase's patterns and provide better safety guarantees, as it ensures all ENV changes are properly restored even if an exception occurs during the begin block.

Copilot uses AI. Check for mistakes.
Comment on lines +346 to +353
uninstaller = Gem::Uninstaller.new(
name,
install_dir: gem_home,
ignore: true,
executables: true,
all: true
)
uninstaller.uninstall
Copy link

Copilot AI Dec 15, 2025

Choose a reason for hiding this comment

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

The uninstall_gem method should temporarily set ENV["GEM_HOME"] to ensure Gem::Uninstaller operates on the correct gem installation directory. Without this, the uninstaller may not properly locate gems in the specified install_dir, especially when it differs from the current ENV["GEM_HOME"]. Consider wrapping the uninstaller logic with temporary ENV["GEM_HOME"] modification and Gem.clear_paths calls, similar to how installed_gems_list handles this.

Suggested change
uninstaller = Gem::Uninstaller.new(
name,
install_dir: gem_home,
ignore: true,
executables: true,
all: true
)
uninstaller.uninstall
old_gem_home = ENV["GEM_HOME"]
ENV["GEM_HOME"] = gem_home
Gem.clear_paths
begin
uninstaller = Gem::Uninstaller.new(
name,
install_dir: gem_home,
ignore: true,
executables: true,
all: true
)
uninstaller.uninstall
ensure
ENV["GEM_HOME"] = old_gem_home
Gem.clear_paths
end

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants