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

Nu-hin / remote_ruby / 13421563399

19 Feb 2025 08:16PM UTC coverage: 94.253% (+0.8%) from 93.425%
13421563399

push

github

Nu-hin
Refactor StreamSplitter

25 of 25 new or added lines in 1 file covered. (100.0%)

21 existing lines in 3 files now uncovered.

1148 of 1218 relevant lines covered (94.25%)

21.36 hits per line

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

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

3
require 'net/ssh'
4✔
4
require 'remote_ruby/pipes'
4✔
5
require 'remote_ruby/stream_splitter'
4✔
6

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

12
    attr_reader :host, :user, :config, :working_dir
4✔
13

14
    def initialize(host:, user: nil, working_dir: nil)
4✔
UNCOV
15
      super
×
UNCOV
16
      @host = host
×
UNCOV
17
      @working_dir = working_dir
×
18
      @config = Net::SSH.configuration_for(@host, true)
×
19
      @user = user || @config[:user]
×
20
    end
21

22
    def open(code)
4✔
UNCOV
23
      Net::SSH.start(host, user, config) do |ssh|
×
24
        with_temp_file(code, ssh) do |fname|
×
25
          Pipes.with_pipes do |p|
×
26
            t = Thread.new do
×
27
              run_code(ssh, fname, p.in_r, p.out_w, p.err_w)
×
28
            end
29

30
            out, res = StreamSplitter.split(p.out_r, Compiler::MARSHAL_TERMINATOR)
×
31

UNCOV
32
            yield p.in_w, out, p.err_r, res
×
33
            t.join
×
34
          end
35
        end
36
      end
37
    end
38

39
    def run_code(ssh, fname, stdin_r, stdout_w, stderr_w)
4✔
40
      ssh.open_channel do |channel|
×
41
        channel.exec("cd '#{working_dir}' && ruby #{fname}") do |ch, success|
×
UNCOV
42
          raise UnableToExecuteError unless success
×
43

44
          ssh.listen_to(stdin_r) do |io|
×
45
            data = io.read_nonblock(4096)
×
46
            ch.send_data(data)
×
47
          rescue EOFError
UNCOV
48
            ch.eof!
×
49
          end
50

UNCOV
51
          ch.on_data do |_, data|
×
52
            stdout_w << data
×
53
          end
54

55
          ch.on_extended_data do |_, _, data|
×
56
            stderr_w << data
×
57
          end
58

UNCOV
59
          ch.on_close do |_|
×
UNCOV
60
            stdout_w.close
×
UNCOV
61
            stderr_w.close
×
62
          end
63
        end
64
      end.wait
65
    end
66

67
    def connection_name
4✔
68
      "#{user}@#{host}:#{working_dir || '~'}> "
×
69
    end
70

71
    def with_temp_file(code, ssh)
4✔
72
      fname = String.new
×
73
      code_channel = ssh.open_channel do |channel|
×
UNCOV
74
        channel.exec('f=$(mktemp remote_ruby.rb.XXXXXX) && cat > $f && echo $f') do |ch, success|
×
UNCOV
75
          raise UnableToExecuteError unless success
×
76

77
          ch.on_data do |_, data|
×
UNCOV
78
            fname << data
×
79
          end
80

81
          ch.send_data(code)
×
UNCOV
82
          ch.eof!
×
83
        end
84
      end
85

UNCOV
86
      code_channel.wait
×
87

UNCOV
88
      yield fname
×
89
    ensure
UNCOV
90
      ssh.exec!("rm #{fname}")
×
91
    end
92
  end
93
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