• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Nu-hin / remote_ruby / 13683852896

05 Mar 2025 07:21PM UTC coverage: 93.333% (-0.5%) from 93.882%
13683852896

push

github

Nu-hin
Refactor SSHAdapter

10 of 49 new or added lines in 1 file covered. (20.41%)

896 of 960 relevant lines covered (93.33%)

90.29 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

25.35
/lib/remote_ruby/ssh_adapter.rb
1
# frozen_string_literal: true
2

3
require 'net/ssh'
20✔
4
require 'remote_ruby/compat_io_reader'
20✔
5

6
module RemoteRuby
20✔
7
  # An adapter for executing Ruby code on a remote host via SSH
8
  class SSHAdapter < ConnectionAdapter
20✔
9
    UnableToExecuteError = Class.new(StandardError)
20✔
10

11
    attr_reader :host, :config, :working_dir, :user
20✔
12

13
    def initialize(host:, working_dir: nil, use_ssh_config_file: true, **params)
20✔
14
      super
×
15
      @host = host
×
16
      @working_dir = working_dir
×
17
      @config = Net::SSH.configuration_for(@host, use_ssh_config_file)
×
18

19
      @config = @config.merge(params)
×
20
      @user = @config[:user]
×
21
    end
22

23
    def open(code, stdin, stdout, stderr)
20✔
24
      ret = nil
×
25
      Net::SSH.start(host, nil, config) do |ssh|
×
26
        with_temp_file(code, ssh) do |fname|
×
27
          res = run_code(ssh, fname, stdin, stdout, stderr)
×
NEW
28
          ret = get_result(ssh, fname) if res.zero?
×
29
        end
30
      end
31
      ret
×
32
    end
33

34
    def connection_name
20✔
NEW
35
      "#{user}@#{host}:#{working_dir || '~'}> "
×
36
    end
37

38
    private
20✔
39

40
    def handle_stdin(chan, stdin)
20✔
NEW
41
      return if stdin.nil?
×
42

NEW
43
      if stdin.is_a?(StringIO)
×
NEW
44
        chan.send_data(stdin.string)
×
NEW
45
        chan.eof!
×
NEW
46
        return
×
47
      end
48

NEW
49
      stdin = RemoteRuby::CompatIOReader.new(stdin)
×
50

NEW
51
      chan.connection.listen_to(stdin.readable) do |io|
×
NEW
52
        data = io.read_nonblock(4096)
×
NEW
53
        chan.send_data(data)
×
54
      rescue EOFError
NEW
55
        chan.connection.stop_listening_to(stdin.readable)
×
NEW
56
        chan.eof!
×
57
      end
58

NEW
59
      chan.on_close do
×
NEW
60
        chan.connection.stop_listening_to(stdin.readable)
×
NEW
61
        stdin.join
×
62
      end
63
    end
64

65
    def handle_stdout(chan, stdout)
20✔
NEW
66
      return if stdout.nil?
×
67

NEW
68
      chan.on_data do |_, data|
×
NEW
69
        stdout.write(data)
×
70
      end
71
    end
72

73
    def handle_stderr(chan, stderr)
20✔
NEW
74
      return if stderr.nil?
×
75

NEW
76
      chan.on_extended_data do |_, _, data|
×
NEW
77
        stderr.write(data)
×
78
      end
79
    end
80

81
    def handle_exit_code(chan)
20✔
NEW
82
      chan.on_request('exit-status') do |_, data|
×
NEW
83
        yield data.read_long
×
84
      end
85
    end
86

87
    def run_remote_process(ssh, cmd, stdin, stdout, stderr)
20✔
NEW
88
      res = nil
×
89

90
      ssh.open_channel do |channel|
×
NEW
91
        channel.exec(cmd) do |ch, success|
×
92
          raise UnableToExecuteError unless success
×
93

NEW
94
          handle_stdin(ch, stdin)
×
NEW
95
          handle_stdout(ch, stdout)
×
NEW
96
          handle_stderr(ch, stderr)
×
NEW
97
          handle_exit_code(ch) do |code|
×
NEW
98
            res = code
×
99
          end
100
        end
101
      end.wait
102

NEW
103
      res
×
104
    end
105

106
    def run_code(ssh, fname, stdin, stdout, stderr)
20✔
NEW
107
      run_remote_process(ssh, "cd '#{working_dir}' && ruby \"#{fname}\"", stdin, stdout, stderr)
×
108
    end
109

110
    def get_result(ssh, fname)
20✔
NEW
111
      ssh.exec!("cat \"#{fname}\"")
×
112
    end
113

114
    def with_temp_file(code, ssh)
20✔
NEW
115
      out = StringIO.new
×
NEW
116
      cmd = 'f=$(mktemp --tmpdir remote_ruby.XXXXXX) && cat > $f && echo $f'
×
NEW
117
      run_remote_process(ssh, cmd, StringIO.new(code), out, nil)
×
NEW
118
      fname = out.string.strip
×
119

120
      yield fname
×
121
    ensure
NEW
122
      ssh.exec!("rm \"#{fname}\"")
×
123
    end
124
  end
125
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc