Class: TalkToYourApp::Plugins::Rake::Tools::Run
- Defined in:
- lib/talk_to_your_app/plugins/rake/tools/run.rb
Overview
Runs a single allow-listed rake task and returns its status and output as JSON. The task must be on the plugin’s ‘allowed:` list; anything else is refused without executing. The task runs in a subprocess (`bundle exec rake`), so it cannot inject shell commands and its real exit status is captured.
Defined Under Namespace
Classes: Result
Class Method Summary collapse
- .app_root ⇒ Object
-
.run_task(task, rake_args) ⇒ Object
Executes ‘bundle exec rake <task>` in the app root.
Instance Method Summary collapse
Methods inherited from Tool
argument, arguments, connection, default_arguments, description, dispatch, input_schema_hash, invoke, name, normalize_response, to_mcp_definition, to_mcp_tool
Class Method Details
.app_root ⇒ Object
49 50 51 |
# File 'lib/talk_to_your_app/plugins/rake/tools/run.rb', line 49 def self.app_root defined?(Rails) && Rails.respond_to?(:root) ? Rails.root.to_s : Dir.pwd end |
.run_task(task, rake_args) ⇒ Object
Executes ‘bundle exec rake <task>` in the app root. Array argv (no shell) so task/args cannot inject shell commands.
43 44 45 46 47 |
# File 'lib/talk_to_your_app/plugins/rake/tools/run.rb', line 43 def self.run_task(task, rake_args) invocation = rake_args.empty? ? task : "#{task}[#{rake_args.join(",")}]" stdout, stderr, status = Open3.capture3("bundle", "exec", "rake", invocation, chdir: app_root) Result.new(stdout: stdout, stderr: stderr, exit_code: status.exitstatus || 1) end |
Instance Method Details
#call(args, _ctx) ⇒ Object
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
# File 'lib/talk_to_your_app/plugins/rake/tools/run.rb', line 23 def call(args, _ctx) task = args[:task].to_s unless TalkToYourApp::Plugins::Rake.allowed?(task) return error("Rake task #{task.inspect} is not allowed. Allowed tasks: #{TalkToYourApp::Plugins::Rake.allowed_tasks.inspect}.") end result = self.class.run_task(task, Array(args[:args]).map(&:to_s)) json( task: task, status: result.exit_code.zero? ? "success" : "error", exit_code: result.exit_code, output: result.stdout.strip, error: (result.stderr.strip.empty? ? nil : result.stderr.strip), ) rescue StandardError => e error("Failed to run rake #{args[:task]}: #{e.class}: #{e.}") end |