kuby-core 0.16.0 → 0.18.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +58 -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 +135 -21
  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 -20
  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 +72 -37
  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 +64 -38
  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 +12 -10
  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 +63 -13
  50. data/lib/kuby/plugin.rb +23 -1
  51. data/lib/kuby/plugin_registry.rb +15 -0
  52. data/lib/kuby/plugins/nginx_ingress.rb +8 -6
  53. data/lib/kuby/plugins/rails_app/assets.rb +16 -4
  54. data/lib/kuby/plugins/rails_app/assets_image.rb +18 -11
  55. data/lib/kuby/plugins/rails_app/crdb/plugin.rb +473 -0
  56. data/lib/kuby/plugins/rails_app/crdb.rb +9 -0
  57. data/lib/kuby/plugins/rails_app/database.rb +12 -8
  58. data/lib/kuby/plugins/rails_app/generators/kuby.rb +17 -16
  59. data/lib/kuby/plugins/rails_app/plugin.rb +37 -27
  60. data/lib/kuby/plugins/rails_app/sqlite.rb +7 -3
  61. data/lib/kuby/plugins/rails_app/tasks.rake +25 -12
  62. data/lib/kuby/plugins/rails_app.rb +1 -0
  63. data/lib/kuby/plugins/system.rb +16 -0
  64. data/lib/kuby/plugins.rb +1 -0
  65. data/lib/kuby/railtie.rb +31 -1
  66. data/lib/kuby/tasks.rb +91 -10
  67. data/lib/kuby/trailing_hash.rb +2 -2
  68. data/lib/kuby/utils/sem_ver/constraint.rb +68 -0
  69. data/lib/kuby/utils/sem_ver/constraint_set.rb +25 -0
  70. data/lib/kuby/utils/sem_ver/version.rb +49 -0
  71. data/lib/kuby/utils/sem_ver.rb +17 -0
  72. data/lib/kuby/utils/table.rb +35 -0
  73. data/lib/kuby/utils/which.rb +65 -0
  74. data/lib/kuby/utils.rb +11 -0
  75. data/lib/kuby/version.rb +1 -1
  76. data/lib/kuby.rb +37 -2
  77. data/rbi/kuby-core.rbi +2128 -0
  78. data/spec/docker/spec_spec.rb +50 -26
  79. data/spec/docker/timestamped_image_spec.rb +2 -2
  80. data/spec/dummy/app/channels/application_cable/channel.rb +2 -1
  81. data/spec/dummy/app/channels/application_cable/connection.rb +2 -1
  82. data/spec/dummy/app/controllers/application_controller.rb +2 -1
  83. data/spec/dummy/app/jobs/application_job.rb +2 -1
  84. data/spec/dummy/app/mailers/application_mailer.rb +2 -1
  85. data/spec/dummy/app/models/application_record.rb +2 -1
  86. data/spec/dummy/config/application.rb +2 -1
  87. data/spec/dummy/config/initializers/wrap_parameters.rb +2 -1
  88. data/spec/dummy/config/routes.rb +2 -1
  89. data/spec/dummy/test/application_system_test_case.rb +2 -1
  90. data/spec/dummy/test/channels/application_cable/connection_test.rb +2 -1
  91. data/spec/spec_helper.rb +13 -1
  92. metadata +46 -39
  93. data/lib/kuby/plugins/rails_app/mysql.rb +0 -158
  94. data/lib/kuby/plugins/rails_app/postgres.rb +0 -163
@@ -7,29 +7,29 @@ require 'shellwords'
7
7
  module Kuby
8
8
  module Docker
9
9
  class CLI < CLIBase
10
- extend T::Sig
10
+ # extend T::Sig
11
11
 
12
- sig { returns(String) }
12
+ # T::Sig::WithoutRuntime.sig { returns(String) }
13
13
  attr_reader :executable
14
14
 
15
- sig { params(executable: T.nilable(String)).void }
15
+ # T::Sig::WithoutRuntime.sig { params(executable: T.nilable(String)).void }
16
16
  def initialize(executable = nil)
17
- @executable = T.let(executable || `which docker`.strip, String)
17
+ @executable = executable || Kuby::Utils.which('docker')
18
18
  end
19
19
 
20
- sig { returns(T.nilable(String)) }
20
+ # T::Sig::WithoutRuntime.sig { returns(T.nilable(String)) }
21
21
  def config_file
22
22
  if File.exist?(default_config_file)
23
23
  default_config_file
24
24
  end
25
25
  end
26
26
 
27
- sig { returns(String) }
27
+ # T::Sig::WithoutRuntime.sig { returns(String) }
28
28
  def default_config_file
29
29
  File.join(Dir.home, '.docker', 'config.json')
30
30
  end
31
31
 
32
- sig { params(url: String, username: String, password: String).void }
32
+ # T::Sig::WithoutRuntime.sig { params(url: String, username: String, password: String).void }
33
33
  def login(url:, username:, password:)
34
34
  cmd = [
35
35
  executable, 'login', url, '--username', username, '--password-stdin'
@@ -39,52 +39,67 @@ module Kuby
39
39
  stdin.puts(password)
40
40
  end
41
41
 
42
- unless T.must(last_status).success?
42
+ unless last_status.success?
43
43
  raise LoginError, 'build failed: docker command exited with '\
44
- "status code #{T.must(last_status).exitstatus}"
44
+ "status code #{last_status.exitstatus}"
45
45
  end
46
46
  end
47
47
 
48
- sig { returns(T::Array[String]) }
48
+ # T::Sig::WithoutRuntime.sig { returns(T::Array[String]) }
49
49
  def auths
50
50
  return [] unless config_file
51
51
 
52
- config = JSON.parse(File.read(T.must(config_file)))
52
+ config = JSON.parse(File.read(config_file))
53
53
  config.fetch('auths', {}).keys
54
54
  end
55
55
 
56
- sig { params(image: Image, build_args: T::Hash[T.any(Symbol, String), String], docker_args: T::Array[String]).void }
57
- def build(image, build_args: {}, docker_args: [])
56
+ # T::Sig::WithoutRuntime.sig {
57
+ # params(
58
+ # image: Image,
59
+ # build_args: T::Hash[T.any(Symbol, String), String],
60
+ # docker_args: T::Array[String],
61
+ # context: T.nilable(String),
62
+ # cache_from: T.nilable(String)
63
+ # ).void
64
+ # }
65
+ def build(image, build_args: {}, docker_args: [], context: nil, cache_from: nil)
58
66
  cmd = [
59
67
  executable, 'build',
60
68
  *image.tags.flat_map { |tag| ['-t', "#{image.image_url}:#{tag}"] },
61
69
  *build_args.flat_map do |arg, val|
62
70
  ['--build-arg', Shellwords.shellescape("#{arg}=#{val}")]
63
- end,
71
+ end
72
+ ]
73
+
74
+ if cache_from
75
+ cmd += ['--cache-from', cache_from]
76
+ end
77
+
78
+ cmd += [
64
79
  '-f-',
65
80
  *docker_args,
66
- '.'
81
+ context || '.'
67
82
  ]
68
83
 
69
84
  open3_w(cmd) do |stdin, _wait_threads|
70
85
  stdin.puts(image.dockerfile.to_s)
71
86
  end
72
87
 
73
- unless T.must(last_status).success?
88
+ unless last_status.success?
74
89
  raise BuildError, 'build failed: docker command exited with '\
75
- "status code #{T.must(last_status).exitstatus}"
90
+ "status code #{last_status.exitstatus}"
76
91
  end
77
92
  end
78
93
 
79
- sig {
80
- params(
81
- image_url: String,
82
- tag: String,
83
- env: T::Hash[T.any(Symbol, String), String],
84
- ports: T::Array[T.any(String, Integer)]
85
- )
86
- .void
87
- }
94
+ # T::Sig::WithoutRuntime.sig {
95
+ # params(
96
+ # image_url: String,
97
+ # tag: String,
98
+ # env: T::Hash[T.any(Symbol, String), String],
99
+ # ports: T::Array[T.any(String, Integer)]
100
+ # )
101
+ # .void
102
+ # }
88
103
  def run(image_url:, tag: 'latest', env: {}, ports: [])
89
104
  cmd = [
90
105
  executable, 'run',
@@ -98,13 +113,33 @@ module Kuby
98
113
  execc(cmd)
99
114
  end
100
115
 
101
- sig { params(image_url: String).returns(T::Array[T::Hash[Symbol, String]]) }
102
- def images(image_url)
116
+ # T::Sig::WithoutRuntime.sig { params(container: String, command: String, tty: T::Boolean).returns(String) }
117
+ def exec_capture(container:, command:, tty: true)
118
+ cmd = [executable, 'exec']
119
+ cmd << '-it' if tty
120
+ cmd += [container, command]
121
+
122
+ backticks(cmd)
123
+ end
124
+
125
+ # T::Sig::WithoutRuntime.sig { params(image_url: String, tag: String, format: T.nilable(String)).returns(String) }
126
+ def inspect(image_url:, tag: 'latest', format: nil)
127
+ cmd = [executable, 'inspect']
128
+ cmd += ['--format', "'#{format}'"]
129
+ cmd << "#{image_url}:#{tag}"
130
+
131
+ backticks(cmd)
132
+ end
133
+
134
+ # T::Sig::WithoutRuntime.sig { params(image_url: String, digests: T::Boolean).returns(T::Array[T::Hash[Symbol, String]]) }
135
+ def images(image_url, digests: true)
103
136
  cmd = [
104
137
  executable, 'images', image_url,
105
138
  '--format', '"{{json . }}"'
106
139
  ]
107
140
 
141
+ cmd << '--digests' if digests
142
+
108
143
  backticks(cmd).split("\n").map do |image_data|
109
144
  JSON.parse(image_data).each_with_object({}) do |(k, v), ret|
110
145
  ret[k.underscore.to_sym] = v
@@ -112,41 +147,41 @@ module Kuby
112
147
  end
113
148
  end
114
149
 
115
- sig { params(image_url: String, tag: String).void }
150
+ # T::Sig::WithoutRuntime.sig { params(image_url: String, tag: String).void }
116
151
  def push(image_url, tag)
117
152
  systemm([
118
153
  executable, 'push', "#{image_url}:#{tag}"
119
154
  ])
120
155
 
121
- unless T.must(last_status).success?
156
+ unless last_status.success?
122
157
  raise PushError, 'push failed: docker command exited with '\
123
- "status code #{T.must(last_status).exitstatus}"
158
+ "status code #{last_status.exitstatus}"
124
159
  end
125
160
  end
126
161
 
127
- sig { params(image_url: String, tag: String).void }
162
+ # T::Sig::WithoutRuntime.sig { params(image_url: String, tag: String).void }
128
163
  def pull(image_url, tag)
129
164
  systemm([
130
165
  executable, 'pull', "#{image_url}:#{tag}"
131
166
  ])
132
167
 
133
- unless T.must(last_status).success?
168
+ unless last_status.success?
134
169
  raise PullError, 'pull failed: docker command exited with '\
135
- "status code #{T.must(last_status).exitstatus}"
170
+ "status code #{last_status.exitstatus}"
136
171
  end
137
172
  end
138
173
 
139
- sig { returns(Symbol) }
174
+ # T::Sig::WithoutRuntime.sig { returns(Symbol) }
140
175
  def status_key
141
176
  :kuby_docker_cli_last_status
142
177
  end
143
178
 
144
- sig { returns(Symbol) }
179
+ # T::Sig::WithoutRuntime.sig { returns(Symbol) }
145
180
  def stdout_key
146
181
  :kuby_docker_stdout
147
182
  end
148
183
 
149
- sig { returns(Symbol) }
184
+ # T::Sig::WithoutRuntime.sig { returns(Symbol) }
150
185
  def stderr_key
151
186
  :kuby_docker_stderr
152
187
  end
@@ -3,25 +3,25 @@
3
3
  module Kuby
4
4
  module Docker
5
5
  class CopyPhase < Layer
6
- extend T::Sig
6
+ # extend T::Sig
7
7
 
8
- DEFAULT_PATHS = T.let(['./'].freeze, T::Array[String])
8
+ DEFAULT_PATHS = ['./'].freeze
9
9
 
10
- sig { returns(T::Array[String]) }
10
+ # T::Sig::WithoutRuntime.sig { returns(T::Array[String]) }
11
11
  attr_reader :paths
12
12
 
13
- sig { params(environment: Environment).void }
13
+ # T::Sig::WithoutRuntime.sig { params(environment: Environment).void }
14
14
  def initialize(environment)
15
15
  super
16
- @paths = T.let([], T::Array[String])
16
+ @paths = []
17
17
  end
18
18
 
19
- sig { params(path: String).void }
19
+ # T::Sig::WithoutRuntime.sig { params(path: String).void }
20
20
  def <<(path)
21
21
  paths << path
22
22
  end
23
23
 
24
- sig { params(dockerfile: Dockerfile).void }
24
+ # T::Sig::WithoutRuntime.sig { params(dockerfile: Dockerfile).void }
25
25
  def apply_to(dockerfile)
26
26
  to_copy = paths.empty? ? DEFAULT_PATHS : paths
27
27
  to_copy.each { |path| dockerfile.copy(path, '.') }
@@ -1,4 +1,5 @@
1
1
  # typed: strict
2
+
2
3
  require 'kube-dsl'
3
4
 
4
5
  module Kuby
@@ -3,39 +3,39 @@
3
3
  module Kuby
4
4
  module Docker
5
5
  class Debian < Distro
6
- SHELL_EXE = T.let('/bin/bash'.freeze, String)
6
+ SHELL_EXE = '/bin/bash'.freeze
7
7
 
8
- DEFAULT_PACKAGES = T.let([
8
+ DEFAULT_PACKAGES = [
9
9
  [:ca_certificates, nil],
10
10
  [:nodejs, '12.14.1'],
11
11
  [:yarn, '1.21.1']
12
- ].freeze, T::Array[[Symbol, T.nilable(String)]])
12
+ ].freeze
13
13
 
14
- sig { returns(Layer) }
14
+ # T::Sig::WithoutRuntime.sig { returns(Layer) }
15
15
  attr_reader :phase
16
16
 
17
- sig { override.params(packages: T::Array[Distro::PackageImpl], into: Dockerfile).void }
17
+ # T::Sig::WithoutRuntime.sig { override.params(packages: T::Array[Distro::PackageImpl], into: Dockerfile).void }
18
18
  def install(packages, into:)
19
19
  dockerfile = into
20
20
  install_managed(packages, dockerfile)
21
21
  install_unmanaged(packages, dockerfile)
22
22
  end
23
23
 
24
- sig { override.returns(T::Array[[Symbol, T.nilable(String)]]) }
24
+ # T::Sig::WithoutRuntime.sig { override.returns(T::Array[[Symbol, T.nilable(String)]]) }
25
25
  def default_packages
26
26
  DEFAULT_PACKAGES
27
27
  end
28
28
 
29
- sig { override.returns(String) }
29
+ # T::Sig::WithoutRuntime.sig { override.returns(String) }
30
30
  def shell_exe
31
31
  SHELL_EXE
32
32
  end
33
33
 
34
34
  private
35
35
 
36
- sig { params(packages: T::Array[Distro::PackageImpl], dockerfile: Dockerfile).void }
36
+ # T::Sig::WithoutRuntime.sig { params(packages: T::Array[Distro::PackageImpl], dockerfile: Dockerfile).void }
37
37
  def install_managed(packages, dockerfile)
38
- pkgs = T.cast(packages.select(&:managed?), T::Array[Distro::ManagedPackageImpl])
38
+ pkgs = packages.select(&:managed?)
39
39
 
40
40
  pkg_cmd = <<~CMD.strip
41
41
  apt-get update -qq && \\
@@ -52,7 +52,7 @@ module Kuby
52
52
  dockerfile.run(pkg_cmd)
53
53
  end
54
54
 
55
- sig { params(packages: T::Array[Distro::PackageImpl], dockerfile: Dockerfile).void }
55
+ # T::Sig::WithoutRuntime.sig { params(packages: T::Array[Distro::PackageImpl], dockerfile: Dockerfile).void }
56
56
  def install_unmanaged(packages, dockerfile)
57
57
  packages
58
58
  .reject(&:managed?)
@@ -3,37 +3,37 @@
3
3
  module Kuby
4
4
  module Docker
5
5
  class Distro
6
- extend T::Sig
7
- extend T::Helpers
6
+ # extend T::Sig
7
+ # extend T::Helpers
8
8
 
9
- abstract!
9
+ # abstract!
10
10
 
11
- PackageImpl = T.type_alias {
12
- T.any(Packages::Package, Packages::ManagedPackage, Packages::SimpleManagedPackage)
13
- }
11
+ # PackageImpl = T.type_alias {
12
+ # T.any(Packages::Package, Packages::ManagedPackage, Packages::SimpleManagedPackage)
13
+ # }
14
14
 
15
- ManagedPackageImpl = T.type_alias {
16
- T.any(Packages::ManagedPackage, Packages::SimpleManagedPackage)
17
- }
15
+ # ManagedPackageImpl = T.type_alias {
16
+ # T.any(Packages::ManagedPackage, Packages::SimpleManagedPackage)
17
+ # }
18
18
 
19
- sig { params(phase: Layer).void }
19
+ # T::Sig::WithoutRuntime.sig { params(phase: Layer).void }
20
20
  def initialize(phase)
21
21
  @phase = phase
22
22
  end
23
23
 
24
- sig { params(packages: T::Array[PackageImpl], into: Dockerfile).void }
24
+ # T::Sig::WithoutRuntime.sig { params(packages: T::Array[PackageImpl], into: Dockerfile).void }
25
25
  def install(packages, into:)
26
26
  raise NotImplementedError,
27
27
  "#{__method__} must be defined in derived classes"
28
28
  end
29
29
 
30
- sig { returns(T::Array[[Symbol, T.nilable(String)]]) }
30
+ # T::Sig::WithoutRuntime.sig { returns(T::Array[[Symbol, T.nilable(String)]]) }
31
31
  def default_packages
32
32
  raise NotImplementedError,
33
33
  "#{__method__} must be defined in derived classes"
34
34
  end
35
35
 
36
- sig { returns(String) }
36
+ # T::Sig::WithoutRuntime.sig { returns(String) }
37
37
  def shell_exe
38
38
  raise NotImplementedError,
39
39
  "#{__method__} must be defined in derived classes"
@@ -3,13 +3,13 @@
3
3
  module Kuby
4
4
  module Docker
5
5
  class DockerURI
6
- extend T::Sig
6
+ # extend T::Sig
7
7
 
8
- DEFAULT_REGISTRY_HOST = T.let('docker.io'.freeze, String)
9
- DEFAULT_REGISTRY_INDEX_HOST = T.let('index.docker.io'.freeze, String)
10
- DEFAULT_PORT = T.let(443, Integer)
8
+ DEFAULT_REGISTRY_HOST = 'docker.io'.freeze
9
+ DEFAULT_REGISTRY_INDEX_HOST = 'index.docker.io'.freeze
10
+ DEFAULT_PORT = 443
11
11
 
12
- sig { params(url: String).returns(DockerURI) }
12
+ # T::Sig::WithoutRuntime.sig { params(url: String).returns(DockerURI) }
13
13
  def self.parse_uri(url)
14
14
  parse(
15
15
  url,
@@ -18,7 +18,7 @@ module Kuby
18
18
  )
19
19
  end
20
20
 
21
- sig { params(url: String).returns(DockerURI) }
21
+ # T::Sig::WithoutRuntime.sig { params(url: String).returns(DockerURI) }
22
22
  def self.parse_index_uri(url)
23
23
  parse(
24
24
  url,
@@ -27,13 +27,13 @@ module Kuby
27
27
  )
28
28
  end
29
29
 
30
- sig {
31
- params(
32
- url: String,
33
- default_host: T.nilable(String),
34
- default_port: T.nilable(Integer)
35
- ).returns(DockerURI)
36
- }
30
+ # T::Sig::WithoutRuntime.sig {
31
+ # params(
32
+ # url: String,
33
+ # default_host: T.nilable(String),
34
+ # default_port: T.nilable(Integer)
35
+ # ).returns(DockerURI)
36
+ # }
37
37
  def self.parse(url, default_host:, default_port:)
38
38
  if idx = url.index('://')
39
39
  url = url[(idx + 3)..-1] || ''
@@ -41,8 +41,8 @@ module Kuby
41
41
 
42
42
  host_port, *path = url.split('/')
43
43
  host, port, *path = if host_port =~ /[.:]/
44
- hst, prt = T.must(host_port).split(':')
45
- [T.must(hst), prt || default_port, *path]
44
+ hst, prt = host_port.split(':')
45
+ [hst, prt || default_port, *path]
46
46
  else
47
47
  [default_host, default_port, host_port, *path]
48
48
  end
@@ -50,23 +50,23 @@ module Kuby
50
50
  new(host.to_s, port.to_i, (path || []).join('/'))
51
51
  end
52
52
 
53
- sig { returns(String) }
53
+ # T::Sig::WithoutRuntime.sig { returns(String) }
54
54
  attr_reader :host
55
55
 
56
- sig { returns(Integer) }
56
+ # T::Sig::WithoutRuntime.sig { returns(Integer) }
57
57
  attr_reader :port
58
58
 
59
- sig { returns(String) }
59
+ # T::Sig::WithoutRuntime.sig { returns(String) }
60
60
  attr_reader :path
61
61
 
62
- sig { params(host: String, port: Integer, path: String).void }
62
+ # T::Sig::WithoutRuntime.sig { params(host: String, port: Integer, path: String).void }
63
63
  def initialize(host, port, path)
64
64
  @host = host
65
65
  @port = port
66
66
  @path = path
67
67
  end
68
68
 
69
- sig { returns(T::Boolean) }
69
+ # T::Sig::WithoutRuntime.sig { returns(T::Boolean) }
70
70
  def has_default_port?
71
71
  port == DEFAULT_PORT
72
72
  end
@@ -5,39 +5,39 @@ require 'digest'
5
5
  module Kuby
6
6
  module Docker
7
7
  class Dockerfile
8
- extend T::Sig
8
+ # extend T::Sig
9
9
 
10
10
  class Command
11
- extend T::Sig
11
+ # extend T::Sig
12
12
 
13
- sig { returns(T::Array[T.any(String, Integer)]) }
13
+ # T::Sig::WithoutRuntime.sig { returns(T::Array[T.any(String, Integer)]) }
14
14
  attr_reader :args
15
15
 
16
- sig { params(args: T::Array[T.any(String, Integer)]).void }
16
+ # T::Sig::WithoutRuntime.sig { params(args: T::Array[T.any(String, Integer)]).void }
17
17
  def initialize(args)
18
18
  @args = args
19
19
  end
20
20
 
21
- sig { returns(String) }
21
+ # T::Sig::WithoutRuntime.sig { returns(String) }
22
22
  def to_s
23
23
  args.join(' ')
24
24
  end
25
25
  end
26
26
 
27
27
  class From < Command
28
- sig { returns(String) }
28
+ # T::Sig::WithoutRuntime.sig { returns(String) }
29
29
  attr_reader :image_url
30
30
 
31
- sig { returns(T.nilable(String)) }
31
+ # T::Sig::WithoutRuntime.sig { returns(T.nilable(String)) }
32
32
  attr_reader :as
33
33
 
34
- sig { params(image_url: String, as: T.nilable(String)).void }
34
+ # T::Sig::WithoutRuntime.sig { params(image_url: String, as: T.nilable(String)).void }
35
35
  def initialize(image_url, as: nil)
36
36
  @image_url = image_url
37
37
  @as = as
38
38
  end
39
39
 
40
- sig { returns(String) }
40
+ # T::Sig::WithoutRuntime.sig { returns(String) }
41
41
  def to_s
42
42
  str = "FROM #{image_url}"
43
43
  str << " AS #{as}" if as
@@ -46,38 +46,38 @@ module Kuby
46
46
  end
47
47
 
48
48
  class Workdir < Command
49
- sig { returns(String) }
49
+ # T::Sig::WithoutRuntime.sig { returns(String) }
50
50
  def to_s; "WORKDIR #{super}"; end
51
51
  end
52
52
 
53
53
  class Env < Command
54
- sig { returns(String) }
54
+ # T::Sig::WithoutRuntime.sig { returns(String) }
55
55
  def to_s; "ENV #{super}"; end
56
56
  end
57
57
 
58
58
  class Run < Command
59
- sig { returns(String) }
59
+ # T::Sig::WithoutRuntime.sig { returns(String) }
60
60
  def to_s; "RUN #{super}"; end
61
61
  end
62
62
 
63
63
  class Copy < Command
64
- sig { returns(String) }
64
+ # T::Sig::WithoutRuntime.sig { returns(String) }
65
65
  attr_reader :source
66
66
 
67
- sig { returns(String) }
67
+ # T::Sig::WithoutRuntime.sig { returns(String) }
68
68
  attr_reader :dest
69
69
 
70
- sig { returns(T.nilable(String)) }
70
+ # T::Sig::WithoutRuntime.sig { returns(T.nilable(String)) }
71
71
  attr_reader :from
72
72
 
73
- sig { params(source: String, dest: String, from: T.nilable(String)).void }
73
+ # T::Sig::WithoutRuntime.sig { params(source: String, dest: String, from: T.nilable(String)).void }
74
74
  def initialize(source, dest, from: nil)
75
75
  @source = source
76
76
  @dest = dest
77
77
  @from = from
78
78
  end
79
79
 
80
- sig { returns(String) }
80
+ # T::Sig::WithoutRuntime.sig { returns(String) }
81
81
  def to_s
82
82
  cmd = ['COPY']
83
83
  cmd << "--from=#{from}" if from
@@ -87,91 +87,100 @@ module Kuby
87
87
  end
88
88
 
89
89
  class Expose < Command
90
- sig { returns(String) }
90
+ # T::Sig::WithoutRuntime.sig { returns(String) }
91
91
  def to_s; "EXPOSE #{super}"; end
92
92
  end
93
93
 
94
94
  class Cmd < Command
95
- sig { returns(String) }
95
+ # T::Sig::WithoutRuntime.sig { returns(String) }
96
96
  def to_s; "CMD #{super}"; end
97
97
  end
98
98
 
99
99
  class Arg < Command
100
- sig { returns(String) }
100
+ # T::Sig::WithoutRuntime.sig { returns(String) }
101
101
  def to_s; "ARG #{super}"; end
102
102
  end
103
103
 
104
- sig { returns(T::Array[Command]) }
104
+ # T::Sig::WithoutRuntime.sig { returns(T::Array[Command]) }
105
105
  attr_reader :commands
106
106
 
107
- sig { returns(Integer) }
107
+ # T::Sig::WithoutRuntime.sig { returns(Integer) }
108
108
  attr_reader :cursor
109
109
 
110
- sig { void }
110
+ # T::Sig::WithoutRuntime.sig { void }
111
111
  def initialize
112
- @commands = T.let([], T::Array[Command])
113
- @cursor = T.let(0, Integer)
112
+ @commands = []
113
+ @cursor = 0
114
114
  end
115
115
 
116
- sig { params(image_url: String, as: T.nilable(String)).void }
116
+ # T::Sig::WithoutRuntime.sig { params(image_url: String, as: T.nilable(String)).void }
117
117
  def from(image_url, as: nil)
118
118
  add From.new(image_url, as: as)
119
119
  end
120
120
 
121
- sig { params(args: String).void }
121
+ # T::Sig::WithoutRuntime.sig { params(args: String).void }
122
122
  def workdir(*args)
123
123
  add Workdir.new(args)
124
124
  end
125
125
 
126
- sig { params(args: String).void }
126
+ # T::Sig::WithoutRuntime.sig { params(args: String).void }
127
127
  def env(*args)
128
128
  add Env.new(args)
129
129
  end
130
130
 
131
- sig { params(args: String).void }
131
+ # T::Sig::WithoutRuntime.sig { params(args: String).void }
132
132
  def arg(*args)
133
133
  add Arg.new(args)
134
134
  end
135
135
 
136
- sig { params(args: String).void }
136
+ # T::Sig::WithoutRuntime.sig { params(args: String).void }
137
137
  def run(*args)
138
138
  add Run.new(args)
139
139
  end
140
140
 
141
- sig { params(source: String, dest: String, from: T.nilable(String)).void }
141
+ # T::Sig::WithoutRuntime.sig { params(source: String, dest: String, from: T.nilable(String)).void }
142
142
  def copy(source, dest, from: nil)
143
143
  add Copy.new(source, dest, from: from)
144
144
  end
145
145
 
146
- sig { params(port: Integer).void }
146
+ # T::Sig::WithoutRuntime.sig { params(port: Integer).void }
147
147
  def expose(port)
148
148
  add Expose.new([port])
149
149
  end
150
150
 
151
- sig { params(args: String).void }
151
+ # T::Sig::WithoutRuntime.sig { params(args: String).void }
152
152
  def cmd(*args)
153
153
  add Cmd.new(args)
154
154
  end
155
155
 
156
- sig { returns(String) }
156
+ # T::Sig::WithoutRuntime.sig { returns(String) }
157
157
  def to_s
158
158
  # ensure trailing newline
159
159
  "#{commands.map(&:to_s).join("\n")}\n"
160
160
  end
161
161
 
162
- sig { returns(String) }
162
+ # T::Sig::WithoutRuntime.sig { returns(String) }
163
163
  def checksum
164
164
  Digest::SHA256.hexdigest(to_s)
165
165
  end
166
166
 
167
- sig { returns(T::Array[Integer]) }
167
+ # T::Sig::WithoutRuntime.sig { returns(T::Array[Integer]) }
168
168
  def exposed_ports
169
169
  commands
170
170
  .select { |c| c.is_a?(Expose) }
171
- .map { |c| T.cast(c.args.first, Integer) }
171
+ .map { |c| c.args.first }
172
172
  end
173
173
 
174
- sig { params(pos: Integer, block: T.proc.void).void }
174
+ # T::Sig::WithoutRuntime.sig { returns(T.nilable(String)) }
175
+ def current_workdir
176
+ found = commands.reverse_each.find do |command|
177
+ command.is_a?(Kuby::Docker::Dockerfile::Workdir)
178
+ end
179
+
180
+ found.args.first if found
181
+ end
182
+
183
+ # T::Sig::WithoutRuntime.sig { params(pos: Integer, block: T.proc.void).void }
175
184
  def insert_at(pos, &block)
176
185
  @cursor = pos
177
186
  yield
@@ -181,7 +190,7 @@ module Kuby
181
190
 
182
191
  private
183
192
 
184
- sig { params(cmd: Command).void }
193
+ # T::Sig::WithoutRuntime.sig { params(cmd: Command).void }
185
194
  def add(cmd)
186
195
  commands.insert(cursor, cmd)
187
196
  @cursor += 1