kuby-core 0.9.1 → 0.11.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +31 -0
  3. data/Gemfile +1 -0
  4. data/README.md +4 -2
  5. data/kuby-core.gemspec +2 -1
  6. data/lib/kuby-core.rb +1 -0
  7. data/lib/kuby.rb +14 -0
  8. data/lib/kuby/basic_logger.rb +56 -7
  9. data/lib/kuby/cli_base.rb +103 -15
  10. data/lib/kuby/commands.rb +29 -4
  11. data/lib/kuby/definition.rb +1 -0
  12. data/lib/kuby/dev_setup.rb +1 -0
  13. data/lib/kuby/docker.rb +3 -0
  14. data/lib/kuby/docker/alpine.rb +16 -12
  15. data/lib/kuby/docker/assets_phase.rb +5 -0
  16. data/lib/kuby/docker/bundler_phase.rb +36 -2
  17. data/lib/kuby/docker/cli.rb +55 -10
  18. data/lib/kuby/docker/copy_phase.rb +11 -3
  19. data/lib/kuby/docker/credentials.rb +1 -0
  20. data/lib/kuby/docker/debian.rb +14 -10
  21. data/lib/kuby/docker/dev_spec.rb +82 -18
  22. data/lib/kuby/docker/distro.rb +43 -0
  23. data/lib/kuby/docker/dockerfile.rb +67 -19
  24. data/lib/kuby/docker/errors.rb +9 -0
  25. data/lib/kuby/docker/inline_layer.rb +7 -0
  26. data/lib/kuby/docker/layer.rb +11 -0
  27. data/lib/kuby/docker/layer_stack.rb +43 -6
  28. data/lib/kuby/docker/local_tags.rb +23 -2
  29. data/lib/kuby/docker/metadata.rb +35 -7
  30. data/lib/kuby/docker/package_list.rb +22 -3
  31. data/lib/kuby/docker/package_phase.rb +25 -5
  32. data/lib/kuby/docker/packages.rb +1 -0
  33. data/lib/kuby/docker/packages/managed_package.rb +20 -2
  34. data/lib/kuby/docker/packages/nodejs.rb +8 -0
  35. data/lib/kuby/docker/packages/package.rb +15 -1
  36. data/lib/kuby/docker/packages/simple_managed_package.rb +10 -1
  37. data/lib/kuby/docker/packages/yarn.rb +14 -0
  38. data/lib/kuby/docker/remote_tags.rb +21 -2
  39. data/lib/kuby/docker/setup_phase.rb +35 -4
  40. data/lib/kuby/docker/spec.rb +89 -13
  41. data/lib/kuby/docker/tags.rb +37 -2
  42. data/lib/kuby/docker/timestamp_tag.rb +14 -2
  43. data/lib/kuby/docker/webserver_phase.rb +41 -6
  44. data/lib/kuby/docker/yarn_phase.rb +5 -0
  45. data/lib/kuby/environment.rb +4 -0
  46. data/lib/kuby/kubernetes.rb +1 -0
  47. data/lib/kuby/kubernetes/deploy_task.rb +1 -0
  48. data/lib/kuby/kubernetes/deployer.rb +1 -0
  49. data/lib/kuby/kubernetes/docker_config.rb +1 -0
  50. data/lib/kuby/kubernetes/docker_desktop_provider.rb +1 -0
  51. data/lib/kuby/kubernetes/errors.rb +1 -0
  52. data/lib/kuby/kubernetes/manifest.rb +1 -0
  53. data/lib/kuby/kubernetes/provider.rb +1 -0
  54. data/lib/kuby/kubernetes/registry_secret.rb +1 -0
  55. data/lib/kuby/kubernetes/spec.rb +19 -3
  56. data/lib/kuby/middleware.rb +1 -0
  57. data/lib/kuby/middleware/health_check.rb +1 -0
  58. data/lib/kuby/plugin.rb +1 -0
  59. data/lib/kuby/plugin_registry.rb +1 -0
  60. data/lib/kuby/plugins.rb +1 -0
  61. data/lib/kuby/plugins/nginx_ingress.rb +1 -0
  62. data/lib/kuby/plugins/rails_app.rb +1 -0
  63. data/lib/kuby/plugins/rails_app/asset_copy_task.rb +1 -0
  64. data/lib/kuby/plugins/rails_app/assets.rb +1 -0
  65. data/lib/kuby/plugins/rails_app/database.rb +10 -9
  66. data/lib/kuby/plugins/rails_app/generators/kuby.rb +45 -32
  67. data/lib/kuby/plugins/rails_app/mysql.rb +1 -3
  68. data/lib/kuby/plugins/rails_app/plugin.rb +13 -4
  69. data/lib/kuby/plugins/rails_app/postgres.rb +1 -0
  70. data/lib/kuby/plugins/rails_app/rewrite_db_config.rb +1 -0
  71. data/lib/kuby/plugins/rails_app/sqlite.rb +1 -0
  72. data/lib/kuby/rails_commands.rb +14 -19
  73. data/lib/kuby/railtie.rb +1 -0
  74. data/lib/kuby/tasks.rb +3 -2
  75. data/lib/kuby/trailing_hash.rb +5 -3
  76. data/lib/kuby/version.rb +3 -1
  77. data/spec/docker/metadata_spec.rb +1 -0
  78. data/spec/docker/spec_spec.rb +37 -0
  79. data/spec/docker/timestamp_tag_spec.rb +1 -0
  80. data/spec/dummy/app/channels/application_cable/channel.rb +1 -0
  81. data/spec/dummy/app/channels/application_cable/connection.rb +1 -0
  82. data/spec/dummy/app/controllers/application_controller.rb +1 -0
  83. data/spec/dummy/app/helpers/application_helper.rb +1 -0
  84. data/spec/dummy/app/jobs/application_job.rb +1 -0
  85. data/spec/dummy/app/mailers/application_mailer.rb +1 -0
  86. data/spec/dummy/app/models/application_record.rb +1 -0
  87. data/spec/dummy/config/application.rb +1 -0
  88. data/spec/dummy/config/boot.rb +1 -0
  89. data/spec/dummy/config/environment.rb +1 -0
  90. data/spec/dummy/config/environments/development.rb +1 -0
  91. data/spec/dummy/config/environments/production.rb +1 -0
  92. data/spec/dummy/config/environments/test.rb +1 -0
  93. data/spec/dummy/config/initializers/application_controller_renderer.rb +1 -0
  94. data/spec/dummy/config/initializers/assets.rb +1 -0
  95. data/spec/dummy/config/initializers/backtrace_silencers.rb +1 -0
  96. data/spec/dummy/config/initializers/content_security_policy.rb +1 -0
  97. data/spec/dummy/config/initializers/cookies_serializer.rb +1 -0
  98. data/spec/dummy/config/initializers/filter_parameter_logging.rb +1 -0
  99. data/spec/dummy/config/initializers/inflections.rb +1 -0
  100. data/spec/dummy/config/initializers/mime_types.rb +1 -0
  101. data/spec/dummy/config/initializers/wrap_parameters.rb +1 -0
  102. data/spec/dummy/config/puma.rb +1 -0
  103. data/spec/dummy/config/routes.rb +1 -0
  104. data/spec/dummy/config/spring.rb +1 -0
  105. data/spec/dummy/db/seeds.rb +1 -0
  106. data/spec/dummy/test/application_system_test_case.rb +1 -0
  107. data/spec/dummy/test/channels/application_cable/connection_test.rb +1 -0
  108. data/spec/dummy/test/test_helper.rb +1 -0
  109. data/spec/spec_helper.rb +10 -0
  110. data/spec/support/docker/fake_cli.rb +1 -0
  111. data/spec/support/docker/remote/fake_client.rb +1 -0
  112. data/spec/trailing_hash_spec.rb +2 -0
  113. metadata +20 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8202396d9daaa1ccba46f2b607f90b64e615b9d44a2f87cbfef1682dadd8a8d1
4
- data.tar.gz: a6ad5b2436b1aacdc097ffd2ff03a2ad993d62747f6e8a54126239c0c42ac628
3
+ metadata.gz: a3a59a9d3e923807647da18d834d994cc7b2d149f4c82d6d9966d72748d7bcd5
4
+ data.tar.gz: 2bbd8e7d1c92ed3d0eb7d6d05420d7119d6f20a249f4401e52191868baeb0996
5
5
  SHA512:
6
- metadata.gz: 2f1c577697475d726c38a74f20ec881613e03be19de90dc4843cee795fe54ec69cdfd23296e60c56db3611707fc397408ca7bbddf257b8a70c84af65d5cf2edd
7
- data.tar.gz: a732245dd7b3a23aa7a0bfeaa8c53b7f057c1a60ac5d4a667b11c966fcc31354df068276624e0c5d8a8c893ef1ea6e779d602087a6ed86ccbdb507664e69abbf
6
+ metadata.gz: d8bf5fce8051029c8231e915035ec6c704ab361a6008b5335bf8a6747fb106ed55869164bb15eb704ecd72e6366ee320664d23d128a74726b6ca320edcb5c442
7
+ data.tar.gz: 679ad59207c201fb710e47e69c4682676a6fb12c826b59350a74d98c48f212d358c50fde0f8da0a5804391738d442a839cb4560d2cebd61ec7e7955677bd8e53
@@ -1,3 +1,34 @@
1
+ ## 0.11.2
2
+ * Attempt to auto-require the requested provider if it isn't registered.
3
+ * Adjust error message when provider can't be found to include reminder to add a require statement.
4
+
5
+ ## 0.11.1
6
+ * Use integers for ports instead of strings to appease Kubernetes.
7
+
8
+ ## 0.11.0
9
+ * Defer evaluation of database config until after Kuby has been configured.
10
+ - The issue that prompted this was that the `database` block was being evaluated before the Rails root had been set via `root`. Kuby couldn't find database.yml in a non-standard location and blew up with an error.
11
+ * Fix tests broken in 0.10.1.
12
+ * Set up Travis CI builds.
13
+ * Add a few tests for custom build phases.
14
+ * Add the `Environment#configured?` method that will return `true` if Kuby has been configured and `false` if configuration hasn't happened or is in progress.
15
+ * Add sorbet typedefs for some classes.
16
+ * Fix issue in Rails generator (hadn't been updated with new `environment` block).
17
+ * Add kuby-core.rb so Bundler setup works for Kuby without having to add a Rails initializer.
18
+
19
+ ## 0.10.1
20
+ * Fix bug causing some `rails` and `rake` commands to not be executed.
21
+ * Fix issue restricting Docker CLI output.
22
+
23
+ ## 0.10.0
24
+ * Set default database user and password in dev environment.
25
+ * Add ability to run rake tasks in dev environment.
26
+ * Disallow running rails and rake tasks in non-dev environments.
27
+ * Don't run database config through ERB.
28
+ - Rails env often isn't loaded, so ERB rendering can blow up with `NoMethodError`s, etc.
29
+ - All we really need to know is what database engine to stand up.
30
+ * Require database user/password to be added manually to Kuby config.
31
+
1
32
  ## 0.9.1
2
33
  * Run dev setup when asked to.
3
34
  - Bug caused dev setup to be skipped even when requested.
data/Gemfile CHANGED
@@ -5,6 +5,7 @@ gemspec
5
5
  group :development, :test do
6
6
  gem 'pry-byebug'
7
7
  gem 'rake'
8
+ gem 'sorbet', '~> 0.5'
8
9
  end
9
10
 
10
11
  group :test do
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  ## Kuby
2
2
 
3
+ [![Build Status](https://travis-ci.com/getkuby/kuby-core.svg?branch=master)](https://travis-ci.com/getkuby/kuby-core)
4
+
3
5
  Deploy your Rails app the easy way.
4
6
 
5
7
  ## What is Kuby?
@@ -20,11 +22,11 @@ Kuby embraces the same convention-over-configuration approach that Rails does. I
20
22
 
21
23
  ## Getting Started
22
24
 
23
- See the [Quick Start Guide](https://github.com/getkuby/kuby-core/wiki/Quick-Start-Guide)
25
+ See the [Quick Start Guide](https://getkuby.io/docs)
24
26
 
25
27
  ## More Info
26
28
 
27
- See the [wiki](https://github.com/getkuby/kuby-core/wiki).
29
+ Check out [getkuby.io](https://getkuby.io).
28
30
 
29
31
  ## Running Tests
30
32
 
@@ -20,11 +20,12 @@ Gem::Specification.new do |s|
20
20
  # See: https://github.com/Shopify/krane/blob/master/CHANGELOG.md#114
21
21
  s.add_dependency 'krane', '>= 1.1.4', '< 2.0'
22
22
  s.add_dependency 'kuby-cert-manager', '>= 0.3'
23
- s.add_dependency 'kube-dsl', '~> 0.3'
23
+ s.add_dependency 'kube-dsl', '~> 0.4'
24
24
  s.add_dependency 'kuby-kube-db', '>= 0.6'
25
25
  s.add_dependency 'kubernetes-cli', '~> 0.3'
26
26
  s.add_dependency 'railties', '>= 5.1'
27
27
  s.add_dependency 'rouge', '~> 3.0'
28
+ s.add_dependency 'sorbet-runtime-stub', '~> 0.2'
28
29
 
29
30
  s.add_development_dependency 'rspec'
30
31
 
@@ -0,0 +1 @@
1
+ require 'kuby'
@@ -1,3 +1,6 @@
1
+ # typed: false
2
+
3
+ require 'sorbet-runtime-stub'
1
4
  require 'kuby/railtie'
2
5
 
3
6
  begin
@@ -23,6 +26,8 @@ module Kuby
23
26
  autoload :TrailingHash, 'kuby/trailing_hash'
24
27
 
25
28
  DEFAULT_ENV = 'development'.freeze
29
+ DEFAULT_DB_USER = 'root'.freeze
30
+ DEFAULT_DB_PASSWORD = 'password'.freeze
26
31
 
27
32
  class UndefinedEnvironmentError < StandardError; end
28
33
  class MissingConfigError < StandardError; end
@@ -52,6 +57,11 @@ module Kuby
52
57
  kubernetes do
53
58
  add_plugin(:rails_app) do
54
59
  tls_enabled false
60
+
61
+ database do
62
+ user(DEFAULT_DB_USER) if respond_to?(:user)
63
+ password(DEFAULT_DB_PASSWORD) if respond_to?(:password)
64
+ end
55
65
  end
56
66
 
57
67
  provider :docker_desktop
@@ -62,6 +72,10 @@ module Kuby
62
72
  env.kubernetes.after_configuration
63
73
  end
64
74
 
75
+ @definition.environments.each do |_, env|
76
+ env.configured = true
77
+ end
78
+
65
79
  @definition
66
80
  end
67
81
 
@@ -1,9 +1,30 @@
1
+ # typed: strict
2
+
1
3
  require 'logger'
2
4
  require 'colorized_string'
3
5
 
4
6
  module Kuby
5
7
  class BasicLogger < Logger
6
- def initialize(*args)
8
+ extend T::Sig
9
+
10
+ sig {
11
+ override.params(
12
+ logdev: T.any(String, IO, StringIO, NilClass),
13
+ shift_age: Integer,
14
+ shift_size: Integer,
15
+ level: Integer,
16
+ progname: T.nilable(String),
17
+ formatter: T.nilable(FormatterProcType),
18
+ datetime_format: T.nilable(String),
19
+ shift_period_suffix: T.nilable(String)
20
+ ).void
21
+ }
22
+ def initialize(
23
+ logdev, shift_age = 0, shift_size = 1048576, level: DEBUG,
24
+ progname: nil, formatter: nil, datetime_format: nil,
25
+ shift_period_suffix: '%Y%m%d')
26
+ @logdev = T.let(@logdev, T.nilable(Logger::LogDevice))
27
+
7
28
  super
8
29
 
9
30
  self.formatter = proc do |_severity, _datetime, _progname, msg|
@@ -11,23 +32,51 @@ module Kuby
11
32
  end
12
33
  end
13
34
 
14
- def info(msg, *args)
15
- super(ColorizedString[msg].yellow, *args)
35
+ sig {
36
+ override.params(
37
+ progname_or_msg: T.untyped,
38
+ block: T.nilable(T.proc.returns(T.untyped))
39
+ ).void
40
+ }
41
+ def info(progname_or_msg = nil, &block)
42
+ if block
43
+ super(progname_or_msg) { ColorizedString[block.call].yellow }
44
+ else
45
+ super(ColorizedString[progname_or_msg].yellow)
46
+ end
16
47
  end
17
48
 
18
- def fatal(msg, *args)
19
- super(ColorizedString[msg].red, *args)
49
+ sig {
50
+ override.params(
51
+ progname_or_msg: T.untyped,
52
+ block: T.nilable(T.proc.returns(T.untyped))
53
+ ).void
54
+ }
55
+ def fatal(progname_or_msg, &block)
56
+ if block
57
+ super(progname_or_msg) { ColorizedString[block.call].red }
58
+ else
59
+ super(ColorizedString[progname_or_msg].red)
60
+ end
20
61
  end
21
62
 
22
63
  # adhere to the "CLI" interface
23
- def with_pipes(out = STDOUT, err = STDERR)
24
- previous_logdev = @logdev || STDERR
64
+ sig {
65
+ params(
66
+ out: T.any(IO, StringIO),
67
+ err: T.any(IO, StringIO),
68
+ block: T.proc.void
69
+ ).void
70
+ }
71
+ def with_pipes(out = STDOUT, err = STDERR, &block)
72
+ previous_logdev = @logdev&.dev || STDERR
25
73
  reopen(err)
26
74
  yield
27
75
  ensure
28
76
  reopen(previous_logdev)
29
77
  end
30
78
 
79
+ sig { returns(T.nilable(Process::Status)) }
31
80
  def last_status
32
81
  nil
33
82
  end
@@ -1,23 +1,39 @@
1
+ # typed: strict
2
+
1
3
  require 'open3'
2
4
  require 'thread'
3
5
 
4
6
  module Kuby
5
7
  class CLIBase
8
+ extend T::Sig
9
+
10
+ sig { returns(T.nilable(Process::Status)) }
6
11
  def last_status
7
12
  Thread.current[status_key]
8
13
  end
9
14
 
15
+ sig { params(block: T.proc.params(cmd: String).void).void }
10
16
  def before_execute(&block)
17
+ @before_execute = T.let(@before_execute, T.nilable(T::Array[T.proc.params(cmd: String).void]))
11
18
  @before_execute ||= []
12
19
  @before_execute << block
13
20
  end
14
21
 
22
+ sig { params(block: T.proc.params(cmd: String).void).void }
15
23
  def after_execute(&block)
24
+ @after_execute = T.let(@after_execute, T.nilable(T::Array[T.proc.params(cmd: String).void]))
16
25
  @after_execute ||= []
17
26
  @after_execute << block
18
27
  end
19
28
 
20
- def with_pipes(out = STDOUT, err = STDERR)
29
+ sig {
30
+ params(
31
+ out: T.any(IO, StringIO),
32
+ err: T.any(IO, StringIO),
33
+ block: T.proc.void
34
+ ).void
35
+ }
36
+ def with_pipes(out = STDOUT, err = STDERR, &block)
21
37
  previous_stdout = self.stdout
22
38
  previous_stderr = self.stderr
23
39
  self.stdout = out
@@ -28,29 +44,39 @@ module Kuby
28
44
  self.stderr = previous_stderr
29
45
  end
30
46
 
47
+ sig { returns(T.nilable(T.any(IO, StringIO))) }
31
48
  def stdout
32
49
  Thread.current[stdout_key] || STDOUT
33
50
  end
34
51
 
52
+ sig { params(new_stdout: T.nilable(T.any(IO, StringIO))).void }
35
53
  def stdout=(new_stdout)
36
54
  Thread.current[stdout_key] = new_stdout
37
55
  end
38
56
 
57
+ sig { returns(T.nilable(T.any(IO, StringIO))) }
39
58
  def stderr
40
59
  Thread.current[stderr_key] || STDERR
41
60
  end
42
61
 
62
+ sig { params(new_stderr: T.nilable(T.any(IO, StringIO))).void }
43
63
  def stderr=(new_stderr)
44
64
  Thread.current[stderr_key] = new_stderr
45
65
  end
46
66
 
47
67
  private
48
68
 
49
- def open3_w(env, cmd, opts = {}, &block)
69
+ sig {
70
+ params(
71
+ cmd: T::Array[String],
72
+ block: T.proc.params(stdin: IO).void
73
+ ).void
74
+ }
75
+ def open3_w(cmd, &block)
50
76
  run_before_callbacks(cmd)
51
77
  cmd_s = cmd.join(' ')
52
78
 
53
- Open3.popen3(env, cmd_s, opts) do |p_stdin, p_stdout, p_stderr, wait_thread|
79
+ Open3.popen3(cmd_s) do |p_stdin, p_stdout, p_stderr, wait_thread|
54
80
  Thread.new(stdout) do |t_stdout|
55
81
  begin
56
82
  p_stdout.each { |line| t_stdout.puts(line) }
@@ -65,55 +91,111 @@ module Kuby
65
91
  end
66
92
  end
67
93
 
68
- yield(p_stdin).tap do
69
- p_stdin.close
70
- self.last_status = wait_thread.value
71
- run_after_callbacks(cmd)
72
- wait_thread.join
73
- end
94
+ yield(p_stdin)
95
+
96
+ p_stdin.close
97
+ self.last_status = T.cast(wait_thread.value, Process::Status)
98
+ run_after_callbacks(cmd)
99
+ wait_thread.join
74
100
  end
75
101
  end
76
102
 
103
+ sig { params(cmd: T::Array[String]).void }
77
104
  def execc(cmd)
78
105
  run_before_callbacks(cmd)
79
106
  cmd_s = cmd.join(' ')
80
107
  exec(cmd_s)
81
108
  end
82
109
 
110
+ sig { params(cmd: T::Array[String]).void }
83
111
  def systemm(cmd)
112
+ if stdout == STDOUT && stderr == STDERR
113
+ systemm_default(cmd)
114
+ else
115
+ systemm_open3(cmd)
116
+ end
117
+ end
118
+
119
+ sig { params(cmd: T::Array[String]).void }
120
+ def systemm_default(cmd)
121
+ run_before_callbacks(cmd)
122
+ cmd_s = cmd.join(' ')
123
+ system(cmd_s).tap do
124
+ self.last_status = $?
125
+ run_after_callbacks(cmd)
126
+ end
127
+ end
128
+
129
+ sig { params(cmd: T::Array[String]).void }
130
+ def systemm_open3(cmd)
84
131
  run_before_callbacks(cmd)
85
132
  cmd_s = cmd.join(' ')
86
133
 
87
134
  Open3.popen3(cmd_s) do |p_stdin, p_stdout, p_stderr, wait_thread|
88
135
  Thread.new(stdout) do |t_stdout|
89
- p_stdout.each { |line| t_stdout.puts(line) }
136
+ begin
137
+ p_stdout.each { |line| t_stdout.puts(line) }
138
+ rescue IOError
139
+ end
90
140
  end
91
141
 
92
142
  Thread.new(stderr) do |t_stderr|
93
- p_stderr.each { |line| t_stderr.puts(line) }
143
+ begin
144
+ p_stderr.each { |line| t_stderr.puts(line) }
145
+ rescue IOError
146
+ end
94
147
  end
95
148
 
96
- self.last_status = wait_thread.value
149
+ p_stdin.close
150
+ self.last_status = T.cast(wait_thread.value, Process::Status)
97
151
  run_after_callbacks(cmd)
98
152
  wait_thread.join
99
153
  end
100
154
  end
101
155
 
156
+
157
+ sig { params(cmd: T::Array[String]).returns(String) }
102
158
  def backticks(cmd)
159
+ if stdout == STDOUT && stderr == STDERR
160
+ backticks_default(cmd)
161
+ else
162
+ backticks_open3(cmd)
163
+ end
164
+ end
165
+
166
+ sig { params(cmd: T::Array[String]).returns(String) }
167
+ def backticks_default(cmd)
168
+ run_before_callbacks(cmd)
169
+ cmd_s = cmd.join(' ')
170
+ `#{cmd_s}`.tap do
171
+ self.last_status = $?
172
+ run_after_callbacks(cmd)
173
+ end
174
+ end
175
+
176
+ sig { params(cmd: T::Array[String]).returns(String) }
177
+ def backticks_open3(cmd)
103
178
  run_before_callbacks(cmd)
104
179
  cmd_s = cmd.join(' ')
105
180
  result = StringIO.new
106
181
 
107
182
  Open3.popen3(cmd_s) do |p_stdin, p_stdout, p_stderr, wait_thread|
108
183
  Thread.new do
109
- p_stdout.each { |line| result.puts(line) }
184
+ begin
185
+ p_stdout.each { |line| result.puts(line) }
186
+ rescue IOError
187
+ end
110
188
  end
111
189
 
112
190
  Thread.new(stderr) do |t_stderr|
113
- p_stderr.each { |line| t_stderr.puts(line) }
191
+ begin
192
+ p_stderr.each { |line| t_stderr.puts(line) }
193
+ rescue IOError
194
+ end
114
195
  end
115
196
 
116
- self.last_status = wait_thread.value
197
+ p_stdin.close
198
+ self.last_status = T.cast(wait_thread.value, Process::Status)
117
199
  run_after_callbacks(cmd)
118
200
  wait_thread.join
119
201
  end
@@ -121,26 +203,32 @@ module Kuby
121
203
  result.string
122
204
  end
123
205
 
206
+ sig { params(cmd: T::Array[String]).void }
124
207
  def run_before_callbacks(cmd)
125
208
  (@before_execute || []).each { |cb| cb.call(cmd) }
126
209
  end
127
210
 
211
+ sig { params(cmd: T::Array[String]).void }
128
212
  def run_after_callbacks(cmd)
129
213
  (@after_execute || []).each { |cb| cb.call(cmd, last_status) }
130
214
  end
131
215
 
216
+ sig { params(status: Process::Status).void }
132
217
  def last_status=(status)
133
218
  Thread.current[status_key] = status
134
219
  end
135
220
 
221
+ sig { returns(Symbol) }
136
222
  def status_key
137
223
  raise NotImplementedError, "#{__method__} must be defined in derived classes"
138
224
  end
139
225
 
226
+ sig { returns(Symbol) }
140
227
  def stdout_key
141
228
  raise NotImplementedError, "#{__method__} must be defined in derived classes"
142
229
  end
143
230
 
231
+ sig { returns(Symbol) }
144
232
  def stderr_key
145
233
  raise NotImplementedError, "#{__method__} must be defined in derived classes"
146
234
  end