kuby-core 0.10.0 → 0.11.3

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 +25 -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 +7 -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 +8 -0
  11. data/lib/kuby/definition.rb +15 -1
  12. data/lib/kuby/dev_setup.rb +113 -22
  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 +9 -7
  66. data/lib/kuby/plugins/rails_app/generators/kuby.rb +53 -40
  67. data/lib/kuby/plugins/rails_app/mysql.rb +1 -0
  68. data/lib/kuby/plugins/rails_app/plugin.rb +9 -5
  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 +1 -6
  73. data/lib/kuby/railtie.rb +1 -0
  74. data/lib/kuby/tasks.rb +1 -0
  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
@@ -1,11 +1,24 @@
1
+ # typed: strict
2
+
1
3
  module Kuby
2
4
  class Definition
5
+ extend T::Sig
6
+
7
+ sig { returns(String) }
3
8
  attr_reader :app_name
4
9
 
10
+ sig { params(app_name: String, block: T.nilable(T.proc.void)).void }
5
11
  def initialize(app_name, &block)
6
12
  @app_name = app_name
13
+ @environments = T.let(@environments, T.nilable(T::Hash[Symbol, Environment]))
7
14
  end
8
15
 
16
+ sig {
17
+ params(
18
+ name: Symbol,
19
+ block: T.nilable(T.proc.void)
20
+ ).returns(Environment)
21
+ }
9
22
  def environment(name = Kuby.env, &block)
10
23
  name = name.to_s
11
24
 
@@ -15,9 +28,10 @@ module Kuby
15
28
  environments[name].instance_eval(&block)
16
29
  end
17
30
 
18
- environments[name]
31
+ T.must(environments[name])
19
32
  end
20
33
 
34
+ sig { returns(T::Hash[Symbol, Environment]) }
21
35
  def environments
22
36
  @environments ||= {}
23
37
  end
@@ -1,18 +1,34 @@
1
+ # typed: strict
2
+
1
3
  module Kuby
2
4
  class Spinner
3
- PIECES = %w(- \\ | /).freeze
4
- INTERVAL = 0.2 # seconds
5
-
6
- def self.spin(message)
5
+ extend T::Sig
6
+
7
+ PIECES = T.let(%w(- \\ | /).freeze, T::Array[String])
8
+ INTERVAL = T.let(0.2, Float) # seconds
9
+
10
+ sig {
11
+ params(
12
+ message: String,
13
+ block: T.proc.params(spinner: Spinner).void
14
+ )
15
+ .void
16
+ }
17
+ def self.spin(message, &block)
7
18
  yield new(message)
8
19
  end
9
20
 
10
- attr_reader :message, :status
21
+ sig { returns(String) }
22
+ attr_reader :message
23
+
24
+ sig { returns(Symbol) }
25
+ attr_reader :status
11
26
 
27
+ sig { params(message: String).void }
12
28
  def initialize(message)
13
- @message = message
14
- @status = :running
15
- @thread = Thread.new do
29
+ @message = T.let(message, String)
30
+ @status = T.let(:running, Symbol)
31
+ @thread = T.let(Thread.new do
16
32
  counter = 0
17
33
 
18
34
  while true
@@ -32,14 +48,16 @@ module Kuby
32
48
  end
33
49
 
34
50
  puts
35
- end
51
+ end, Thread)
36
52
  end
37
53
 
54
+ sig { void }
38
55
  def success
39
56
  @status = :success
40
57
  @thread.join
41
58
  end
42
59
 
60
+ sig { void }
43
61
  def failure
44
62
  @status = :failure
45
63
  @thread.join
@@ -47,66 +65,116 @@ module Kuby
47
65
  end
48
66
 
49
67
  class SetupTask
50
- attr_reader :message, :callable
68
+ extend T::Sig
51
69
 
70
+ sig { returns(String) }
71
+ attr_reader :message
72
+
73
+ sig { returns(T.proc.void) }
74
+ attr_reader :callable
75
+
76
+ sig { params(message: String, callable: T.proc.void).void }
52
77
  def initialize(message, callable)
53
78
  @message = message
54
79
  @callable = callable
55
80
  end
56
81
 
82
+ sig { void }
57
83
  def run
58
84
  callable.call
59
85
  end
60
86
  end
61
87
 
62
88
  class Pipe
63
- attr_reader :name, :cli, :out, :err
89
+ extend T::Sig
90
+
91
+ sig { returns(Symbol) }
92
+ attr_reader :name
93
+
94
+ sig { returns(T.untyped) }
95
+ attr_reader :cli
64
96
 
97
+ sig { returns(StringIO) }
98
+ attr_reader :out
99
+
100
+ sig { returns(StringIO) }
101
+ attr_reader :err
102
+
103
+ sig { params(name: Symbol, cli: T.untyped).void }
65
104
  def initialize(name, cli)
66
- @name = name
67
- @cli = cli
68
- @out = StringIO.new
69
- @err = StringIO.new
105
+ @name = T.let(name, Symbol)
106
+ @cli = T.let(cli, T.untyped)
107
+ @out = T.let(StringIO.new, StringIO)
108
+ @err = T.let(StringIO.new, StringIO)
70
109
  end
71
110
 
111
+ sig { params(block: T.proc.void).void }
72
112
  def wrap(&block)
73
113
  cli.with_pipes(out, err) do
74
114
  block.call
75
115
  end
76
116
  end
77
117
 
118
+ sig { returns(T::Boolean) }
78
119
  def success?
79
120
  cli.last_status.nil? || cli.last_status.success?
80
121
  end
81
122
  end
82
123
 
83
124
  class Pipes
125
+ extend T::Sig
126
+ extend T::Generic
127
+
84
128
  include Enumerable
85
129
 
86
- attr_reader :pipes, :ex
130
+ Elem = type_member(fixed: Pipe)
131
+
132
+ sig { returns(T::Array[Pipe]) }
133
+ attr_reader :pipes
87
134
 
135
+ sig { returns(T.nilable(StandardError)) }
136
+ attr_reader :ex
137
+
138
+ sig { params(clis: T::Hash[Symbol, T.untyped]).returns(Pipes) }
88
139
  def self.build(clis)
89
140
  new(clis.map { |name, cli| Pipe.new(name, cli) })
90
141
  end
91
142
 
143
+ sig { params(pipes: T::Array[Pipe]).void }
92
144
  def initialize(pipes)
93
- @pipes = pipes
145
+ @ex = T.let(@ex, T.nilable(StandardError))
146
+ @pipes = T.let(pipes, T::Array[Pipe])
94
147
  end
95
148
 
149
+ sig {
150
+ override.params(
151
+ block: T.proc.params(package: Pipe).void
152
+ )
153
+ .void
154
+ }
96
155
  def each(&block)
97
156
  pipes.each(&block)
98
157
  end
99
158
 
159
+ sig { params(block: T.proc.void).void }
100
160
  def wrap(&block)
101
161
  do_wrap(pipes, &block)
102
162
  end
103
163
 
164
+ sig { returns(T::Boolean) }
104
165
  def success?
105
166
  pipes.all?(&:success?) && !ex
106
167
  end
107
168
 
108
169
  private
109
170
 
171
+ sig {
172
+ params(
173
+ remaining_pipes: T::Array[Pipe],
174
+ block: T.proc.void
175
+ )
176
+ .void
177
+ }
110
178
  def do_wrap(remaining_pipes, &block)
111
179
  if remaining_pipes.empty?
112
180
  begin
@@ -118,20 +186,28 @@ module Kuby
118
186
  return
119
187
  end
120
188
 
121
- remaining_pipes[0].wrap do
122
- do_wrap(remaining_pipes[1..-1], &block)
189
+ T.must(remaining_pipes[0]).wrap do
190
+ do_wrap(T.must(remaining_pipes[1..-1]), &block)
123
191
  end
124
192
  end
125
193
  end
126
194
 
127
195
  class SetupTaskList
128
- attr_reader :tasks, :clis
196
+ extend T::Sig
197
+
198
+ sig { returns(T::Array[SetupTask]) }
199
+ attr_reader :tasks
129
200
 
201
+ sig { returns T::Hash[Symbol, T.untyped] }
202
+ attr_reader :clis
203
+
204
+ sig { params(tasks: T::Array[SetupTask], clis: T::Hash[Symbol, T.untyped]).void }
130
205
  def initialize(tasks, clis)
131
206
  @tasks = tasks
132
207
  @clis = clis
133
208
  end
134
209
 
210
+ sig { void }
135
211
  def run
136
212
  tasks.each do |task|
137
213
  pipes = Pipes.build(clis)
@@ -159,6 +235,7 @@ module Kuby
159
235
 
160
236
  private
161
237
 
238
+ sig { params(pipe: Pipe).void }
162
239
  def print_streams(pipe)
163
240
  unless pipe.out.string.strip.empty?
164
241
  puts("========= #{pipe.name.upcase} STDOUT ========")
@@ -171,27 +248,37 @@ module Kuby
171
248
  end
172
249
  end
173
250
 
251
+ sig { params(ex: T.nilable(StandardError)).void }
174
252
  def print_error(ex)
175
253
  return unless ex
176
254
  puts("========= RUBY ERROR ========")
177
255
  puts(ex.message)
178
- puts(ex.backtrace.join("\n"))
256
+ puts(T.must(ex.backtrace).join("\n"))
179
257
  end
180
258
  end
181
259
 
182
260
  class DevSetup
261
+ extend T::Sig
262
+
263
+ sig { returns(Environment) }
183
264
  attr_reader :environment
184
265
 
266
+ sig { params(environment: Environment).void }
185
267
  def initialize(environment)
186
- @environment = environment
268
+ @environment = T.let(environment, Environment)
269
+ @setup_tasks = T.let(@setup_tasks, T.nilable(T::Array[SetupTask]))
270
+ @clis = T.let(@clis, T.nilable(T::Hash[Symbol, T.untyped]))
271
+ @tasks = T.let(@tasks, T.nilable(Tasks))
187
272
  end
188
273
 
274
+ sig { void }
189
275
  def run
190
276
  SetupTaskList.new(setup_tasks, clis).run
191
277
  end
192
278
 
193
279
  private
194
280
 
281
+ sig { returns(T::Array[SetupTask]) }
195
282
  def setup_tasks
196
283
  @setup_tasks ||= [
197
284
  SetupTask.new(
@@ -230,14 +317,17 @@ module Kuby
230
317
  ]
231
318
  end
232
319
 
320
+ sig { returns(Kubernetes::Spec) }
233
321
  def kubernetes
234
322
  environment.kubernetes
235
323
  end
236
324
 
325
+ sig { returns(Docker::Spec) }
237
326
  def docker
238
327
  environment.docker
239
328
  end
240
329
 
330
+ sig { returns T::Hash[Symbol, T.untyped] }
241
331
  def clis
242
332
  @clis ||= {
243
333
  kubectl: kubernetes.provider.kubernetes_cli,
@@ -248,6 +338,7 @@ module Kuby
248
338
  }
249
339
  end
250
340
 
341
+ sig { returns(Tasks) }
251
342
  def tasks
252
343
  @tasks ||= Kuby::Tasks.new(environment)
253
344
  end
@@ -1,3 +1,5 @@
1
+ # typed: strict
2
+
1
3
  require 'kuby/docker/errors'
2
4
 
3
5
  module Kuby
@@ -10,6 +12,7 @@ module Kuby
10
12
  autoload :Credentials, 'kuby/docker/credentials'
11
13
  autoload :Debian, 'kuby/docker/debian'
12
14
  autoload :DevSpec, 'kuby/docker/dev_spec'
15
+ autoload :Distro, 'kuby/docker/distro'
13
16
  autoload :Dockerfile, 'kuby/docker/dockerfile'
14
17
  autoload :InlineLayer, 'kuby/docker/inline_layer'
15
18
  autoload :Layer, 'kuby/docker/layer'
@@ -1,40 +1,43 @@
1
+ # typed: strict
2
+
1
3
  module Kuby
2
4
  module Docker
3
- class Alpine
4
- SHELL_EXE = '/bin/sh'.freeze
5
+ class Alpine < Distro
6
+ SHELL_EXE = T.let('/bin/sh'.freeze, String)
5
7
 
6
- DEFAULT_PACKAGES = [
7
- [:ca_certificates],
8
+ DEFAULT_PACKAGES = T.let([
9
+ [:ca_certificates, nil],
8
10
  [:nodejs, '12.14.1'],
9
11
  [:yarn, '1.21.1'],
10
- [:c_toolchain],
11
- [:tzdata]
12
- ].freeze
12
+ [:c_toolchain, nil],
13
+ [:tzdata, nil]
14
+ ].freeze, T::Array[[Symbol, T.nilable(String)]])
13
15
 
16
+ sig { returns(Layer) }
14
17
  attr_reader :phase
15
18
 
16
- def initialize(phase)
17
- @phase = phase
18
- end
19
-
19
+ sig { override.params(packages: T::Array[Distro::PackageImpl], into: Dockerfile).void }
20
20
  def install(packages, into:)
21
21
  dockerfile = into
22
22
  install_managed(packages, dockerfile)
23
23
  install_unmanaged(packages, dockerfile)
24
24
  end
25
25
 
26
+ sig { override.returns(T::Array[[Symbol, T.nilable(String)]]) }
26
27
  def default_packages
27
28
  DEFAULT_PACKAGES
28
29
  end
29
30
 
31
+ sig { override.returns(String) }
30
32
  def shell_exe
31
33
  SHELL_EXE
32
34
  end
33
35
 
34
36
  private
35
37
 
38
+ sig { params(packages: T::Array[Distro::PackageImpl], dockerfile: Dockerfile).void }
36
39
  def install_managed(packages, dockerfile)
37
- pkgs = packages.select(&:managed?)
40
+ pkgs = T.cast(packages.select(&:managed?), T::Array[Distro::ManagedPackageImpl])
38
41
 
39
42
  unless pkgs.empty?
40
43
  package_names = pkgs.map { |pkg| pkg.package_name_for(:alpine) }
@@ -44,6 +47,7 @@ module Kuby
44
47
  end
45
48
  end
46
49
 
50
+ sig { params(packages: T::Array[Distro::PackageImpl], dockerfile: Dockerfile).void }
47
51
  def install_unmanaged(packages, dockerfile)
48
52
  packages
49
53
  .reject(&:managed?)
@@ -1,6 +1,11 @@
1
+ # typed: strict
2
+
1
3
  module Kuby
2
4
  module Docker
3
5
  class AssetsPhase < Layer
6
+ extend T::Sig
7
+
8
+ sig { override.params(dockerfile: Dockerfile).void }
4
9
  def apply_to(dockerfile)
5
10
  dockerfile.run(
6
11
  'bundle', 'exec', 'rake', 'assets:precompile'
@@ -1,12 +1,44 @@
1
+ # typed: strict
2
+
1
3
  require 'pathname'
2
4
 
3
5
  module Kuby
4
6
  module Docker
5
7
  class BundlerPhase < Layer
6
- DEFAULT_WITHOUT = ['development', 'test', 'deploy'].freeze
8
+ extend T::Sig
9
+
10
+ DEFAULT_WITHOUT = T.let(
11
+ ['development', 'test', 'deploy'].freeze, T::Array[String]
12
+ )
13
+
14
+ sig { returns(T.nilable(String)) }
15
+ attr_reader :version
16
+
17
+ sig { params(version: String).void }
18
+ attr_writer :version
19
+
20
+ sig { returns(T.nilable(String)) }
21
+ attr_reader :gemfile
7
22
 
8
- attr_accessor :version, :gemfile, :without
23
+ sig { params(gemfile: String).void }
24
+ attr_writer :gemfile
25
+
26
+ sig { returns(T.nilable(T::Array[String])) }
27
+ attr_reader :without
28
+
29
+ sig { params(without: T::Array[String]).void }
30
+ attr_writer :without
31
+
32
+ sig { params(environment: Environment).void }
33
+ def initialize(environment)
34
+ super
35
+
36
+ @version = T.let(@version, T.nilable(String))
37
+ @gemfile = T.let(@gemfile, T.nilable(String))
38
+ @without = T.let(@without, T.nilable(T::Array[String]))
39
+ end
9
40
 
41
+ sig { override.params(dockerfile: Dockerfile).void }
10
42
  def apply_to(dockerfile)
11
43
  gf = gemfile || default_gemfile
12
44
  lf = "#{gf}.lock"
@@ -41,10 +73,12 @@ module Kuby
41
73
 
42
74
  private
43
75
 
76
+ sig { returns(String) }
44
77
  def default_version
45
78
  Bundler::VERSION
46
79
  end
47
80
 
81
+ sig { returns(String) }
48
82
  def default_gemfile
49
83
  Bundler
50
84
  .definition