kuby-core 0.17.0 → 0.18.0

Sign up to get free protection for your applications and to get access to all the features.
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