kuby-core 0.17.0 → 0.18.0

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 (91) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +44 -0
  3. data/Gemfile +6 -2
  4. data/Rakefile +5 -3
  5. data/bin/tapioca +29 -0
  6. data/kuby-core.gemspec +9 -11
  7. data/lib/kuby/basic_logger.rb +34 -34
  8. data/lib/kuby/cli_base.rb +43 -43
  9. data/lib/kuby/commands.rb +94 -11
  10. data/lib/kuby/definition.rb +12 -12
  11. data/lib/kuby/dependable.rb +20 -0
  12. data/lib/kuby/dependency.rb +14 -0
  13. data/lib/kuby/docker/alpine.rb +10 -10
  14. data/lib/kuby/docker/app_image.rb +11 -11
  15. data/lib/kuby/docker/app_phase.rb +36 -0
  16. data/lib/kuby/docker/assets_phase.rb +2 -2
  17. data/lib/kuby/docker/bundler_phase.rb +42 -40
  18. data/lib/kuby/docker/cli.rb +71 -43
  19. data/lib/kuby/docker/copy_phase.rb +7 -7
  20. data/lib/kuby/docker/credentials.rb +1 -0
  21. data/lib/kuby/docker/debian.rb +10 -10
  22. data/lib/kuby/docker/distro.rb +13 -13
  23. data/lib/kuby/docker/docker_uri.rb +20 -20
  24. data/lib/kuby/docker/dockerfile.rb +48 -39
  25. data/lib/kuby/docker/image.rb +66 -54
  26. data/lib/kuby/docker/inline_layer.rb +4 -4
  27. data/lib/kuby/docker/layer.rb +6 -6
  28. data/lib/kuby/docker/layer_stack.rb +35 -35
  29. data/lib/kuby/docker/local_tags.rb +16 -16
  30. data/lib/kuby/docker/package_list.rb +16 -16
  31. data/lib/kuby/docker/package_phase.rb +16 -16
  32. data/lib/kuby/docker/packages/managed_package.rb +13 -13
  33. data/lib/kuby/docker/packages/nodejs.rb +5 -5
  34. data/lib/kuby/docker/packages/package.rb +8 -8
  35. data/lib/kuby/docker/packages/simple_managed_package.rb +7 -7
  36. data/lib/kuby/docker/packages/yarn.rb +6 -6
  37. data/lib/kuby/docker/remote_tags.rb +16 -16
  38. data/lib/kuby/docker/setup_phase.rb +18 -20
  39. data/lib/kuby/docker/spec.rb +93 -72
  40. data/lib/kuby/docker/timestamp_tag.rb +16 -11
  41. data/lib/kuby/docker/timestamped_image.rb +59 -40
  42. data/lib/kuby/docker/webserver_phase.rb +20 -20
  43. data/lib/kuby/docker/yarn_phase.rb +29 -5
  44. data/lib/kuby/docker.rb +2 -1
  45. data/lib/kuby/kubernetes/bare_metal_provider.rb +9 -9
  46. data/lib/kuby/kubernetes/deployer.rb +22 -10
  47. data/lib/kuby/kubernetes/docker_config.rb +1 -0
  48. data/lib/kuby/kubernetes/provider.rb +1 -0
  49. data/lib/kuby/kubernetes/spec.rb +47 -7
  50. data/lib/kuby/plugin.rb +22 -1
  51. data/lib/kuby/plugins/nginx_ingress.rb +8 -6
  52. data/lib/kuby/plugins/rails_app/assets.rb +16 -4
  53. data/lib/kuby/plugins/rails_app/assets_image.rb +17 -8
  54. data/lib/kuby/plugins/rails_app/crdb/plugin.rb +473 -0
  55. data/lib/kuby/plugins/rails_app/crdb.rb +9 -0
  56. data/lib/kuby/plugins/rails_app/database.rb +12 -8
  57. data/lib/kuby/plugins/rails_app/generators/kuby.rb +17 -16
  58. data/lib/kuby/plugins/rails_app/plugin.rb +29 -18
  59. data/lib/kuby/plugins/rails_app/sqlite.rb +7 -3
  60. data/lib/kuby/plugins/rails_app/tasks.rake +25 -12
  61. data/lib/kuby/plugins/rails_app.rb +1 -0
  62. data/lib/kuby/plugins/system.rb +16 -0
  63. data/lib/kuby/plugins.rb +1 -0
  64. data/lib/kuby/railtie.rb +31 -1
  65. data/lib/kuby/tasks.rb +72 -5
  66. data/lib/kuby/trailing_hash.rb +2 -2
  67. data/lib/kuby/utils/sem_ver/constraint.rb +68 -0
  68. data/lib/kuby/utils/sem_ver/constraint_set.rb +25 -0
  69. data/lib/kuby/utils/sem_ver/version.rb +49 -0
  70. data/lib/kuby/utils/sem_ver.rb +17 -0
  71. data/lib/kuby/utils/which.rb +65 -0
  72. data/lib/kuby/utils.rb +7 -1
  73. data/lib/kuby/version.rb +1 -1
  74. data/lib/kuby.rb +37 -2
  75. data/rbi/kuby-core.rbi +2128 -0
  76. data/spec/docker/spec_spec.rb +50 -26
  77. data/spec/dummy/app/channels/application_cable/channel.rb +2 -1
  78. data/spec/dummy/app/channels/application_cable/connection.rb +2 -1
  79. data/spec/dummy/app/controllers/application_controller.rb +2 -1
  80. data/spec/dummy/app/jobs/application_job.rb +2 -1
  81. data/spec/dummy/app/mailers/application_mailer.rb +2 -1
  82. data/spec/dummy/app/models/application_record.rb +2 -1
  83. data/spec/dummy/config/application.rb +2 -1
  84. data/spec/dummy/config/initializers/wrap_parameters.rb +2 -1
  85. data/spec/dummy/config/routes.rb +2 -1
  86. data/spec/dummy/test/application_system_test_case.rb +2 -1
  87. data/spec/dummy/test/channels/application_cable/connection_test.rb +2 -1
  88. data/spec/spec_helper.rb +13 -1
  89. metadata +44 -39
  90. data/lib/kuby/plugins/rails_app/mysql.rb +0 -158
  91. data/lib/kuby/plugins/rails_app/postgres.rb +0 -163
@@ -3,201 +3,221 @@
3
3
  module Kuby
4
4
  module Docker
5
5
  class Spec
6
- extend T::Sig
6
+ # extend T::Sig
7
7
 
8
8
  DEFAULT_DISTRO = :debian
9
+ DEFAULT_APP_ROOT_PATH = '.'.freeze
9
10
 
10
- sig { returns(Environment) }
11
+ # T::Sig::WithoutRuntime.sig { returns(Kuby::Environment) }
11
12
  attr_reader :environment
12
13
 
13
- sig { returns(T.nilable(String)) }
14
+ # T::Sig::WithoutRuntime.sig { returns(T.nilable(String)) }
14
15
  attr_reader :image_url_str
15
16
 
16
- sig { returns(T.nilable(String)) }
17
+ # T::Sig::WithoutRuntime.sig { returns(T.nilable(String)) }
17
18
  attr_reader :registry_index_url_str
18
19
 
19
- sig { params(environment: Environment).void }
20
+ # T::Sig::WithoutRuntime.sig { returns(T.nilable(String)) }
21
+ attr_reader :app_root_path
22
+
23
+ # T::Sig::WithoutRuntime.sig { returns T.nilable(Kuby::Docker::AppImage) }
24
+ attr_reader :image
25
+
26
+ # T::Sig::WithoutRuntime.sig { params(environment: Kuby::Environment).void }
20
27
  def initialize(environment)
21
28
  @environment = environment
22
29
 
23
- @credentials = T.let(@credentials, T.nilable(Credentials))
24
- @setup_phase = T.let(@setup_phase, T.nilable(SetupPhase))
25
- @package_phase = T.let(@package_phase, T.nilable(PackagePhase))
26
- @bundler_phase = T.let(@bundler_phase, T.nilable(BundlerPhase))
27
- @yarn_phase = T.let(@yarn_phase, T.nilable(YarnPhase))
28
- @copy_phase = T.let(@copy_phase, T.nilable(CopyPhase))
29
- @assets_phase = T.let(@assets_phase, T.nilable(AssetsPhase))
30
- @webserver_phase = T.let(@webserver_phase, T.nilable(WebserverPhase))
30
+ # @credentials = T.let(@credentials, T.nilable(Credentials))
31
+ # @setup_phase = T.let(@setup_phase, T.nilable(SetupPhase))
32
+ # @package_phase = T.let(@package_phase, T.nilable(PackagePhase))
33
+ # @bundler_phase = T.let(@bundler_phase, T.nilable(BundlerPhase))
34
+ # @yarn_phase = T.let(@yarn_phase, T.nilable(YarnPhase))
35
+ # @copy_phase = T.let(@copy_phase, T.nilable(CopyPhase))
36
+ # @app_phase = T.let(@app_phase, T.nilable(AppPhase))
37
+ # @assets_phase = T.let(@assets_phase, T.nilable(AssetsPhase))
38
+ # @webserver_phase = T.let(@webserver_phase, T.nilable(WebserverPhase))
31
39
 
32
- @distro_name = T.let(@distro_name, T.nilable(Symbol))
33
- @distro_spec = T.let(@distro_spec, T.nilable(Distro))
34
- @layer_stack = T.let(@layer_stack, T.nilable(Kuby::Docker::LayerStack))
40
+ # @distro_name = T.let(@distro_name, T.nilable(Symbol))
41
+ # @distro_spec = T.let(@distro_spec, T.nilable(Distro))
42
+ # @layer_stack = T.let(@layer_stack, T.nilable(Kuby::Docker::LayerStack))
35
43
 
36
- @image_url_str = T.let(@image_url_str, T.nilable(String))
37
- @registry_index_url_str = T.let(@registry_index_url_str, T.nilable(String))
38
- @image = T.let(@image, T.nilable(Docker::AppImage))
44
+ # @image_url_str = T.let(@image_url_str, T.nilable(String))
45
+ # @registry_index_url_str = T.let(@registry_index_url_str, T.nilable(String))
46
+ # @image = T.let(@image, T.nilable(Docker::AppImage))
47
+
48
+ @app_root_path = DEFAULT_APP_ROOT_PATH
39
49
  end
40
50
 
41
- sig { returns(Symbol) }
51
+ # T::Sig::WithoutRuntime.sig { returns(Symbol) }
42
52
  def distro_name
43
53
  @distro_name || DEFAULT_DISTRO
44
54
  end
45
55
 
46
- sig { params(image_url: String).void }
56
+ # T::Sig::WithoutRuntime.sig { params(image_url: String).void }
47
57
  def base_image(image_url)
48
58
  setup_phase.base_image = image_url
49
59
  end
50
60
 
51
- sig { params(dir: String).void }
61
+ # T::Sig::WithoutRuntime.sig { params(dir: String).void }
52
62
  def working_dir(dir)
53
63
  setup_phase.working_dir = dir
54
64
  end
55
65
 
56
- sig { params(env: String).void }
66
+ # T::Sig::WithoutRuntime.sig { params(env: String).void }
57
67
  def rails_env(env)
58
68
  setup_phase.rails_env = env
59
69
  end
60
70
 
61
- sig { params(version: String).void }
71
+ # T::Sig::WithoutRuntime.sig { params(version: String).void }
62
72
  def bundler_version(version)
63
73
  bundler_phase.version = version
64
74
  end
65
75
 
66
- sig { params(path: String).void }
76
+ # T::Sig::WithoutRuntime.sig { params(path: String).void }
67
77
  def gemfile(path)
68
78
  bundler_phase.gemfile = path
69
79
  end
70
80
 
71
- sig {
72
- params(
73
- package_name: Symbol,
74
- version: T.nilable(String)
75
- )
76
- .void
77
- }
81
+ # T::Sig::WithoutRuntime.sig { params(path: String).void }
82
+ def app_root(path)
83
+ @app_root_path = path
84
+ end
85
+
86
+ # T::Sig::WithoutRuntime.sig {
87
+ # params(
88
+ # package_name: Symbol,
89
+ # version: T.nilable(String)
90
+ # )
91
+ # .void
92
+ # }
78
93
  def package(package_name, version = nil)
79
94
  package_phase.add(package_name, version)
80
95
  end
81
96
 
82
- sig { params(distro_name: Symbol).void }
97
+ # T::Sig::WithoutRuntime.sig { params(distro_name: Symbol).void }
83
98
  def distro(distro_name)
84
99
  @distro_name = distro_name
85
100
  @distro_spec = nil
86
101
  end
87
102
 
88
- sig { params(path: String).void }
103
+ # T::Sig::WithoutRuntime.sig { params(path: String).void }
89
104
  def files(path)
90
105
  copy_phase << path
91
106
  end
92
107
 
93
- sig { params(port: Integer).void }
108
+ # T::Sig::WithoutRuntime.sig { params(port: Integer).void }
94
109
  def port(port)
95
110
  webserver_phase.port = port
96
111
  end
97
112
 
98
- sig { params(url: String).void }
113
+ # T::Sig::WithoutRuntime.sig { params(url: String).void }
99
114
  def image_url(url)
100
115
  @image_url_str = url
101
116
  end
102
117
 
103
- sig { params(url: String).void }
118
+ # T::Sig::WithoutRuntime.sig { params(url: String).void }
104
119
  def registry_index_url(url)
105
120
  @registry_index_url_str = url
106
121
  end
107
122
 
108
- sig {
109
- params(
110
- name: Symbol,
111
- layer: T.nilable(Layer),
112
- block: T.nilable(T.proc.params(df: Dockerfile).void)
113
- )
114
- .void
115
- }
123
+ # T::Sig::WithoutRuntime.sig {
124
+ # params(
125
+ # name: Symbol,
126
+ # layer: T.nilable(Layer),
127
+ # block: T.nilable(T.proc.params(df: Kuby::Docker::Dockerfile).void)
128
+ # )
129
+ # .void
130
+ # }
116
131
  def use(name, layer = nil, &block)
117
132
  layer_stack.use(name, layer, &block)
118
133
  end
119
134
 
120
- sig {
121
- params(
122
- name: Symbol,
123
- layer: T.nilable(T.any(Layer, T::Hash[Symbol, T.untyped])),
124
- options: T::Hash[Symbol, T.untyped],
125
- block: T.nilable(T.proc.params(df: Dockerfile).void)
126
- )
127
- .void
128
- }
135
+ # T::Sig::WithoutRuntime.sig {
136
+ # params(
137
+ # name: Symbol,
138
+ # layer: T.nilable(T.any(Layer, T::Hash[Symbol, T.untyped])),
139
+ # options: T::Hash[Symbol, T.untyped],
140
+ # block: T.nilable(T.proc.params(df: Dockerfile).void)
141
+ # )
142
+ # .void
143
+ # }
129
144
  def insert(name, layer = nil, options = {}, &block)
130
145
  layer_stack.insert(name, layer, options, &block)
131
146
  end
132
147
 
133
- sig { params(name: Symbol).void }
148
+ # T::Sig::WithoutRuntime.sig { params(name: Symbol).void }
134
149
  def delete(name)
135
150
  layer_stack.delete(name)
136
151
  end
137
152
 
138
- sig { params(name: Symbol).returns(T::Boolean) }
153
+ # T::Sig::WithoutRuntime.sig { params(name: Symbol).returns(T::Boolean) }
139
154
  def exists?(name)
140
155
  layer_stack.includes?(name)
141
156
  end
142
157
 
143
- sig {
144
- params(block: T.nilable(T.proc.void)).returns(Credentials)
145
- }
158
+ # T::Sig::WithoutRuntime.sig {
159
+ # params(block: T.nilable(T.proc.void)).returns(Kuby::Docker::Credentials)
160
+ # }
146
161
  def credentials(&block)
147
162
  @credentials ||= Credentials.new
148
163
  @credentials.instance_eval(&block) if block
149
164
  @credentials
150
165
  end
151
166
 
152
- sig { returns(Docker::AppImage) }
153
- def image
154
- @image ||= begin
167
+ # T::Sig::WithoutRuntime.sig { void }
168
+ def after_configuration
169
+ @image = begin
155
170
  dockerfile = Dockerfile.new.tap do |df|
156
171
  layer_stack.each { |layer| layer.apply_to(df) }
157
172
  end
158
173
 
159
174
  Docker::AppImage.new(
160
- dockerfile, T.must(image_url_str), credentials, registry_index_url_str
175
+ dockerfile, image_url_str, credentials, registry_index_url_str
161
176
  )
162
177
  end
163
178
  end
164
179
 
165
- sig { returns(SetupPhase) }
180
+ # T::Sig::WithoutRuntime.sig { returns(Kuby::Docker::SetupPhase) }
166
181
  def setup_phase
167
182
  @setup_phase ||= SetupPhase.new(environment, self)
168
183
  end
169
184
 
170
- sig { returns(PackagePhase) }
185
+ # T::Sig::WithoutRuntime.sig { returns(Kuby::Docker::PackagePhase) }
171
186
  def package_phase
172
187
  @package_phase ||= PackagePhase.new(environment)
173
188
  end
174
189
 
175
- sig { returns(BundlerPhase) }
190
+ # T::Sig::WithoutRuntime.sig { returns(Kuby::Docker::BundlerPhase) }
176
191
  def bundler_phase
177
192
  @bundler_phase ||= BundlerPhase.new(environment)
178
193
  end
179
194
 
180
- sig { returns(YarnPhase) }
195
+ # T::Sig::WithoutRuntime.sig { returns(Kuby::Docker::YarnPhase) }
181
196
  def yarn_phase
182
197
  @yarn_phase ||= YarnPhase.new(environment)
183
198
  end
184
199
 
185
- sig { returns(CopyPhase) }
200
+ # T::Sig::WithoutRuntime.sig { returns(Kuby::Docker::CopyPhase) }
186
201
  def copy_phase
187
202
  @copy_phase ||= CopyPhase.new(environment)
188
203
  end
189
204
 
190
- sig { returns(AssetsPhase) }
205
+ # T::Sig::WithoutRuntime.sig { returns(Kuby::Docker::AppPhase) }
206
+ def app_phase
207
+ @app_phase ||= AppPhase.new(environment)
208
+ end
209
+
210
+ # T::Sig::WithoutRuntime.sig { returns(Kuby::Docker::AssetsPhase) }
191
211
  def assets_phase
192
212
  @assets_phase ||= AssetsPhase.new(environment)
193
213
  end
194
214
 
195
- sig { returns(WebserverPhase) }
215
+ # T::Sig::WithoutRuntime.sig { returns(Kuby::Docker::WebserverPhase) }
196
216
  def webserver_phase
197
217
  @webserver_phase ||= WebserverPhase.new(environment)
198
218
  end
199
219
 
200
- sig { returns(Distro) }
220
+ # T::Sig::WithoutRuntime.sig { returns(Kuby::Docker::Distro) }
201
221
  def distro_spec
202
222
  @distro_spec ||= if distro_klass = Kuby.distros[distro_name]
203
223
  distro_klass.new(self)
@@ -208,7 +228,7 @@ module Kuby
208
228
 
209
229
  private
210
230
 
211
- sig { returns(Kuby::Docker::LayerStack) }
231
+ # T::Sig::WithoutRuntime.sig { returns(Kuby::Docker::LayerStack) }
212
232
  def layer_stack
213
233
  @layer_stack ||= Kuby::Docker::LayerStack.new.tap do |stack|
214
234
  stack.use(:setup_phase, setup_phase)
@@ -216,6 +236,7 @@ module Kuby
216
236
  stack.use(:bundler_phase, bundler_phase)
217
237
  stack.use(:yarn_phase, yarn_phase)
218
238
  stack.use(:copy_phase, copy_phase)
239
+ stack.use(:app_phase, app_phase)
219
240
  stack.use(:assets_phase, assets_phase)
220
241
  stack.use(:webserver_phase, webserver_phase)
221
242
  end
@@ -5,11 +5,11 @@ require 'time'
5
5
  module Kuby
6
6
  module Docker
7
7
  class TimestampTag
8
- extend T::Sig
8
+ # extend T::Sig
9
9
 
10
- FORMAT = T.let('%Y%m%d%H%M%S'.freeze, String)
10
+ FORMAT = '%Y%m%d%H%M%S'.freeze
11
11
 
12
- sig { params(str: T.nilable(String)).returns(T.nilable(TimestampTag)) }
12
+ # T::Sig::WithoutRuntime.sig { params(str: T.nilable(String)).returns(T.nilable(Kuby::Docker::TimestampTag)) }
13
13
  def self.try_parse(str)
14
14
  return nil unless str
15
15
 
@@ -27,35 +27,40 @@ module Kuby
27
27
  new(time)
28
28
  end
29
29
 
30
- sig { returns(Time) }
30
+ # T::Sig::WithoutRuntime.sig { returns(Kuby::Docker::TimestampTag) }
31
+ def self.now
32
+ new(Time.now.utc)
33
+ end
34
+
35
+ # T::Sig::WithoutRuntime.sig { returns(Time) }
31
36
  attr_reader :time
32
37
 
33
- sig { params(time: Time).void }
38
+ # T::Sig::WithoutRuntime.sig { params(time: Time).void }
34
39
  def initialize(time)
35
- @time = T.let(time, Time)
40
+ @time = time
36
41
  end
37
42
 
38
- sig { returns(String) }
43
+ # T::Sig::WithoutRuntime.sig { returns(String) }
39
44
  def to_s
40
45
  time.strftime(FORMAT)
41
46
  end
42
47
 
43
- sig { params(other: TimestampTag).returns(T.nilable(Integer)) }
48
+ # T::Sig::WithoutRuntime.sig { params(other: Kuby::Docker::TimestampTag).returns(T.nilable(Integer)) }
44
49
  def <=>(other)
45
50
  time <=> other.time
46
51
  end
47
52
 
48
- sig { params(other: TimestampTag).returns(T::Boolean) }
53
+ # T::Sig::WithoutRuntime.sig { params(other: Kuby::Docker::TimestampTag).returns(T::Boolean) }
49
54
  def ==(other)
50
55
  time == other.time
51
56
  end
52
57
 
53
- sig { returns(Integer) }
58
+ # T::Sig::WithoutRuntime.sig { returns(Integer) }
54
59
  def hash
55
60
  time.hash
56
61
  end
57
62
 
58
- sig { params(other: TimestampTag).returns(T::Boolean) }
63
+ # T::Sig::WithoutRuntime.sig { params(other: Kuby::Docker::TimestampTag).returns(T::Boolean) }
59
64
  def eql?(other)
60
65
  time == other.time
61
66
  end
@@ -5,54 +5,56 @@ require 'docker/remote'
5
5
  module Kuby
6
6
  module Docker
7
7
  class TimestampedImage < Image
8
- extend T::Sig
9
-
10
- sig {
11
- params(
12
- dockerfile: T.any(Dockerfile, T.proc.returns(Dockerfile)),
13
- image_url: String,
14
- credentials: Credentials,
15
- registry_index_url_str: T.nilable(String),
16
- main_tag: T.nilable(String),
17
- alias_tags: T::Array[String]
18
- ).void
19
- }
8
+ # extend T::Sig
9
+
10
+ # T::Sig::WithoutRuntime.sig {
11
+ # params(
12
+ # dockerfile: T.any(Dockerfile, T.proc.returns(Kuby::Docker::Dockerfile)),
13
+ # image_url: String,
14
+ # credentials: Kuby::Docker::Credentials,
15
+ # registry_index_url_str: T.nilable(String),
16
+ # main_tag: T.nilable(String),
17
+ # alias_tags: T::Array[String]
18
+ # ).void
19
+ # }
20
20
  def initialize(dockerfile, image_url, credentials, registry_index_url_str = nil, main_tag = nil, alias_tags = [])
21
- @new_version = T.let(@new_version, T.nilable(Image))
22
- @current_version = T.let(@current_version, T.nilable(Image))
23
- @previous_version = T.let(@previous_version, T.nilable(Image))
21
+ # @new_version = T.let(@new_version, T.nilable(Image))
22
+ # @current_version = T.let(@current_version, T.nilable(Image))
23
+ # @previous_version = T.let(@previous_version, T.nilable(Image))
24
24
 
25
- @remote_client = T.let(@remote_client, T.nilable(::Docker::Remote::Client))
26
- @local = T.let(@local, T.nilable(LocalTags))
27
- @remote = T.let(@remote, T.nilable(RemoteTags))
25
+ # @remote_client = T.let(@remote_client, T.nilable(::Docker::Remote::Client))
26
+ # @local = T.let(@local, T.nilable(LocalTags))
27
+ # @remote = T.let(@remote, T.nilable(RemoteTags))
28
28
 
29
29
  super
30
30
  end
31
31
 
32
- sig { returns(Image) }
32
+ # T::Sig::WithoutRuntime.sig { returns(Kuby::Docker::Image) }
33
33
  def new_version
34
- @new_version ||= create_new_version
34
+ @new_version ||= duplicate_with_tags(
35
+ TimestampTag.now.to_s, [Kuby::Docker::LATEST_TAG]
36
+ )
35
37
  end
36
38
 
37
- sig { returns(Image) }
39
+ # T::Sig::WithoutRuntime.sig { returns(Kuby::Docker::Image) }
38
40
  def current_version
39
41
  @current_version ||= begin
40
42
  duplicate_with_tags(
41
43
  latest_timestamp_tag.to_s, [Kuby::Docker::LATEST_TAG]
42
44
  )
43
45
  rescue MissingTagError
44
- create_new_version
46
+ new_version
45
47
  end
46
48
  end
47
49
 
48
- sig { params(current_tag: T.nilable(String)).returns(Image) }
50
+ # T::Sig::WithoutRuntime.sig { params(current_tag: T.nilable(String)).returns(Kuby::Docker::Image) }
49
51
  def previous_version(current_tag = nil)
50
52
  @previous_version ||= duplicate_with_tags(
51
53
  previous_timestamp_tag(current_tag).to_s, []
52
54
  )
53
55
  end
54
56
 
55
- sig { params(current_tag: T.nilable(String)).returns(TimestampTag) }
57
+ # T::Sig::WithoutRuntime.sig { params(current_tag: T.nilable(String)).returns(Kuby::Docker::TimestampTag) }
56
58
  def previous_timestamp_tag(current_tag = nil)
57
59
  current_tag = TimestampTag.try_parse(current_tag || latest_timestamp_tag.to_s)
58
60
  raise MissingTagError, 'could not find current timestamp tag' unless current_tag
@@ -66,53 +68,70 @@ module Kuby
66
68
  idx ||= 0
67
69
  raise MissingTagError, 'could not find previous timestamp tag' unless idx > 0
68
70
 
69
- T.must(all_tags[idx - 1])
71
+ all_tags[idx - 1]
70
72
  end
71
73
 
72
- sig { returns(TimestampTag) }
74
+ # T::Sig::WithoutRuntime.sig { returns(Kuby::Docker::TimestampTag) }
73
75
  def latest_timestamp_tag
74
76
  tag = timestamp_tags.sort.last
75
77
  raise MissingTagError, 'could not find latest timestamp tag' unless tag
76
78
  tag
77
79
  end
78
80
 
79
- sig { params(build_args: T::Hash[String, String], docker_args: T::Array[String], context: T.nilable(String)).void }
80
- def build(build_args = {}, docker_args = [], context: nil)
81
- docker_cli.build(new_version, build_args: build_args, docker_args: docker_args, context: context)
81
+ # T::Sig::WithoutRuntime.sig {
82
+ # params(
83
+ # build_args: T::Hash[String, String],
84
+ # docker_args: T::Array[String],
85
+ # context: T.nilable(String),
86
+ # cache_from: T.nilable(String)
87
+ # ).void
88
+ # }
89
+ def build(build_args = {}, docker_args = [], context: nil, cache_from: nil)
90
+ docker_cli.build(
91
+ self,
92
+ build_args: build_args,
93
+ docker_args: docker_args,
94
+ context: context,
95
+ cache_from: cache_from
96
+ )
82
97
  end
83
98
 
84
- sig { params(tag: String).void }
99
+ # T::Sig::WithoutRuntime.sig { params(tag: String).void }
85
100
  def push(tag)
86
101
  docker_cli.push(image_url, tag)
87
102
  end
88
103
 
89
- private
104
+ # T::Sig::WithoutRuntime.sig { params(tag: String).void }
105
+ def pull(tag)
106
+ docker_cli.pull(image_url, tag)
107
+ end
90
108
 
91
- sig { returns(Image) }
92
- def create_new_version
93
- duplicate_with_tags(
94
- TimestampTag.new(Time.now).to_s, [Kuby::Docker::LATEST_TAG]
95
- )
109
+ # T::Sig::WithoutRuntime.sig { returns(T::Boolean) }
110
+ def exists?
111
+ return false unless main_tag
112
+ timestamp_tags.include?(TimestampTag.try_parse(main_tag))
96
113
  end
97
114
 
98
- sig { returns(::Docker::Remote::Client) }
115
+ private
116
+
117
+ # T::Sig::WithoutRuntime.sig { returns(::Docker::Remote::Client) }
99
118
  def remote_client
100
119
  @remote_client ||= ::Docker::Remote::Client.new(
101
120
  registry_index_host, image_repo, credentials.username, credentials.password,
102
121
  )
103
122
  end
104
123
 
105
- sig { returns(T::Array[TimestampTag]) }
124
+ # T::Sig::WithoutRuntime.sig { returns(T::Array[Kuby::Docker::TimestampTag]) }
106
125
  def timestamp_tags
107
126
  (local.timestamp_tags + remote.timestamp_tags).uniq
108
127
  end
109
128
 
110
- sig { returns(LocalTags) }
129
+ # T::Sig::WithoutRuntime.sig { returns(Kuby::Docker::LocalTags) }
111
130
  def local
112
131
  @local ||= LocalTags.new(docker_cli, image_url)
113
132
  end
114
133
 
115
- sig { returns(RemoteTags) }
134
+ # T::Sig::WithoutRuntime.sig { returns(Kuby::Docker::RemoteTags) }
116
135
  def remote
117
136
  @remote ||= RemoteTags.new(remote_client, registry_index_host)
118
137
  end
@@ -3,28 +3,28 @@
3
3
  module Kuby
4
4
  module Docker
5
5
  class WebserverPhase < Layer
6
- extend T::Sig
6
+ # extend T::Sig
7
7
 
8
8
  class Webserver
9
- extend T::Sig
10
- extend T::Helpers
9
+ # extend T::Sig
10
+ # extend T::Helpers
11
11
 
12
- abstract!
12
+ # abstract!
13
13
 
14
- sig { returns(WebserverPhase) }
14
+ # T::Sig::WithoutRuntime.sig { returns(WebserverPhase) }
15
15
  attr_reader :phase
16
16
 
17
- sig { params(phase: WebserverPhase).void }
17
+ # T::Sig::WithoutRuntime.sig { params(phase: WebserverPhase).void }
18
18
  def initialize(phase)
19
19
  @phase = phase
20
20
  end
21
21
 
22
- sig { abstract.params(dockerfile: Dockerfile).void }
22
+ # T::Sig::WithoutRuntime.sig { abstract.params(dockerfile: Dockerfile).void }
23
23
  def apply_to(dockerfile); end
24
24
  end
25
25
 
26
26
  class Puma < Webserver
27
- sig { override.params(dockerfile: Dockerfile).void }
27
+ # T::Sig::WithoutRuntime.sig { override.params(dockerfile: Dockerfile).void }
28
28
  def apply_to(dockerfile)
29
29
  dockerfile.cmd(
30
30
  'puma',
@@ -39,43 +39,43 @@ module Kuby
39
39
  end
40
40
  end
41
41
 
42
- DEFAULT_PORT = T.let(8080, Integer)
43
- WEBSERVER_MAP = T.let({ puma: Puma }.freeze, T::Hash[Symbol, T.class_of(Webserver)])
42
+ DEFAULT_PORT = 8080
43
+ WEBSERVER_MAP = { puma: Puma }.freeze
44
44
 
45
- sig { params(port: Integer).void }
45
+ # T::Sig::WithoutRuntime.sig { params(port: Integer).returns(Integer) }
46
46
  attr_writer :port
47
47
 
48
- sig { returns(T.nilable(Symbol)) }
48
+ # T::Sig::WithoutRuntime.sig { returns(T.nilable(Symbol)) }
49
49
  attr_reader :webserver
50
50
 
51
- sig { params(webserver: Symbol).void }
51
+ # T::Sig::WithoutRuntime.sig { params(webserver: Symbol).returns(Symbol) }
52
52
  attr_writer :webserver
53
53
 
54
- sig { override.params(environment: Environment).void }
54
+ # T::Sig::WithoutRuntime.sig { override.params(environment: Environment).void }
55
55
  def initialize(environment)
56
56
  super
57
57
 
58
- @port = T.let(@port, T.nilable(Integer))
59
- @webserver = T.let(@webserver, T.nilable(Symbol))
58
+ # @port = T.let(@port, T.nilable(Integer))
59
+ # @webserver = T.let(@webserver, T.nilable(Symbol))
60
60
  end
61
61
 
62
- sig { override.params(dockerfile: Dockerfile).void }
62
+ # T::Sig::WithoutRuntime.sig { override.params(dockerfile: Dockerfile).void }
63
63
  def apply_to(dockerfile)
64
64
  ws = webserver || default_webserver
65
- ws_class = WEBSERVER_MAP[T.must(ws)]
65
+ ws_class = WEBSERVER_MAP[ws]
66
66
  raise "No webserver named #{ws}" unless ws_class
67
67
 
68
68
  ws_class.new(self).apply_to(dockerfile)
69
69
  end
70
70
 
71
- sig { returns(Integer) }
71
+ # T::Sig::WithoutRuntime.sig { returns(Integer) }
72
72
  def port
73
73
  @port || DEFAULT_PORT
74
74
  end
75
75
 
76
76
  private
77
77
 
78
- sig { returns(T.nilable(Symbol)) }
78
+ # T::Sig::WithoutRuntime.sig { returns(T.nilable(Symbol)) }
79
79
  def default_webserver
80
80
  if Gem.loaded_specs.include?('puma')
81
81
  :puma
@@ -3,13 +3,37 @@
3
3
  module Kuby
4
4
  module Docker
5
5
  class YarnPhase < Layer
6
- extend T::Sig
6
+ # extend T::Sig
7
7
 
8
- sig { params(dockerfile: Dockerfile).void }
8
+ # T::Sig::WithoutRuntime.sig { params(dockerfile: Dockerfile).void }
9
9
  def apply_to(dockerfile)
10
- # use character classes as a hack to only copy the files if they exist
11
- dockerfile.copy('package.json yarn.loc[k] .npmr[c] .yarnr[c]', './')
12
- dockerfile.run('yarn', 'install')
10
+ host_path = environment.docker.app_root_path
11
+
12
+ # if more than one file is passed to the COPY directive, the destination must be
13
+ # a directory and must end with a slash
14
+ container_path = ensure_trailing_delimiter(
15
+ File.join(
16
+ dockerfile.current_workdir,
17
+ environment.docker.app_root_path
18
+ )
19
+ )
20
+
21
+ if File.exist?(File.join(host_path, 'package.json'))
22
+ # use brackets as a hack to only copy the files if they exist
23
+ dockerfile.copy(
24
+ "#{host_path}/package.json #{host_path}/yarn.loc[k] #{host_path}/.npmr[c] #{host_path}/.yarnr[c]",
25
+ container_path
26
+ )
27
+
28
+ dockerfile.run('yarn', 'install', '--cwd', container_path)
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ # T::Sig::WithoutRuntime.sig { params(path: String).returns(String) }
35
+ def ensure_trailing_delimiter(path)
36
+ path.end_with?(File::SEPARATOR) ? path : File.join(path, '')
13
37
  end
14
38
  end
15
39
  end