Class: Appraisal::Command

Inherits:
Object
  • Object
show all
Defined in:
lib/appraisal/command.rb

Overview

Executes commands with a clean environment

Constant Summary collapse

PRESERVED_BUNDLE_VARS =

BUNDLE_* environment variables that must be preserved for proper bundler operation and test isolation. These are preserved when using with_bundler_env to ensure:

  • Bundler version switching works (BUNDLE_GEMFILE)

  • Test isolation is maintained (BUNDLE_APP_CONFIG, etc.)

  • User settings are respected (BUNDLE_PATH, BUNDLE_USER_CACHE, etc.)

NOTE: BUNDLE_LOCKFILE is NOT preserved because:

  • Bundler automatically infers lockfile from BUNDLE_GEMFILE (e.g., foo.gemfile -> foo.gemfile.lock)

  • Forcing BUNDLE_LOCKFILE breaks appraisal’s ability to create per-gemfile lockfiles

  • Each appraisal needs its own lockfile, not the root Gemfile.lock

[
  "BUNDLE_GEMFILE",
  "BUNDLE_APP_CONFIG",
  "BUNDLE_PATH",
  "BUNDLE_USER_CONFIG",
  "BUNDLE_USER_CACHE",
  "BUNDLE_USER_PLUGIN",
  "BUNDLE_IGNORE_FUNDING_REQUESTS",
  "BUNDLE_DISABLE_SHARED_GEMS"
].freeze
PRESERVED_RUNTIME_VARS =
[
  "PATH",
  "GEM_PATH"
].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(command, options = {}) ⇒ Command

Returns a new instance of Command.



36
37
38
39
40
41
# File 'lib/appraisal/command.rb', line 36

def initialize(command, options = {})
  @gemfile = options[:gemfile]
  @env = options.fetch(:env, {})
  @skip_bundle_exec = options.fetch(:skip_bundle_exec, false)
  @command = @skip_bundle_exec ? command : command_starting_with_bundle(command)
end

Instance Attribute Details

#commandObject (readonly)

Returns the value of attribute command.



8
9
10
# File 'lib/appraisal/command.rb', line 8

def command
  @command
end

#envObject (readonly)

Returns the value of attribute env.



8
9
10
# File 'lib/appraisal/command.rb', line 8

def env
  @env
end

#gemfileObject (readonly)

Returns the value of attribute gemfile.



8
9
10
# File 'lib/appraisal/command.rb', line 8

def gemfile
  @gemfile
end

Instance Method Details

#runObject



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/appraisal/command.rb', line 43

def run
  run_env = test_environment.merge(env)

  if @skip_bundle_exec
    execute(run_env)
  else
    # For bundler version switching to work reliably, we need to preserve
    # the appraisal Gemfile while avoiding the active parent Bundler process.
    # However, we still need to isolate from the parent's bundler state
    # to avoid conflicts.
    #
    # Solution: Use a selective environment approach instead of with_original_env,
    # which strips all BUNDLE_* variables and breaks version switching.
    with_bundler_env do
      apply_run_env(run_env)
      ensure_bundler_is_available
      ensure_locked_bundler_is_available
      execute(run_env)
    end
  end
end