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

Nu-hin / remote_ruby / 13682598348

05 Mar 2025 06:09PM UTC coverage: 93.882% (-0.3%) from 94.18%
13682598348

push

github

Nu-hin
Unsibsribe from stdin events when channel is closed

0 of 3 new or added lines in 1 file covered. (0.0%)

890 of 948 relevant lines covered (93.88%)

91.3 hits per line

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

20.34
/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)
×
28
          ret = get_result(ssh, fname, res)
×
29
        end
30
      end
31
      ret
×
32
    end
33

34
    def run_code(ssh, fname, stdin_r, stdout_w, stderr_w)
20✔
35
      res = nil
×
36
      stdin_r = RemoteRuby::CompatIOReader.new(stdin_r)
×
37
      ssh.open_channel do |channel|
×
38
        channel.exec("cd '#{working_dir}' && ruby \"#{fname}\"") do |ch, success|
×
39
          raise UnableToExecuteError unless success
×
40

41
          ssh.listen_to(stdin_r.readable) do |io|
×
42
            data = io.read_nonblock(4096)
×
43
            ch.send_data(data)
×
44
          rescue EOFError
NEW
45
            ssh.stop_listening_to(stdin_r.readable)
×
46
            stdin_r.join
×
47
            ch.eof!
×
48
          end
49

50
          ch.on_data do |_, data|
×
51
            stdout_w.write(data)
×
52
          end
53

54
          ch.on_extended_data do |_, _, data|
×
55
            stderr_w.write(data)
×
56
          end
57

58
          ch.on_request('exit-status') do |_, data|
×
59
            res = data.read_long
×
60
          end
61

NEW
62
          ch.on_close do
×
NEW
63
            ssh.stop_listening_to(stdin_r.readable)
×
64
          end
65
        end
66
      end.wait
67

68
      res
×
69
    end
70

71
    def get_result(ssh, fname, process_status)
20✔
72
      raise "Process exited with code #{process_status}" unless process_status.zero?
×
73

74
      ssh.exec!("cat \"#{fname}\"")
×
75
    end
76

77
    def connection_name
20✔
78
      "#{user}@#{host}:#{working_dir || '~'}> "
×
79
    end
80

81
    def with_temp_file(code, ssh)
20✔
82
      fname = String.new
×
83
      ssh.open_channel do |channel|
×
84
        channel.exec('f=$(mktemp --tmpdir remote_ruby.XXXXXX) && cat > $f && echo $f') do |ch, success|
×
85
          raise UnableToExecuteError unless success
×
86

87
          ch.on_data do |_, data|
×
88
            fname << data
×
89
          end
90

91
          ch.send_data(code)
×
92
          ch.eof!
×
93
        end
94
      end.wait
95

96
      fname.strip!
×
97

98
      yield fname
×
99
    ensure
100
      Net::SSH.start(host, nil, config) do |del_ssh|
×
101
        del_ssh.exec!("rm \"#{fname}\"")
×
102
      end
103
    end
104
  end
105
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