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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +58 -0
- data/Gemfile +6 -2
- data/Rakefile +5 -3
- data/bin/tapioca +29 -0
- data/kuby-core.gemspec +9 -11
- data/lib/kuby/basic_logger.rb +34 -34
- data/lib/kuby/cli_base.rb +43 -43
- data/lib/kuby/commands.rb +135 -21
- data/lib/kuby/definition.rb +12 -12
- data/lib/kuby/dependable.rb +20 -0
- data/lib/kuby/dependency.rb +14 -0
- data/lib/kuby/docker/alpine.rb +10 -10
- data/lib/kuby/docker/app_image.rb +11 -20
- data/lib/kuby/docker/app_phase.rb +36 -0
- data/lib/kuby/docker/assets_phase.rb +2 -2
- data/lib/kuby/docker/bundler_phase.rb +42 -40
- data/lib/kuby/docker/cli.rb +72 -37
- data/lib/kuby/docker/copy_phase.rb +7 -7
- data/lib/kuby/docker/credentials.rb +1 -0
- data/lib/kuby/docker/debian.rb +10 -10
- data/lib/kuby/docker/distro.rb +13 -13
- data/lib/kuby/docker/docker_uri.rb +20 -20
- data/lib/kuby/docker/dockerfile.rb +48 -39
- data/lib/kuby/docker/image.rb +66 -54
- data/lib/kuby/docker/inline_layer.rb +4 -4
- data/lib/kuby/docker/layer.rb +6 -6
- data/lib/kuby/docker/layer_stack.rb +35 -35
- data/lib/kuby/docker/local_tags.rb +16 -16
- data/lib/kuby/docker/package_list.rb +16 -16
- data/lib/kuby/docker/package_phase.rb +16 -16
- data/lib/kuby/docker/packages/managed_package.rb +13 -13
- data/lib/kuby/docker/packages/nodejs.rb +5 -5
- data/lib/kuby/docker/packages/package.rb +8 -8
- data/lib/kuby/docker/packages/simple_managed_package.rb +7 -7
- data/lib/kuby/docker/packages/yarn.rb +6 -6
- data/lib/kuby/docker/remote_tags.rb +16 -16
- data/lib/kuby/docker/setup_phase.rb +18 -20
- data/lib/kuby/docker/spec.rb +93 -72
- data/lib/kuby/docker/timestamp_tag.rb +16 -11
- data/lib/kuby/docker/timestamped_image.rb +64 -38
- data/lib/kuby/docker/webserver_phase.rb +20 -20
- data/lib/kuby/docker/yarn_phase.rb +29 -5
- data/lib/kuby/docker.rb +2 -1
- data/lib/kuby/kubernetes/bare_metal_provider.rb +12 -10
- data/lib/kuby/kubernetes/deployer.rb +22 -10
- data/lib/kuby/kubernetes/docker_config.rb +1 -0
- data/lib/kuby/kubernetes/provider.rb +1 -0
- data/lib/kuby/kubernetes/spec.rb +63 -13
- data/lib/kuby/plugin.rb +23 -1
- data/lib/kuby/plugin_registry.rb +15 -0
- data/lib/kuby/plugins/nginx_ingress.rb +8 -6
- data/lib/kuby/plugins/rails_app/assets.rb +16 -4
- data/lib/kuby/plugins/rails_app/assets_image.rb +18 -11
- data/lib/kuby/plugins/rails_app/crdb/plugin.rb +473 -0
- data/lib/kuby/plugins/rails_app/crdb.rb +9 -0
- data/lib/kuby/plugins/rails_app/database.rb +12 -8
- data/lib/kuby/plugins/rails_app/generators/kuby.rb +17 -16
- data/lib/kuby/plugins/rails_app/plugin.rb +37 -27
- data/lib/kuby/plugins/rails_app/sqlite.rb +7 -3
- data/lib/kuby/plugins/rails_app/tasks.rake +25 -12
- data/lib/kuby/plugins/rails_app.rb +1 -0
- data/lib/kuby/plugins/system.rb +16 -0
- data/lib/kuby/plugins.rb +1 -0
- data/lib/kuby/railtie.rb +31 -1
- data/lib/kuby/tasks.rb +91 -10
- data/lib/kuby/trailing_hash.rb +2 -2
- data/lib/kuby/utils/sem_ver/constraint.rb +68 -0
- data/lib/kuby/utils/sem_ver/constraint_set.rb +25 -0
- data/lib/kuby/utils/sem_ver/version.rb +49 -0
- data/lib/kuby/utils/sem_ver.rb +17 -0
- data/lib/kuby/utils/table.rb +35 -0
- data/lib/kuby/utils/which.rb +65 -0
- data/lib/kuby/utils.rb +11 -0
- data/lib/kuby/version.rb +1 -1
- data/lib/kuby.rb +37 -2
- data/rbi/kuby-core.rbi +2128 -0
- data/spec/docker/spec_spec.rb +50 -26
- data/spec/docker/timestamped_image_spec.rb +2 -2
- data/spec/dummy/app/channels/application_cable/channel.rb +2 -1
- data/spec/dummy/app/channels/application_cable/connection.rb +2 -1
- data/spec/dummy/app/controllers/application_controller.rb +2 -1
- data/spec/dummy/app/jobs/application_job.rb +2 -1
- data/spec/dummy/app/mailers/application_mailer.rb +2 -1
- data/spec/dummy/app/models/application_record.rb +2 -1
- data/spec/dummy/config/application.rb +2 -1
- data/spec/dummy/config/initializers/wrap_parameters.rb +2 -1
- data/spec/dummy/config/routes.rb +2 -1
- data/spec/dummy/test/application_system_test_case.rb +2 -1
- data/spec/dummy/test/channels/application_cable/connection_test.rb +2 -1
- data/spec/spec_helper.rb +13 -1
- metadata +46 -39
- data/lib/kuby/plugins/rails_app/mysql.rb +0 -158
- data/lib/kuby/plugins/rails_app/postgres.rb +0 -163
data/lib/kuby/commands.rb
CHANGED
@@ -3,9 +3,12 @@
|
|
3
3
|
require 'kuby/version'
|
4
4
|
require 'gli'
|
5
5
|
|
6
|
+
# run the pre hook for the help command
|
7
|
+
GLI::Commands::Help.skips_pre = false
|
8
|
+
|
6
9
|
module Kuby
|
7
10
|
class Commands
|
8
|
-
extend T::Sig
|
11
|
+
# extend T::Sig
|
9
12
|
extend GLI::App
|
10
13
|
|
11
14
|
# GLI doesn't have a wildcard option, so it's impossible to tell it to
|
@@ -19,12 +22,12 @@ module Kuby
|
|
19
22
|
# avoid the usual series of cryptic alias_method calls (note that there
|
20
23
|
# is no singleton class version of #prepend in the Ruby language).
|
21
24
|
singleton_class.send(:prepend, Module.new do
|
22
|
-
extend T::Sig
|
25
|
+
# extend T::Sig
|
23
26
|
|
24
|
-
sig { params(args: T::Array[String]).void }
|
27
|
+
# T::Sig::WithoutRuntime.sig { params(args: T::Array[String]).void }
|
25
28
|
def run(args)
|
26
29
|
if idx = args.index('rails') || idx = args.index('rake')
|
27
|
-
@rails_options = T.let(@rails_options, T.nilable(T::Array[String]))
|
30
|
+
# @rails_options = T.let(@rails_options, T.nilable(T::Array[String]))
|
28
31
|
@rails_options = args[(idx + 1)..-1]
|
29
32
|
super(args[0..idx])
|
30
33
|
else
|
@@ -34,11 +37,24 @@ module Kuby
|
|
34
37
|
end
|
35
38
|
end)
|
36
39
|
|
37
|
-
sig { returns(Kuby::Tasks) }
|
40
|
+
# T::Sig::WithoutRuntime.sig { returns(Kuby::Tasks) }
|
38
41
|
def self.tasks
|
39
42
|
Kuby::Tasks.new(Kuby.environment)
|
40
43
|
end
|
41
44
|
|
45
|
+
# T::Sig::WithoutRuntime.sig {
|
46
|
+
# params(
|
47
|
+
# global_options: T::Hash[T.any(String, Symbol), T.any(String, Integer)]
|
48
|
+
# ).void
|
49
|
+
# }
|
50
|
+
def self.load_kuby_config!(global_options)
|
51
|
+
return if @kuby_config_loaded
|
52
|
+
|
53
|
+
Kuby.env = global_options[:environment] if global_options[:environment]
|
54
|
+
Kuby.load!(global_options[:config])
|
55
|
+
@kuby_config_loaded = true
|
56
|
+
end
|
57
|
+
|
42
58
|
program_desc 'Kuby command-line interface. Kuby is a convention '\
|
43
59
|
'over configuration approach for running Rails apps in Kubernetes.'
|
44
60
|
|
@@ -54,19 +70,59 @@ module Kuby
|
|
54
70
|
default_value './kuby.rb'
|
55
71
|
flag [:c, :config]
|
56
72
|
|
73
|
+
command_missing do |command_name, global_options|
|
74
|
+
load_kuby_config!(global_options)
|
75
|
+
cmd = nil
|
76
|
+
|
77
|
+
# command_name is also the name of the plugin
|
78
|
+
if plugin_klass = Kuby.plugins.find(command_name)
|
79
|
+
if plugin_klass.respond_to?(:install_commands)
|
80
|
+
desc "Run commands for the #{command_name} plugin."
|
81
|
+
cmd = command(command_name) do |c|
|
82
|
+
# the plugin now defines its own commands on c
|
83
|
+
plugin_klass.install_commands(c)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
cmd
|
89
|
+
end
|
90
|
+
|
57
91
|
pre do |global_options, options, args|
|
58
|
-
|
59
|
-
|
92
|
+
load_kuby_config!(global_options)
|
93
|
+
|
94
|
+
Kuby.plugins.each do |plugin_name, plugin_klass|
|
95
|
+
if plugin_klass.respond_to?(:commands) && !@commands[plugin_name]
|
96
|
+
desc "Run commands for the #{plugin_name} plugin."
|
97
|
+
command plugin_name.to_sym do |c|
|
98
|
+
plugin_klass.commands(c)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
60
102
|
|
61
103
|
# GLI will abort unless this block returns a truthy value
|
62
104
|
true
|
63
105
|
end
|
64
106
|
|
65
|
-
desc 'Builds
|
107
|
+
desc 'Builds Docker images.'
|
66
108
|
command :build do |c|
|
109
|
+
c.desc 'Docker build argument.'
|
67
110
|
c.flag [:a, :arg], required: false, multiple: true
|
68
|
-
|
69
|
-
c.
|
111
|
+
|
112
|
+
c.desc 'When enabled, ignores missing build arguments.'
|
113
|
+
c.switch [:'ignore-missing-args'], required: false, default_value: false
|
114
|
+
|
115
|
+
c.desc 'Build only the images associated with the specified identifier(s). '\
|
116
|
+
'Run `kuby images` for a list of all valid identifiers (note that '\
|
117
|
+
'identifiers can be associated with more than one image).'
|
118
|
+
c.flag [:only], required: false, multiple: true
|
119
|
+
|
120
|
+
c.desc 'The directory to use as the Docker build context.'
|
121
|
+
c.flag [:c, :context], required: false
|
122
|
+
|
123
|
+
c.desc 'Pull the latest images from the registry and reuse any previously built layers.'
|
124
|
+
c.switch [:l, :'cache-from-latest'], required: false, default_value: true
|
125
|
+
|
70
126
|
c.action do |global_options, options, docker_args|
|
71
127
|
build_args = {}.tap do |build_args|
|
72
128
|
(options[:arg] || []).each do |a|
|
@@ -79,14 +135,19 @@ module Kuby
|
|
79
135
|
tasks.build(
|
80
136
|
build_args, docker_args,
|
81
137
|
only: options[:only],
|
82
|
-
ignore_missing_args: options[:'ignore-missing-args']
|
138
|
+
ignore_missing_args: options[:'ignore-missing-args'],
|
139
|
+
context: options[:context],
|
140
|
+
cache_from_latest: options[:'cache-from-latest']
|
83
141
|
)
|
84
142
|
end
|
85
143
|
end
|
86
144
|
|
87
|
-
desc 'Pushes
|
145
|
+
desc 'Pushes Docker images to their associated registries.'
|
88
146
|
command :push do |c|
|
89
|
-
c.
|
147
|
+
c.desc 'Push only the images associated with the specified identifier(s). '\
|
148
|
+
'Run `kuby images` for a list of all valid identifiers (note that '\
|
149
|
+
'identifiers can be associated with more than one image).'
|
150
|
+
c.flag [:only], required: false, multiple: true
|
90
151
|
c.action do |global_options, options, args|
|
91
152
|
tasks.push(only: options[:only])
|
92
153
|
end
|
@@ -94,14 +155,18 @@ module Kuby
|
|
94
155
|
|
95
156
|
desc 'Gets your Kubernetes cluster ready to run your Rails app.'
|
96
157
|
command :setup do |c|
|
158
|
+
c.desc 'Run the setup routines for only the specified plugin identifier(s).'
|
159
|
+
c.flag [:only], required: false, multiple: true
|
97
160
|
c.action do |global_options, options, args|
|
98
|
-
tasks.setup
|
161
|
+
tasks.setup(only: options[:only])
|
99
162
|
end
|
100
163
|
end
|
101
164
|
|
102
165
|
desc 'Prints the effective Dockerfiles used to build Docker images.'
|
103
166
|
command :dockerfiles do |c|
|
104
|
-
c.
|
167
|
+
c.desc 'Print Dockerfiles for only the images associated with the specified '\
|
168
|
+
'identifier(s).'
|
169
|
+
c.flag [:only], required: false, multiple: true
|
105
170
|
c.action do |global_options, options, args|
|
106
171
|
tasks.print_dockerfiles(only: options[:only])
|
107
172
|
end
|
@@ -116,7 +181,7 @@ module Kuby
|
|
116
181
|
end
|
117
182
|
end
|
118
183
|
|
119
|
-
desc 'Rolls back to the previous
|
184
|
+
desc 'Rolls back to the previous release.'
|
120
185
|
command :rollback do |c|
|
121
186
|
c.action do |global_options, options, args|
|
122
187
|
tasks.rollback
|
@@ -125,26 +190,38 @@ module Kuby
|
|
125
190
|
|
126
191
|
desc 'Prints the effective Kubernetes resources that will be applied on deploy.'
|
127
192
|
command :resources do |c|
|
193
|
+
c.desc 'Only print resources of the given kind.'
|
128
194
|
c.flag [:K, :kind], required: false
|
195
|
+
|
196
|
+
c.desc 'Only print resources that match the given name.'
|
129
197
|
c.flag [:N, :name], required: false
|
198
|
+
|
130
199
|
c.action do |global_options, options, args|
|
131
200
|
tasks.print_resources(options[:kind], options[:name])
|
132
201
|
end
|
133
202
|
end
|
134
203
|
|
135
|
-
desc 'Prints out the contents of the kubeconfig Kuby is using to communicate
|
204
|
+
desc 'Prints out the contents of the kubeconfig file Kuby is using to communicate '\
|
205
|
+
'with your cluster.'
|
136
206
|
command :kubeconfig do |c|
|
137
207
|
c.action do |global_options, options, args|
|
138
208
|
tasks.print_kubeconfig
|
139
209
|
end
|
140
210
|
end
|
141
211
|
|
212
|
+
desc 'Prints out the URLs to the latest Docker images in the Docker registry.'
|
213
|
+
command :images do |c|
|
214
|
+
c.action do |global_options, options, args|
|
215
|
+
tasks.print_images
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
142
219
|
desc 'Runs an arbitrary kubectl command.'
|
143
220
|
command :kubectl do |c|
|
144
221
|
c.desc 'Prefixes the kubectl command with the namespace associated with '\
|
145
|
-
|
146
|
-
|
147
|
-
c.switch [:N, :namespaced],
|
222
|
+
'the current environment. For example, if the Kuby env is "production", '\
|
223
|
+
'this option will prefix the kubectl command with "-n myapp-production".'
|
224
|
+
c.switch [:N, :namespaced], default_value: false
|
148
225
|
c.action do |global_options, options, args|
|
149
226
|
if options[:namespaced]
|
150
227
|
# sorry Demeter
|
@@ -156,6 +233,43 @@ module Kuby
|
|
156
233
|
end
|
157
234
|
end
|
158
235
|
|
236
|
+
desc 'Provides information about plugins.'
|
237
|
+
command :plugin do |rc|
|
238
|
+
rc.desc "Run a plugin's remove routine, i.e. uninstall it's resources from your cluster."
|
239
|
+
rc.command :remove do |c|
|
240
|
+
c.desc 'The plugin to remove. Run `kuby plugin list` for a list of valid plugin '\
|
241
|
+
'identifiers.'
|
242
|
+
c.flag [:p, :plugin], required: true
|
243
|
+
c.action do |global_options, options, args|
|
244
|
+
tasks.remove_plugin(options[:plugin])
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
rc.desc 'List plugins.'
|
249
|
+
rc.command :list do |c|
|
250
|
+
c.desc 'Show all available plugins, not just the ones in use.'
|
251
|
+
c.switch [:a, :all], default_value: false
|
252
|
+
c.action do |global_options, options, args|
|
253
|
+
tasks.list_plugins(all: options[:all])
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
rc.desc "Run one of a plugin's rake tasks. Omit task names to print all tasks."
|
258
|
+
rc.arg_name 'task_name', [:multiple, :optional]
|
259
|
+
rc.command :rake do |c|
|
260
|
+
c.action do |global_options, options, args|
|
261
|
+
# Args come through as @rails_options here because of the monkeypatch
|
262
|
+
# at the top of this file. Should revisit the patch at some point because
|
263
|
+
# I think GLI's arg concept can replace it.
|
264
|
+
if @rails_options.empty?
|
265
|
+
tasks.list_rake_tasks
|
266
|
+
else
|
267
|
+
tasks.run_rake_tasks(@rails_options)
|
268
|
+
end
|
269
|
+
end
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
159
273
|
desc 'Runs commands, etc against the Kubernetes cluster.'
|
160
274
|
command :remote do |rc|
|
161
275
|
rc.desc 'Tails (i.e. continuously streams) the Rails log from your running application.'
|
@@ -175,7 +289,7 @@ module Kuby
|
|
175
289
|
rc.desc 'Runs an arbitrary command inside a running Rails pod.'
|
176
290
|
rc.command :exec do |c|
|
177
291
|
c.action do |global_options, options, args|
|
178
|
-
tasks.remote_exec([*args,
|
292
|
+
tasks.remote_exec([*args, *@rails_options])
|
179
293
|
end
|
180
294
|
end
|
181
295
|
|
data/lib/kuby/definition.rb
CHANGED
@@ -2,23 +2,23 @@
|
|
2
2
|
|
3
3
|
module Kuby
|
4
4
|
class Definition
|
5
|
-
extend T::Sig
|
5
|
+
# extend T::Sig
|
6
6
|
|
7
|
-
sig { returns(String) }
|
7
|
+
# T::Sig::WithoutRuntime.sig { returns(String) }
|
8
8
|
attr_reader :app_name
|
9
9
|
|
10
|
-
sig { params(app_name: String, block: T.nilable(T.proc.void)).void }
|
10
|
+
# T::Sig::WithoutRuntime.sig { params(app_name: String, block: T.nilable(T.proc.void)).void }
|
11
11
|
def initialize(app_name, &block)
|
12
12
|
@app_name = app_name
|
13
|
-
@environments = T.let(@environments, T.nilable(T::Hash[Symbol, Environment]))
|
13
|
+
# @environments = T.let(@environments, T.nilable(T::Hash[Symbol, Environment]))
|
14
14
|
end
|
15
15
|
|
16
|
-
sig {
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
}
|
16
|
+
# T::Sig::WithoutRuntime.sig {
|
17
|
+
# params(
|
18
|
+
# name: Symbol,
|
19
|
+
# block: T.nilable(T.proc.void)
|
20
|
+
# ).returns(Kuby::Environment)
|
21
|
+
# }
|
22
22
|
def environment(name = Kuby.env, &block)
|
23
23
|
name = name.to_s
|
24
24
|
|
@@ -28,10 +28,10 @@ module Kuby
|
|
28
28
|
environments[name].instance_eval(&block)
|
29
29
|
end
|
30
30
|
|
31
|
-
|
31
|
+
environments[name]
|
32
32
|
end
|
33
33
|
|
34
|
-
sig { returns(T::Hash[Symbol, Environment]) }
|
34
|
+
# T::Sig::WithoutRuntime.sig { returns(T::Hash[Symbol, Kuby::Environment]) }
|
35
35
|
def environments
|
36
36
|
@environments ||= {}
|
37
37
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Kuby
|
2
|
+
class Dependable
|
3
|
+
attr_reader :name, :version_or_callable
|
4
|
+
|
5
|
+
def initialize(name, version_or_callable)
|
6
|
+
@name = name
|
7
|
+
@version_or_callable = version_or_callable
|
8
|
+
end
|
9
|
+
|
10
|
+
def version
|
11
|
+
@version ||= Kuby::Utils::SemVer.parse_version(
|
12
|
+
if version_or_callable.respond_to?(:call)
|
13
|
+
version_or_callable.call
|
14
|
+
else
|
15
|
+
version_or_callable
|
16
|
+
end
|
17
|
+
)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Kuby
|
2
|
+
class Dependency
|
3
|
+
attr_reader :name, :constraints
|
4
|
+
|
5
|
+
def initialize(name, *constraints)
|
6
|
+
@name = name
|
7
|
+
@constraints = Kuby::Utils::SemVer.parse_constraints(*constraints)
|
8
|
+
end
|
9
|
+
|
10
|
+
def satisfied_by?(dependable)
|
11
|
+
constraints.satisfied_by?(dependable.version)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/lib/kuby/docker/alpine.rb
CHANGED
@@ -3,42 +3,42 @@
|
|
3
3
|
module Kuby
|
4
4
|
module Docker
|
5
5
|
class Alpine < Distro
|
6
|
-
SHELL_EXE =
|
6
|
+
SHELL_EXE = '/bin/sh'.freeze
|
7
7
|
|
8
|
-
DEFAULT_PACKAGES =
|
8
|
+
DEFAULT_PACKAGES = [
|
9
9
|
[:ca_certificates, nil],
|
10
10
|
[:nodejs, '12.14.1'],
|
11
11
|
[:yarn, '1.21.1'],
|
12
12
|
[:c_toolchain, nil],
|
13
13
|
[:tzdata, nil],
|
14
14
|
[:git, nil]
|
15
|
-
].freeze
|
15
|
+
].freeze
|
16
16
|
|
17
|
-
sig { returns(Layer) }
|
17
|
+
# T::Sig::WithoutRuntime.sig { returns(Layer) }
|
18
18
|
attr_reader :phase
|
19
19
|
|
20
|
-
sig { override.params(packages: T::Array[Distro::PackageImpl], into: Dockerfile).void }
|
20
|
+
# T::Sig::WithoutRuntime.sig { override.params(packages: T::Array[Distro::PackageImpl], into: Dockerfile).void }
|
21
21
|
def install(packages, into:)
|
22
22
|
dockerfile = into
|
23
23
|
install_managed(packages, dockerfile)
|
24
24
|
install_unmanaged(packages, dockerfile)
|
25
25
|
end
|
26
26
|
|
27
|
-
sig { override.returns(T::Array[[Symbol, T.nilable(String)]]) }
|
27
|
+
# T::Sig::WithoutRuntime.sig { override.returns(T::Array[[Symbol, T.nilable(String)]]) }
|
28
28
|
def default_packages
|
29
29
|
DEFAULT_PACKAGES
|
30
30
|
end
|
31
31
|
|
32
|
-
sig { override.returns(String) }
|
32
|
+
# T::Sig::WithoutRuntime.sig { override.returns(String) }
|
33
33
|
def shell_exe
|
34
34
|
SHELL_EXE
|
35
35
|
end
|
36
36
|
|
37
37
|
private
|
38
38
|
|
39
|
-
sig { params(packages: T::Array[Distro::PackageImpl], dockerfile: Dockerfile).void }
|
39
|
+
# T::Sig::WithoutRuntime.sig { params(packages: T::Array[Distro::PackageImpl], dockerfile: Dockerfile).void }
|
40
40
|
def install_managed(packages, dockerfile)
|
41
|
-
pkgs =
|
41
|
+
pkgs = packages.select(&:managed?)
|
42
42
|
|
43
43
|
unless pkgs.empty?
|
44
44
|
package_names = pkgs.map { |pkg| pkg.package_name_for(:alpine) }
|
@@ -48,7 +48,7 @@ module Kuby
|
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
51
|
-
sig { params(packages: T::Array[Distro::PackageImpl], dockerfile: Dockerfile).void }
|
51
|
+
# T::Sig::WithoutRuntime.sig { params(packages: T::Array[Distro::PackageImpl], dockerfile: Dockerfile).void }
|
52
52
|
def install_unmanaged(packages, dockerfile)
|
53
53
|
packages
|
54
54
|
.reject(&:managed?)
|
@@ -4,31 +4,22 @@
|
|
4
4
|
module Kuby
|
5
5
|
module Docker
|
6
6
|
class AppImage < ::Kuby::Docker::TimestampedImage
|
7
|
-
extend T::Sig
|
7
|
+
# extend T::Sig
|
8
8
|
|
9
|
-
sig {
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
}
|
9
|
+
# T::Sig::WithoutRuntime.sig {
|
10
|
+
# params(
|
11
|
+
# dockerfile: T.any(Dockerfile, T.proc.returns(Dockerfile)),
|
12
|
+
# image_url: String,
|
13
|
+
# credentials: Credentials,
|
14
|
+
# registry_index_url: T.nilable(String),
|
15
|
+
# main_tag: T.nilable(String),
|
16
|
+
# alias_tags: T::Array[String]
|
17
|
+
# ).void
|
18
|
+
# }
|
19
19
|
def initialize(dockerfile, image_url, credentials, registry_index_url = nil, main_tag = nil, alias_tags = [])
|
20
20
|
super
|
21
21
|
@identifier = "app"
|
22
22
|
end
|
23
|
-
|
24
|
-
sig { params(build_args: T::Hash[String, String], docker_args: T::Array[String]).returns(AppImage) }
|
25
|
-
def build(build_args = {}, docker_args = [])
|
26
|
-
unless ENV.fetch('RAILS_MASTER_KEY', '').empty?
|
27
|
-
build_args['RAILS_MASTER_KEY'] = T.must(ENV['RAILS_MASTER_KEY'])
|
28
|
-
end
|
29
|
-
|
30
|
-
super(build_args, docker_args)
|
31
|
-
end
|
32
23
|
end
|
33
24
|
end
|
34
25
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# typed: strict
|
2
|
+
|
3
|
+
module Kuby
|
4
|
+
module Docker
|
5
|
+
class AppPhase < Layer
|
6
|
+
# extend T::Sig
|
7
|
+
|
8
|
+
# T::Sig::WithoutRuntime.sig { params(environment: Environment).void }
|
9
|
+
def initialize(environment)
|
10
|
+
super
|
11
|
+
|
12
|
+
@env_vars = {}
|
13
|
+
end
|
14
|
+
|
15
|
+
# T::Sig::WithoutRuntime.sig { override.params(dockerfile: Dockerfile).void }
|
16
|
+
def apply_to(dockerfile)
|
17
|
+
@env_vars.each_pair do |key, value|
|
18
|
+
dockerfile.env("#{key}='#{value}'")
|
19
|
+
end
|
20
|
+
|
21
|
+
absolute_app_root = Pathname(dockerfile.current_workdir)
|
22
|
+
.join(environment.docker.app_root_path)
|
23
|
+
.to_s
|
24
|
+
|
25
|
+
if dockerfile.current_workdir != absolute_app_root
|
26
|
+
dockerfile.workdir(absolute_app_root)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# T::Sig::WithoutRuntime.sig { params(key: String, value: String).void }
|
31
|
+
def env(key, value)
|
32
|
+
@env_vars[key] = value
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -3,9 +3,9 @@
|
|
3
3
|
module Kuby
|
4
4
|
module Docker
|
5
5
|
class AssetsPhase < Layer
|
6
|
-
extend T::Sig
|
6
|
+
# extend T::Sig
|
7
7
|
|
8
|
-
sig { override.params(dockerfile: Dockerfile).void }
|
8
|
+
# T::Sig::WithoutRuntime.sig { override.params(dockerfile: Dockerfile).void }
|
9
9
|
def apply_to(dockerfile)
|
10
10
|
dockerfile.run(
|
11
11
|
'bundle', 'exec', 'rake', 'assets:precompile'
|
@@ -5,101 +5,103 @@ require 'pathname'
|
|
5
5
|
module Kuby
|
6
6
|
module Docker
|
7
7
|
class BundlerPhase < Layer
|
8
|
-
extend T::Sig
|
8
|
+
# extend T::Sig
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
10
|
+
DEFAULT_GEMFILE = 'Gemfile'.freeze
|
11
|
+
DEFAULT_WITHOUT =
|
12
|
+
['development', 'test', 'deploy'].freeze
|
13
|
+
|
13
14
|
|
14
|
-
sig { returns(T.nilable(String)) }
|
15
|
+
# T::Sig::WithoutRuntime.sig { returns(T.nilable(String)) }
|
15
16
|
attr_reader :version
|
16
17
|
|
17
|
-
sig { params(version: String).
|
18
|
+
# T::Sig::WithoutRuntime.sig { params(version: String).returns(String) }
|
18
19
|
attr_writer :version
|
19
20
|
|
20
|
-
sig { returns(T.nilable(String)) }
|
21
|
+
# T::Sig::WithoutRuntime.sig { returns(T.nilable(String)) }
|
21
22
|
attr_reader :gemfile
|
22
23
|
|
23
|
-
sig { params(gemfile: String).
|
24
|
+
# T::Sig::WithoutRuntime.sig { params(gemfile: String).returns(String) }
|
24
25
|
attr_writer :gemfile
|
25
26
|
|
26
|
-
sig { returns(T.nilable(T::Array[String])) }
|
27
|
+
# T::Sig::WithoutRuntime.sig { returns(T.nilable(T::Array[String])) }
|
27
28
|
attr_reader :without
|
28
29
|
|
29
|
-
sig { params(without: T::Array[String]).
|
30
|
+
# T::Sig::WithoutRuntime.sig { params(without: T::Array[String]).returns(T::Array[String]) }
|
30
31
|
attr_writer :without
|
31
32
|
|
32
|
-
sig { returns(T.nilable(String)) }
|
33
|
+
# T::Sig::WithoutRuntime.sig { returns(T.nilable(String)) }
|
33
34
|
attr_reader :executable
|
34
35
|
|
35
|
-
sig { params(executable: String).
|
36
|
+
# T::Sig::WithoutRuntime.sig { params(executable: String).returns(String) }
|
36
37
|
attr_writer :executable
|
37
38
|
|
38
|
-
sig { params(environment: Environment).void }
|
39
|
+
# T::Sig::WithoutRuntime.sig { params(environment: Environment).void }
|
39
40
|
def initialize(environment)
|
40
41
|
super
|
41
42
|
|
42
|
-
@version = T.let(@version, T.nilable(String))
|
43
|
-
@gemfile = T.let(@gemfile, T.nilable(String))
|
44
|
-
@gemfiles =
|
45
|
-
@without = T.let(@without, T.nilable(T::Array[String]))
|
46
|
-
@executable = T.let(@executable, T.nilable(String))
|
43
|
+
# @version = T.let(@version, T.nilable(String))
|
44
|
+
# @gemfile = T.let(@gemfile, T.nilable(String))
|
45
|
+
@gemfiles = []
|
46
|
+
# @without = T.let(@without, T.nilable(T::Array[String]))
|
47
|
+
# @executable = T.let(@executable, T.nilable(String))
|
47
48
|
end
|
48
49
|
|
49
|
-
sig { override.params(dockerfile: Dockerfile).void }
|
50
|
+
# T::Sig::WithoutRuntime.sig { override.params(dockerfile: Dockerfile).void }
|
50
51
|
def apply_to(dockerfile)
|
51
|
-
gf = gemfile ||
|
52
|
+
gf = gemfile || DEFAULT_GEMFILE
|
52
53
|
lf = "#{gf}.lock"
|
53
54
|
v = version || default_version
|
54
55
|
wo = without || DEFAULT_WITHOUT
|
55
56
|
|
56
|
-
|
57
|
+
host_path = Pathname(environment.docker.app_root_path)
|
58
|
+
container_path = Pathname(dockerfile.current_workdir).join(environment.docker.app_root_path)
|
57
59
|
|
58
|
-
|
59
|
-
dockerfile.copy(gf, '.')
|
60
|
-
dockerfile.copy(lf, '.')
|
60
|
+
dockerfile.run('gem', 'install', 'bundler', '-v', v)
|
61
61
|
|
62
|
+
dockerfile.copy(host_path.join(gf), container_path.join(gf))
|
63
|
+
dockerfile.copy(host_path.join(lf), container_path.join(lf))
|
62
64
|
@gemfiles.each do |file|
|
63
|
-
dockerfile.copy(file, file)
|
65
|
+
dockerfile.copy(host_path.join(file), container_path.join(file))
|
66
|
+
extra_lf = host_path.join("#{file}.lock")
|
67
|
+
|
68
|
+
if extra_lf.exist?
|
69
|
+
dockerfile.copy(extra_lf, container_path.join("#{file}.lock"))
|
70
|
+
end
|
64
71
|
end
|
65
72
|
|
73
|
+
dockerfile.env("BUNDLE_GEMFILE=#{container_path.join(gf)}")
|
74
|
+
|
66
75
|
unless wo.empty?
|
67
76
|
dockerfile.env("BUNDLE_WITHOUT='#{wo.join(' ')}'")
|
68
77
|
end
|
69
78
|
|
79
|
+
dockerfile.run(
|
80
|
+
executable || 'bundle', 'lock', '--lockfile', container_path.join(lf)
|
81
|
+
)
|
82
|
+
|
70
83
|
dockerfile.run(
|
71
84
|
executable || 'bundle', 'install',
|
72
85
|
'--jobs', '$(nproc)',
|
73
|
-
'--retry', '3'
|
74
|
-
'--gemfile', gf
|
86
|
+
'--retry', '3'
|
75
87
|
)
|
76
88
|
|
77
89
|
# generate binstubs and add the bin directory to our path
|
78
90
|
dockerfile.run(executable || 'bundle', 'binstubs', '--all')
|
79
|
-
dockerfile.env("PATH
|
91
|
+
dockerfile.env("PATH=#{container_path.join('bin')}:$PATH")
|
80
92
|
end
|
81
93
|
|
82
|
-
sig { params(paths: String).void }
|
94
|
+
# T::Sig::WithoutRuntime.sig { params(paths: String).void }
|
83
95
|
def gemfiles(*paths)
|
84
96
|
@gemfiles.concat(paths)
|
85
97
|
end
|
86
98
|
|
87
99
|
private
|
88
100
|
|
89
|
-
sig { returns(String) }
|
101
|
+
# T::Sig::WithoutRuntime.sig { returns(String) }
|
90
102
|
def default_version
|
91
103
|
Bundler::VERSION
|
92
104
|
end
|
93
|
-
|
94
|
-
sig { returns(String) }
|
95
|
-
def default_gemfile
|
96
|
-
Bundler
|
97
|
-
.definition
|
98
|
-
.gemfiles
|
99
|
-
.first
|
100
|
-
.relative_path_from(Pathname(Dir.getwd))
|
101
|
-
.to_s
|
102
|
-
end
|
103
105
|
end
|
104
106
|
end
|
105
107
|
end
|