Search code examples
iocapistranocapistrano3

How to ask for user input when running ruby code on remote server with capistrano?


I want to confirm the action when running a capistrano task on a remote server:

task :do_someting do
  on roles(:primary) do
    within release_path do
      with rails_env: fetch(:rails_env) do
        execute :rails, :runner,
          %Q['require "do_something"; Do::Something.()']
      end
    end
  end
end

Where `DoSomethig looks like this:

require "highline/import"

class DoSomething

  def self.call
    query_db_for_objects.each do |obj|
      answer = ask "Are you sure to do something with #{obj}? (y/n)"
      rerun unless answer == 'y'
      do_something
    end
  end

end

Method ask from highline gem doesn't seem to work when asking from a remote server and the command bundle exec cap production do_something hangs forever.

How can I ask for a user input from a remote server when running this capistrano task?


Solution

  • I was able to read the user answer from a remote server with the following ruby code

    task :do_someting do
    
      class ConfirmHandler
        def on_data(command, stream_name, data, channel)
          if data.to_s =~ /\?$/
            prompt = Net::SSH::Prompt.default.start(type: 'confirm')
            response = prompt.ask "Please enter your response (y/n)"
            channel.send_data "#{response}\n"
          end
        end
      end
    
      on roles(:primary) do
        within release_path do
          with rails_env: fetch(:rails_env) do
            execute :rails, :runner,
              %Q['require "do_something"; Do::Something.()']
          end
        end
      end
    
    end
    

    where Do::Something has ask_user method which looks the following way:

    class Do::Something
    
      def self.call
        answer = ask_user
        puts "Answer is: #{answer}"
      end
    
      def self.ask_user
        puts 'Do something?'
        `read response; echo $response`
      end
    
    end