kuby-core 0.14.0 → 0.15.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 +9 -0
- data/lib/kuby/commands.rb +2 -2
- data/lib/kuby/docker/app_image.rb +2 -1
- data/lib/kuby/docker/docker_uri.rb +35 -5
- data/lib/kuby/docker/image.rb +26 -3
- data/lib/kuby/docker/spec.rb +10 -1
- data/lib/kuby/docker/timestamped_image.rb +4 -3
- data/lib/kuby/plugins/rails_app/assets.rb +2 -1
- data/lib/kuby/plugins/rails_app/assets_image.rb +3 -2
- data/lib/kuby/plugins/rails_app/generators/kuby.rb +31 -9
- data/lib/kuby/tasks.rb +70 -15
- data/lib/kuby/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0a5f265cee423b7487de7e4c209b26cc9fef63cf584455bc4164ecd7e6384377
|
4
|
+
data.tar.gz: e48304bf9397b30ceed7025039d074e55423ced190f734a416a311e412bd609d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d4cbd6c2fbf6de8f621d4b2412bb4c1921eff7e5ba3c90b5afefac3c0d216aff676772b0582dab70a688c3c1dc7ce55a48f9c42f3b178ad25f31d489a3f33421
|
7
|
+
data.tar.gz: b9b3f808ed6184c73edb8652a958cd53b12337c8a48bf2f19d188b07c1c4d56283f7bfbfffd2a9338dc522a2376f8665e9c792571b4fdb609bf14b0181efcc16
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
## 0.15.0
|
2
|
+
* Add an extra parameter to the Docker spec for specifying the URL of the Docker registry index.
|
3
|
+
- In most cases, the registry and registry index URLs will be the same. However Docker Hub, the default registry, uses index.docker.io for API requests (catalog, tags, etc) but only allows pushes to docker.io.
|
4
|
+
* Add config/master.key to the .dockerignore created by the Rails generator.
|
5
|
+
- This was an unfortunate oversight, but such are the perils of using pre-1.0 software.
|
6
|
+
* Print an error message if building images on non-x86 hardware.
|
7
|
+
- People with M1 Macs are running into mismatches between their laptop's arch and the arch of their hosting provider's hardware. The error message asks you to explicitly pass the `--platform` flag to Docker.
|
8
|
+
- We may need to revisit this in the future if ARM processors become more popular.
|
9
|
+
|
1
10
|
## 0.14.0
|
2
11
|
* Make RAILS_MASTER_KEY available in the assets image (@palkan, #63)
|
3
12
|
* Allow specifying custom docker build options via CLI (@palkan, #65)
|
data/lib/kuby/commands.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: false
|
2
2
|
|
3
3
|
require 'kuby/version'
|
4
4
|
require 'gli'
|
@@ -170,7 +170,7 @@ module Kuby
|
|
170
170
|
rc.desc 'Runs an arbitrary command inside a running Rails pod.'
|
171
171
|
rc.command :exec do |c|
|
172
172
|
c.action do |global_options, options, args|
|
173
|
-
tasks.remote_exec([*args,
|
173
|
+
tasks.remote_exec([*args, *T.unsafe(@rails_options)])
|
174
174
|
end
|
175
175
|
end
|
176
176
|
|
@@ -11,11 +11,12 @@ module Kuby
|
|
11
11
|
dockerfile: T.any(Dockerfile, T.proc.returns(Dockerfile)),
|
12
12
|
image_url: String,
|
13
13
|
credentials: Credentials,
|
14
|
+
registry_index_url: T.nilable(String),
|
14
15
|
main_tag: T.nilable(String),
|
15
16
|
alias_tags: T::Array[String]
|
16
17
|
).void
|
17
18
|
}
|
18
|
-
def initialize(dockerfile, image_url, credentials, main_tag = nil, alias_tags = [])
|
19
|
+
def initialize(dockerfile, image_url, credentials, registry_index_url = nil, main_tag = nil, alias_tags = [])
|
19
20
|
super
|
20
21
|
@identifier = "app"
|
21
22
|
end
|
@@ -5,11 +5,36 @@ module Kuby
|
|
5
5
|
class DockerURI
|
6
6
|
extend T::Sig
|
7
7
|
|
8
|
-
DEFAULT_REGISTRY_HOST = T.let('
|
9
|
-
|
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)
|
10
11
|
|
11
12
|
sig { params(url: String).returns(DockerURI) }
|
12
|
-
def self.
|
13
|
+
def self.parse_uri(url)
|
14
|
+
parse(
|
15
|
+
url,
|
16
|
+
default_host: DEFAULT_REGISTRY_HOST,
|
17
|
+
default_port: DEFAULT_PORT
|
18
|
+
)
|
19
|
+
end
|
20
|
+
|
21
|
+
sig { params(url: String).returns(DockerURI) }
|
22
|
+
def self.parse_index_uri(url)
|
23
|
+
parse(
|
24
|
+
url,
|
25
|
+
default_host: DEFAULT_REGISTRY_INDEX_HOST,
|
26
|
+
default_port: DEFAULT_PORT
|
27
|
+
)
|
28
|
+
end
|
29
|
+
|
30
|
+
sig {
|
31
|
+
params(
|
32
|
+
url: String,
|
33
|
+
default_host: T.nilable(String),
|
34
|
+
default_port: T.nilable(Integer)
|
35
|
+
).returns(DockerURI)
|
36
|
+
}
|
37
|
+
def self.parse(url, default_host:, default_port:)
|
13
38
|
if idx = url.index('://')
|
14
39
|
url = url[(idx + 3)..-1] || ''
|
15
40
|
end
|
@@ -17,9 +42,9 @@ module Kuby
|
|
17
42
|
host_port, *path = url.split('/')
|
18
43
|
host, port, *path = if host_port =~ /[.:]/
|
19
44
|
hst, prt = T.must(host_port).split(':')
|
20
|
-
[T.must(hst), prt ||
|
45
|
+
[T.must(hst), prt || default_port, *path]
|
21
46
|
else
|
22
|
-
[
|
47
|
+
[default_host, default_port, host_port, *path]
|
23
48
|
end
|
24
49
|
|
25
50
|
new(host.to_s, port.to_i, (path || []).join('/'))
|
@@ -40,6 +65,11 @@ module Kuby
|
|
40
65
|
@port = port
|
41
66
|
@path = path
|
42
67
|
end
|
68
|
+
|
69
|
+
sig { returns(T::Boolean) }
|
70
|
+
def has_default_port?
|
71
|
+
port == DEFAULT_PORT
|
72
|
+
end
|
43
73
|
end
|
44
74
|
end
|
45
75
|
end
|
data/lib/kuby/docker/image.rb
CHANGED
@@ -11,6 +11,9 @@ module Kuby
|
|
11
11
|
sig { returns(String) }
|
12
12
|
attr_reader :image_url
|
13
13
|
|
14
|
+
sig { returns(T.nilable(String)) }
|
15
|
+
attr_reader :registry_index_url
|
16
|
+
|
14
17
|
sig { returns(Credentials) }
|
15
18
|
attr_reader :credentials
|
16
19
|
|
@@ -25,13 +28,15 @@ module Kuby
|
|
25
28
|
dockerfile: T.any(Dockerfile, T.proc.returns(Dockerfile)),
|
26
29
|
image_url: String,
|
27
30
|
credentials: Credentials,
|
31
|
+
registry_index_url: T.nilable(String),
|
28
32
|
main_tag: T.nilable(String),
|
29
33
|
alias_tags: T::Array[String]
|
30
34
|
).void
|
31
35
|
}
|
32
|
-
def initialize(dockerfile, image_url, credentials, main_tag = nil, alias_tags = [])
|
36
|
+
def initialize(dockerfile, image_url, credentials, registry_index_url = nil, main_tag = nil, alias_tags = [])
|
33
37
|
@dockerfile = T.let(dockerfile, T.any(Dockerfile, T.proc.returns(Dockerfile)))
|
34
38
|
@image_url = T.let(image_url, String)
|
39
|
+
@registry_index_url = T.let(registry_index_url, T.nilable(String))
|
35
40
|
@credentials = T.let(credentials, Credentials)
|
36
41
|
@main_tag = T.let(main_tag, T.nilable(String))
|
37
42
|
@alias_tags = T.let(alias_tags, T::Array[String])
|
@@ -39,6 +44,9 @@ module Kuby
|
|
39
44
|
|
40
45
|
@image_host = T.let(@image_host, T.nilable(String))
|
41
46
|
@image_hostname = T.let(@image_hostname, T.nilable(String))
|
47
|
+
@registry_index_host = T.let(@registry_index_host, T.nilable(String))
|
48
|
+
@registry_index_hostname = T.let(@registry_index_hostname, T.nilable(String))
|
49
|
+
@registry_index_uri = T.let(@registry_index_uri, T.nilable(DockerURI))
|
42
50
|
@image_repo = T.let(@image_repo, T.nilable(String))
|
43
51
|
@full_image_uri = T.let(@full_image_uri, T.nilable(DockerURI))
|
44
52
|
@docker_cli = T.let(@docker_cli, T.nilable(Docker::CLI))
|
@@ -73,6 +81,16 @@ module Kuby
|
|
73
81
|
@image_host ||= "#{image_uri.host}:#{image_uri.port}"
|
74
82
|
end
|
75
83
|
|
84
|
+
sig { returns(String) }
|
85
|
+
def registry_index_host
|
86
|
+
@registry_index_host ||= "#{registry_index_uri.host}:#{registry_index_uri.port}"
|
87
|
+
end
|
88
|
+
|
89
|
+
sig { returns(String) }
|
90
|
+
def registry_index_hostname
|
91
|
+
@registry_index_hostname ||= registry_index_uri.host
|
92
|
+
end
|
93
|
+
|
76
94
|
sig { returns(String) }
|
77
95
|
def image_hostname
|
78
96
|
@image_hostname ||= image_uri.host
|
@@ -85,7 +103,12 @@ module Kuby
|
|
85
103
|
|
86
104
|
sig { returns(DockerURI) }
|
87
105
|
def image_uri
|
88
|
-
@full_image_uri ||= DockerURI.
|
106
|
+
@full_image_uri ||= DockerURI.parse_uri(image_url)
|
107
|
+
end
|
108
|
+
|
109
|
+
sig { returns(DockerURI) }
|
110
|
+
def registry_index_uri
|
111
|
+
@registry_index_uri ||= DockerURI.parse_index_uri(registry_index_url || image_url)
|
89
112
|
end
|
90
113
|
|
91
114
|
sig { returns(T::Array[String]) }
|
@@ -112,7 +135,7 @@ module Kuby
|
|
112
135
|
|
113
136
|
sig { params(main_tag: String, alias_tags: T::Array[String]).returns(Image) }
|
114
137
|
def duplicate_with_tags(main_tag, alias_tags)
|
115
|
-
self.class.new(dockerfile, image_url, credentials, main_tag, alias_tags)
|
138
|
+
self.class.new(dockerfile, image_url, credentials, registry_index_url, main_tag, alias_tags)
|
116
139
|
end
|
117
140
|
end
|
118
141
|
end
|
data/lib/kuby/docker/spec.rb
CHANGED
@@ -13,6 +13,9 @@ module Kuby
|
|
13
13
|
sig { returns(T.nilable(String)) }
|
14
14
|
attr_reader :image_url_str
|
15
15
|
|
16
|
+
sig { returns(T.nilable(String)) }
|
17
|
+
attr_reader :registry_index_url_str
|
18
|
+
|
16
19
|
sig { params(environment: Environment).void }
|
17
20
|
def initialize(environment)
|
18
21
|
@environment = environment
|
@@ -31,6 +34,7 @@ module Kuby
|
|
31
34
|
@layer_stack = T.let(@layer_stack, T.nilable(Kuby::Docker::LayerStack))
|
32
35
|
|
33
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))
|
34
38
|
@image = T.let(@image, T.nilable(Docker::AppImage))
|
35
39
|
end
|
36
40
|
|
@@ -96,6 +100,11 @@ module Kuby
|
|
96
100
|
@image_url_str = url
|
97
101
|
end
|
98
102
|
|
103
|
+
sig { params(url: String).void }
|
104
|
+
def registry_index_url(url)
|
105
|
+
@registry_index_url_str = url
|
106
|
+
end
|
107
|
+
|
99
108
|
sig {
|
100
109
|
params(
|
101
110
|
name: Symbol,
|
@@ -148,7 +157,7 @@ module Kuby
|
|
148
157
|
end
|
149
158
|
|
150
159
|
Docker::AppImage.new(
|
151
|
-
dockerfile, T.must(image_url_str), credentials
|
160
|
+
dockerfile, T.must(image_url_str), credentials, registry_index_url_str
|
152
161
|
)
|
153
162
|
end
|
154
163
|
end
|
@@ -12,11 +12,12 @@ module Kuby
|
|
12
12
|
dockerfile: T.any(Dockerfile, T.proc.returns(Dockerfile)),
|
13
13
|
image_url: String,
|
14
14
|
credentials: Credentials,
|
15
|
+
registry_index_url_str: T.nilable(String),
|
15
16
|
main_tag: T.nilable(String),
|
16
17
|
alias_tags: T::Array[String]
|
17
18
|
).void
|
18
19
|
}
|
19
|
-
def initialize(dockerfile, image_url, credentials, main_tag = nil, alias_tags = [])
|
20
|
+
def initialize(dockerfile, image_url, credentials, registry_index_url_str = nil, main_tag = nil, alias_tags = [])
|
20
21
|
@new_version = T.let(@new_version, T.nilable(Image))
|
21
22
|
@current_version = T.let(@current_version, T.nilable(Image))
|
22
23
|
@previous_version = T.let(@previous_version, T.nilable(Image))
|
@@ -90,7 +91,7 @@ module Kuby
|
|
90
91
|
sig { returns(::Docker::Remote::Client) }
|
91
92
|
def remote_client
|
92
93
|
@remote_client ||= ::Docker::Remote::Client.new(
|
93
|
-
|
94
|
+
registry_index_host, image_repo, credentials.username, credentials.password,
|
94
95
|
)
|
95
96
|
end
|
96
97
|
|
@@ -106,7 +107,7 @@ module Kuby
|
|
106
107
|
|
107
108
|
sig { returns(RemoteTags) }
|
108
109
|
def remote
|
109
|
-
@remote ||= RemoteTags.new(remote_client,
|
110
|
+
@remote ||= RemoteTags.new(remote_client, registry_index_host)
|
110
111
|
end
|
111
112
|
end
|
112
113
|
end
|
@@ -296,7 +296,7 @@ module Kuby
|
|
296
296
|
end
|
297
297
|
|
298
298
|
def image
|
299
|
-
@image ||= RailsApp::AssetsImage.new(docker.image, -> { dockerfile })
|
299
|
+
@image ||= RailsApp::AssetsImage.new(docker.image, -> { dockerfile }, docker.image.registry_index_url)
|
300
300
|
end
|
301
301
|
|
302
302
|
private
|
@@ -324,6 +324,7 @@ module Kuby
|
|
324
324
|
if tag
|
325
325
|
image_name = "#{app_name}-#{tag}"
|
326
326
|
df.from("#{base_image.image_url}:#{tag}", as: image_name)
|
327
|
+
df.arg('RAILS_MASTER_KEY')
|
327
328
|
df.copy("--from=#{prev_image_name} #{RAILS_MOUNT_PATH}", RAILS_MOUNT_PATH)
|
328
329
|
df.run("env RAILS_MASTER_KEY=$RAILS_MASTER_KEY bundle exec rake kuby:rails_app:assets:copy")
|
329
330
|
end
|
@@ -4,8 +4,8 @@ module Kuby
|
|
4
4
|
class AssetsImage < ::Kuby::Docker::Image
|
5
5
|
attr_reader :base_image
|
6
6
|
|
7
|
-
def initialize(base_image, dockerfile, main_tag = nil, alias_tags = [])
|
8
|
-
super(dockerfile, base_image.image_url, base_image.credentials, main_tag, alias_tags)
|
7
|
+
def initialize(base_image, dockerfile, registry_index_url = nil, main_tag = nil, alias_tags = [])
|
8
|
+
super(dockerfile, base_image.image_url, base_image.credentials, registry_index_url, main_tag, alias_tags)
|
9
9
|
@base_image = base_image
|
10
10
|
@identifier = "assets"
|
11
11
|
end
|
@@ -42,6 +42,7 @@ module Kuby
|
|
42
42
|
self.class.new(
|
43
43
|
base_image,
|
44
44
|
dockerfile,
|
45
|
+
registry_index_url,
|
45
46
|
annotate_tag(image.main_tag),
|
46
47
|
image.alias_tags.map { |at| annotate_tag(at) }
|
47
48
|
)
|
@@ -86,16 +86,38 @@ class KubyGenerator < Rails::Generators::Base
|
|
86
86
|
create_file(
|
87
87
|
'.dockerignore',
|
88
88
|
<<~END
|
89
|
-
.
|
90
|
-
|
91
|
-
|
92
|
-
.
|
93
|
-
|
94
|
-
|
95
|
-
log
|
96
|
-
|
97
|
-
|
89
|
+
.git/
|
90
|
+
|
91
|
+
# Ignore bundler config.
|
92
|
+
.bundle
|
93
|
+
|
94
|
+
# Ignore all logfiles and tempfiles.
|
95
|
+
log/*
|
96
|
+
tmp/*
|
97
|
+
!log/.keep
|
98
|
+
!tmp/.keep
|
99
|
+
|
100
|
+
# Ignore pidfiles, but keep the directory.
|
101
|
+
tmp/pids/*
|
102
|
+
!tmp/pids/
|
103
|
+
!tmp/pids/.keep
|
104
|
+
|
105
|
+
# Ignore uploaded files in development.
|
106
|
+
storage/*
|
107
|
+
!storage/.keep
|
108
|
+
|
98
109
|
public/assets
|
110
|
+
**/.byebug_history
|
111
|
+
|
112
|
+
# Ignore master key for decrypting credentials and more.
|
113
|
+
config/master.key
|
114
|
+
|
115
|
+
public/packs
|
116
|
+
public/packs-test
|
117
|
+
node_modules
|
118
|
+
yarn-error.log
|
119
|
+
**/yarn-debug.log*
|
120
|
+
**/.yarn-integrity
|
99
121
|
END
|
100
122
|
)
|
101
123
|
end
|
data/lib/kuby/tasks.rb
CHANGED
@@ -29,9 +29,13 @@ module Kuby
|
|
29
29
|
end
|
30
30
|
|
31
31
|
def build(build_args = {}, docker_args = [], only = nil)
|
32
|
+
check_platform(docker_args)
|
33
|
+
|
32
34
|
kubernetes.docker_images.each do |image|
|
33
35
|
next if only && image.identifier != only
|
34
36
|
|
37
|
+
return unless perform_docker_login_if_necessary(image)
|
38
|
+
|
35
39
|
image = image.new_version
|
36
40
|
Kuby.logger.info("Building image #{image.image_url} with tags #{image.tags.join(', ')}")
|
37
41
|
image.build(build_args, docker_args)
|
@@ -49,21 +53,7 @@ module Kuby
|
|
49
53
|
end
|
50
54
|
|
51
55
|
def push_image(image)
|
52
|
-
|
53
|
-
Kuby.logger.info("Attempting to log in to registry at #{image.image_host}")
|
54
|
-
|
55
|
-
begin
|
56
|
-
image.docker_cli.login(
|
57
|
-
url: image.image_host,
|
58
|
-
username: image.credentials.username,
|
59
|
-
password: image.credentials.password
|
60
|
-
)
|
61
|
-
rescue Kuby::Docker::LoginError => e
|
62
|
-
Kuby.logger.fatal("Couldn't log in to the registry at #{image.image_host}")
|
63
|
-
Kuby.logger.fatal(e.message)
|
64
|
-
return
|
65
|
-
end
|
66
|
-
end
|
56
|
+
return unless perform_docker_login_if_necessary(image)
|
67
57
|
|
68
58
|
begin
|
69
59
|
image.tags.each { |tag| image.push(tag) }
|
@@ -145,6 +135,71 @@ module Kuby
|
|
145
135
|
|
146
136
|
private
|
147
137
|
|
138
|
+
def check_platform(docker_args)
|
139
|
+
arch, * = RUBY_PLATFORM.split('-')
|
140
|
+
|
141
|
+
if arch != 'x86_64' && !docker_args.include?('--platform')
|
142
|
+
Kuby.logger.fatal(<<~END)
|
143
|
+
Hey there! It looks like your processor isn't x86-compatible.
|
144
|
+
By default, Docker will try to build images that match the
|
145
|
+
current architecture, in this case #{arch}. Most hosting
|
146
|
+
providers run x86 hardware, meaning Docker images built using
|
147
|
+
this computer's architecture might fail to run when deployed
|
148
|
+
to production. You can fix this by running the build command
|
149
|
+
with a special --platform flag, eg:
|
150
|
+
|
151
|
+
bundle exec kuby -e production build -- --platform linux/amd64
|
152
|
+
|
153
|
+
If you meant to build for the current architecture, you can
|
154
|
+
prevent this error by passing the --platform argument for the
|
155
|
+
current architecture, eg. --platform linux/arm64 for ARM, etc.
|
156
|
+
END
|
157
|
+
|
158
|
+
exit 1
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def perform_docker_login_if_necessary(image)
|
163
|
+
auth_uris = image.docker_cli.auths.map do |url|
|
164
|
+
Kuby::Docker::DockerURI.parse_uri(url)
|
165
|
+
end
|
166
|
+
|
167
|
+
logged_in = image.credentials.username && (
|
168
|
+
auth_uris.any? do |uri|
|
169
|
+
image.image_hostname == uri.host ||
|
170
|
+
image.registry_index_hostname == uri.host
|
171
|
+
end
|
172
|
+
)
|
173
|
+
|
174
|
+
if !logged_in
|
175
|
+
Kuby.logger.info("Attempting to log in to registry at #{image.image_host}")
|
176
|
+
|
177
|
+
begin
|
178
|
+
# For some reason, Docker login with a port doesn't work for some
|
179
|
+
# registries (most notably Docker Hub). Since the default is 443 anyway,
|
180
|
+
# it should be fine to omit it.
|
181
|
+
url = if image.image_uri.has_default_port?
|
182
|
+
image.image_hostname # host without port
|
183
|
+
else
|
184
|
+
image.image_host # host with port
|
185
|
+
end
|
186
|
+
|
187
|
+
image.docker_cli.login(
|
188
|
+
url: url,
|
189
|
+
username: image.credentials.username,
|
190
|
+
password: image.credentials.password
|
191
|
+
)
|
192
|
+
rescue Kuby::Docker::LoginError => e
|
193
|
+
Kuby.logger.fatal("Couldn't log in to the registry at #{image.image_host}")
|
194
|
+
Kuby.logger.fatal(e.message)
|
195
|
+
|
196
|
+
return false
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
true
|
201
|
+
end
|
202
|
+
|
148
203
|
def get_first_pod
|
149
204
|
pods = kubernetes_cli.get_objects(
|
150
205
|
'pods', namespace, match_labels.serialize
|
data/lib/kuby/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kuby-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.15.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Cameron Dutro
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-11
|
11
|
+
date: 2021-12-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: colorize
|