Class: Ace::Test::EndToEndRunner::Molecules::SetupExecutor

Inherits:
Object
  • Object
show all
Defined in:
lib/ace/test/end_to_end_runner/molecules/setup_executor.rb

Overview

Executes setup steps deterministically to create a populated sandbox

Processes the setup array from scenario.yml, running each action via Ruby system calls (no LLM involved). Supports: git-init, copy-fixtures, run, write-file, agent-env, and tmux-session actions.

Note: This is a Molecule because it performs filesystem I/O and system calls via Open3 and FileUtils.

Constant Summary collapse

AMBIENT_TMUX_ENV_VARS =
%w[TMUX TMUX_PANE].freeze
BUNDLER_ENV_PREFIXES =
%w[BUNDLE BUNDLER].freeze
STRIPPED_ENV_KEYS =
%w[RUBYOPT RUBYLIB].freeze
RESERVED_ENV_KEYS =
Molecules::SandboxRuntimeBuilder::RESERVED_ENV_KEYS + %w[
  PATH HOME TMPDIR XDG_RUNTIME_DIR TMUX_TMPDIR ACE_TMUX_SESSION
]

Instance Method Summary collapse

Constructor Details

#initialize(command_runner: nil, system_runner: nil, time_source: nil, sandbox_backend: nil) ⇒ SetupExecutor

Returns a new instance of SetupExecutor.



27
28
29
30
31
32
# File 'lib/ace/test/end_to_end_runner/molecules/setup_executor.rb', line 27

def initialize(command_runner: nil, system_runner: nil, time_source: nil, sandbox_backend: nil)
  @command_runner = command_runner || method(:capture3)
  @system_runner = system_runner || method(:system)
  @time_source = time_source || -> { Time.now.to_i }
  @sandbox_backend = sandbox_backend
end

Instance Method Details

#execute(setup_steps:, sandbox_dir:, fixture_source: nil, scenario_name: nil, run_id: nil, initial_env: {}) ⇒ Hash

Execute all setup steps in a sandbox directory

Parameters:

  • setup_steps (Array)

    Setup steps from scenario.yml

  • sandbox_dir (String)

    Path to the sandbox directory

  • fixture_source (String, nil) (defaults to: nil)

    Path to the fixtures/ directory

  • scenario_name (String, nil) (defaults to: nil)

    Test ID for tmux session naming (e.g., “TS-OVERSEER-001”)

  • run_id (String, nil) (defaults to: nil)

    Unique run ID for deterministic tmux session naming

Returns:

  • (Hash)

    Result with :success, :steps_completed, :error, :env, :tmux_session keys



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/ace/test/end_to_end_runner/molecules/setup_executor.rb', line 42

def execute(setup_steps:, sandbox_dir:, fixture_source: nil, scenario_name: nil, run_id: nil, initial_env: {})
  FileUtils.mkdir_p(sandbox_dir)
  env = if @sandbox_backend
    @sandbox_backend.prepared_env(initial_env.dup)
  else
    initial_env.dup
  end
  steps_completed = 0
  @tmux_session = nil
  @scenario_name = scenario_name
  @run_id = run_id
  @teardown_env = nil

  setup_steps.each do |step|
    execute_step(step, sandbox_dir, env, fixture_source)
    steps_completed += 1
  end

  {
    success: true,
    steps_completed: steps_completed,
    error: nil,
    env: merged_environment(env),
    tmux_session: @tmux_session
  }
rescue => e
  {
    success: false,
    steps_completed: steps_completed,
    error: e.message,
    env: merged_environment(env),
    tmux_session: @tmux_session
  }
end

#teardownObject

Clean up resources created during setup (e.g. tmux session)



78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/ace/test/end_to_end_runner/molecules/setup_executor.rb', line 78

def teardown
  return unless @tmux_session

  if @sandbox_backend
    @sandbox_backend.capture3(
      ["tmux", "kill-session", "-t", @tmux_session],
      chdir: @teardown_env&.fetch("PROJECT_ROOT_PATH", Dir.pwd) || Dir.pwd,
      env: @teardown_env || {}
    )
  else
    @system_runner.call("tmux", "kill-session", "-t", @tmux_session, out: File::NULL, err: File::NULL)
  end
  @tmux_session = nil
end