kuby-core 0.11.16 → 0.12.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 +18 -0
- data/Gemfile +1 -2
- data/kuby-core.gemspec +1 -1
- data/lib/kuby.rb +2 -20
- data/lib/kuby/commands.rb +13 -67
- data/lib/kuby/docker.rb +27 -25
- data/lib/kuby/docker/alpine.rb +2 -1
- data/lib/kuby/docker/app_image.rb +19 -0
- data/lib/kuby/docker/cli.rb +4 -12
- data/lib/kuby/docker/docker_uri.rb +18 -7
- data/lib/kuby/docker/errors.rb +1 -19
- data/lib/kuby/docker/image.rb +115 -0
- data/lib/kuby/docker/layer.rb +0 -7
- data/lib/kuby/docker/local_tags.rb +9 -10
- data/lib/kuby/docker/package_phase.rb +0 -5
- data/lib/kuby/docker/packages.rb +1 -0
- data/lib/kuby/docker/remote_tags.rb +10 -5
- data/lib/kuby/docker/setup_phase.rb +17 -9
- data/lib/kuby/docker/spec.rb +29 -62
- data/lib/kuby/docker/timestamp_tag.rb +8 -1
- data/lib/kuby/docker/timestamped_image.rb +113 -0
- data/lib/kuby/environment.rb +1 -10
- data/lib/kuby/kubernetes/bare_metal_provider.rb +16 -4
- data/lib/kuby/kubernetes/deployer.rb +1 -1
- data/lib/kuby/kubernetes/docker_desktop_provider.rb +0 -15
- data/lib/kuby/kubernetes/spec.rb +21 -17
- data/lib/kuby/plugin.rb +2 -2
- data/lib/kuby/plugins/rails_app.rb +1 -0
- data/lib/kuby/plugins/rails_app/assets.rb +60 -70
- data/lib/kuby/plugins/rails_app/assets_image.rb +55 -0
- data/lib/kuby/plugins/rails_app/plugin.rb +53 -236
- data/lib/kuby/tasks.rb +30 -69
- data/lib/kuby/version.rb +1 -1
- data/spec/docker/spec_spec.rb +9 -118
- data/spec/docker/timestamped_image_spec.rb +123 -0
- data/spec/spec_helper.rb +10 -11
- metadata +9 -10
- data/lib/kuby/dev_setup.rb +0 -346
- data/lib/kuby/docker/dev_spec.rb +0 -202
- data/lib/kuby/docker/metadata.rb +0 -90
- data/lib/kuby/docker/tags.rb +0 -92
- data/lib/kuby/rails_commands.rb +0 -84
- data/spec/docker/metadata_spec.rb +0 -73
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4a072588afc0cc4e0cf815c276628b90c192bf24310ed6c4c53089bc467ba278
|
4
|
+
data.tar.gz: 364b1265256eda0eea1f57469f241a1c78f1bdb2be0d37d8a23b5c6f01f4ff43
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 866438d8c0880d949150d337b01fce94dfab9d0606ab3e2358e4c7cad376bb36cb3ff958ea72188967abf1192216c3b7586ddcfba6d7e0324ab4fbe37a085e49
|
7
|
+
data.tar.gz: 87e438bd3f4783b1b3d0e7609d773f5eeee91f7b9ae980446c8ca63084bddeb3a525d944750fe13fb36e98d782188cf6bd06c3df5edff742d8a1d5d80aa53966
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,21 @@
|
|
1
|
+
## 0.12.0
|
2
|
+
* Fix issue causing volume mount errors when k8s tries to schedule asset pods on multiple nodes (fixes #42).
|
3
|
+
- Persistent volumes can only be mounted on a single physical node.
|
4
|
+
- Kuby now creates a separate assets image powered by nginx.
|
5
|
+
- Ingress routes requests to either the Rails service or assets service depending on the URL (i.e. /assets).
|
6
|
+
- Since the ingress layer is now essential, the Docker Desktop provider no longer deletes ingresses or monkeys with service objects. You'll have to either 1) add an entry for your hostname to your hosts file, or 2) set the `Host` header when making requests to your app.
|
7
|
+
* Plugins can now specify additional Dockerfiles to build during `kuby build`.
|
8
|
+
* Switch from TravisCI to Github Actions.
|
9
|
+
* Remove support for development environments.
|
10
|
+
- Proved to be too difficult to maintain.
|
11
|
+
- Kuby is a _deployment_ tool anyway, not a dev tool.
|
12
|
+
- Maybe we can turn the dev stuff into a gem at some point.
|
13
|
+
* Refactor Docker image logic.
|
14
|
+
- Introduced the `Image` class and friends.
|
15
|
+
- Deleted the `Kuby::Docker::Metadata` class.
|
16
|
+
* Add missing git dependency to Alpine distro.
|
17
|
+
* Add a bare metal provider (fixes #10).
|
18
|
+
|
1
19
|
## 0.11.16
|
2
20
|
* Fix yarn phase
|
3
21
|
- Apparently you have to copy at least one file, TIL.
|
data/Gemfile
CHANGED
@@ -6,10 +6,9 @@ group :development, :test do
|
|
6
6
|
gem 'pry-byebug'
|
7
7
|
gem 'rake'
|
8
8
|
# lock to a specific version to prevent breaking CI when new versions come out
|
9
|
-
gem 'sorbet', '= 0.5.
|
9
|
+
gem 'sorbet', '= 0.5.6433'
|
10
10
|
end
|
11
11
|
|
12
12
|
group :test do
|
13
13
|
gem 'rspec', '~> 3.0'
|
14
|
-
gem 'timecop', '~> 0.9'
|
15
14
|
end
|
data/kuby-core.gemspec
CHANGED
@@ -13,7 +13,7 @@ Gem::Specification.new do |s|
|
|
13
13
|
s.platform = Gem::Platform::RUBY
|
14
14
|
|
15
15
|
s.add_dependency 'colorize', '~> 0.8'
|
16
|
-
s.add_dependency 'docker-remote', '~> 0.
|
16
|
+
s.add_dependency 'docker-remote', '~> 0.6'
|
17
17
|
s.add_dependency 'gli', '~> 2.0'
|
18
18
|
s.add_dependency 'helm-cli', '~> 0.3'
|
19
19
|
# See: https://github.com/Shopify/krane/pull/720
|
data/lib/kuby.rb
CHANGED
@@ -13,7 +13,6 @@ module Kuby
|
|
13
13
|
autoload :CLIBase, 'kuby/cli_base'
|
14
14
|
autoload :Commands, 'kuby/commands'
|
15
15
|
autoload :Definition, 'kuby/definition'
|
16
|
-
autoload :DevSetup, 'kuby/dev_setup'
|
17
16
|
autoload :Docker, 'kuby/docker'
|
18
17
|
autoload :Environment, 'kuby/environment'
|
19
18
|
autoload :Kubernetes, 'kuby/kubernetes'
|
@@ -21,7 +20,6 @@ module Kuby
|
|
21
20
|
autoload :Plugin, 'kuby/plugin'
|
22
21
|
autoload :PluginRegistry, 'kuby/plugin_registry'
|
23
22
|
autoload :Plugins, 'kuby/plugins'
|
24
|
-
autoload :RailsCommands, 'kuby/rails_commands'
|
25
23
|
autoload :Tasks, 'kuby/tasks'
|
26
24
|
autoload :TrailingHash, 'kuby/trailing_hash'
|
27
25
|
|
@@ -52,24 +50,6 @@ module Kuby
|
|
52
50
|
@definition = Definition.new(name.to_s)
|
53
51
|
@definition.instance_eval(&block)
|
54
52
|
|
55
|
-
# default development environment
|
56
|
-
@definition.environment(:development) do
|
57
|
-
kubernetes do
|
58
|
-
add_plugin(:rails_app) do
|
59
|
-
tls_enabled false
|
60
|
-
|
61
|
-
database do
|
62
|
-
if requires_credentials?
|
63
|
-
user(DEFAULT_DB_USER)
|
64
|
-
password(DEFAULT_DB_PASSWORD)
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
provider :docker_desktop
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
53
|
@definition.environments.each do |_, env|
|
74
54
|
env.kubernetes.after_configuration
|
75
55
|
end
|
@@ -174,3 +154,5 @@ Kuby.register_package(:c_toolchain,
|
|
174
154
|
debian: 'build-essential',
|
175
155
|
alpine: 'build-base'
|
176
156
|
)
|
157
|
+
|
158
|
+
Kuby.register_package(:git, 'git')
|
data/lib/kuby/commands.rb
CHANGED
@@ -38,13 +38,6 @@ module Kuby
|
|
38
38
|
Kuby::Tasks.new(Kuby.environment)
|
39
39
|
end
|
40
40
|
|
41
|
-
sig { void }
|
42
|
-
def self.must_be_dev_env!
|
43
|
-
unless Kuby.environment.development?
|
44
|
-
fail "Command not supported in the '#{Kuby.environment.name}' environment"
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
41
|
program_desc 'Kuby command-line interface. Kuby is a convention '\
|
49
42
|
'over configuration approach for running Rails apps in Kubernetes.'
|
50
43
|
|
@@ -68,59 +61,19 @@ module Kuby
|
|
68
61
|
true
|
69
62
|
end
|
70
63
|
|
71
|
-
# These are only stubs included to fill out the help screens. Rails
|
72
|
-
# commands are handled by the RailsCommands class.
|
73
|
-
desc 'Runs a Rails command.'
|
74
|
-
command :rails do |rc|
|
75
|
-
rc.action do |global_options, options, args|
|
76
|
-
must_be_dev_env!
|
77
|
-
exit 1 unless tasks.dev_deployment_ok
|
78
|
-
@rails_options = T.let(@rails_options, T.nilable(T::Array[String]))
|
79
|
-
Kuby::RailsCommands.run(@rails_options)
|
80
|
-
end
|
81
|
-
|
82
|
-
rc.desc 'Runs the rails server (run `rails server --help` for options)'
|
83
|
-
rc.command [:server, :s] do |c|
|
84
|
-
c.action do |global_options, options, args|
|
85
|
-
must_be_dev_env!
|
86
|
-
exit 1 unless tasks.dev_deployment_ok
|
87
|
-
Kuby::RailsCommands.run(@rails_options)
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
rc.desc 'Runs a script in the Rails environment (run `rails runner --help` for options)'
|
92
|
-
rc.command [:runner, :r] do |c|
|
93
|
-
c.action do |global_options, options, args|
|
94
|
-
must_be_dev_env!
|
95
|
-
exit 1 unless tasks.dev_deployment_ok
|
96
|
-
Kuby::RailsCommands.run(@rails_options)
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
rc.desc 'Starts an interactive Ruby console with the Rails environment loaded '\
|
101
|
-
'(run `rails console --help` for options)'
|
102
|
-
rc.command [:console, :c] do |c|
|
103
|
-
c.action do |global_options, options, args|
|
104
|
-
must_be_dev_env!
|
105
|
-
exit 1 unless tasks.dev_deployment_ok
|
106
|
-
Kuby::RailsCommands.run(@rails_options)
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
desc 'Runs a rake task.'
|
112
|
-
command :rake do |rc|
|
113
|
-
rc.action do |global_options, options, args|
|
114
|
-
must_be_dev_env!
|
115
|
-
exit 1 unless tasks.dev_deployment_ok
|
116
|
-
Kuby::RailsCommands.run(@rails_options)
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
64
|
desc 'Builds the Docker image.'
|
121
65
|
command :build do |c|
|
66
|
+
c.flag [:a, :arg], required: false, multiple: true
|
122
67
|
c.action do |global_options, options, args|
|
123
|
-
|
68
|
+
build_args = {}.tap do |build_args|
|
69
|
+
(options[:arg] || []).each do |a|
|
70
|
+
key, value = a.split('=')
|
71
|
+
value = value[1..-2] if value.start_with?('"') || value.start_with?("'")
|
72
|
+
build_args[key] = value
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
tasks.build(build_args)
|
124
77
|
end
|
125
78
|
end
|
126
79
|
|
@@ -138,10 +91,10 @@ module Kuby
|
|
138
91
|
end
|
139
92
|
end
|
140
93
|
|
141
|
-
desc 'Prints the effective
|
142
|
-
command :
|
94
|
+
desc 'Prints the effective Dockerfiles used to build Docker images.'
|
95
|
+
command :dockerfiles do |c|
|
143
96
|
c.action do |global_options, options, args|
|
144
|
-
tasks.
|
97
|
+
tasks.print_dockerfiles
|
145
98
|
end
|
146
99
|
end
|
147
100
|
|
@@ -197,7 +150,6 @@ module Kuby
|
|
197
150
|
rc.desc 'Tails (i.e. continuously streams) the Rails log from your running application.'
|
198
151
|
rc.command :logs do |c|
|
199
152
|
c.action do |global_options, options, args|
|
200
|
-
exit 1 unless tasks.dev_deployment_ok
|
201
153
|
tasks.remote_logs
|
202
154
|
end
|
203
155
|
end
|
@@ -205,7 +157,6 @@ module Kuby
|
|
205
157
|
rc.desc 'Lists running Kubernetes pods.'
|
206
158
|
rc.command :status do |c|
|
207
159
|
c.action do |global_options, options, args|
|
208
|
-
exit 1 unless tasks.dev_deployment_ok
|
209
160
|
tasks.remote_status
|
210
161
|
end
|
211
162
|
end
|
@@ -213,7 +164,6 @@ module Kuby
|
|
213
164
|
rc.desc 'Runs an arbitrary command inside a running Rails pod.'
|
214
165
|
rc.command :exec do |c|
|
215
166
|
c.action do |global_options, options, args|
|
216
|
-
exit 1 unless tasks.dev_deployment_ok
|
217
167
|
tasks.remote_exec(args)
|
218
168
|
end
|
219
169
|
end
|
@@ -221,7 +171,6 @@ module Kuby
|
|
221
171
|
rc.desc 'Establishes a shell inside a running Rails pod.'
|
222
172
|
rc.command :shell do |c|
|
223
173
|
c.action do |global_options, options, args|
|
224
|
-
exit 1 unless tasks.dev_deployment_ok
|
225
174
|
tasks.remote_shell
|
226
175
|
end
|
227
176
|
end
|
@@ -229,7 +178,6 @@ module Kuby
|
|
229
178
|
rc.desc 'Establishes a Rails console inside a running Rails pod.'
|
230
179
|
rc.command :console do |c|
|
231
180
|
c.action do |global_options, options, args|
|
232
|
-
exit 1 unless tasks.dev_deployment_ok
|
233
181
|
tasks.remote_console
|
234
182
|
end
|
235
183
|
end
|
@@ -237,7 +185,6 @@ module Kuby
|
|
237
185
|
rc.desc 'Establishes a database console inside a running Rails pod.'
|
238
186
|
rc.command :dbconsole do |c|
|
239
187
|
c.action do |global_options, options, args|
|
240
|
-
exit 1 unless tasks.dev_deployment_ok
|
241
188
|
tasks.remote_dbconsole
|
242
189
|
end
|
243
190
|
end
|
@@ -245,7 +192,6 @@ module Kuby
|
|
245
192
|
rc.desc "Restarts the Rails app's web pods."
|
246
193
|
rc.command :restart do |c|
|
247
194
|
c.action do |global_options, options, args|
|
248
|
-
exit 1 unless tasks.dev_deployment_ok
|
249
195
|
tasks.remote_restart
|
250
196
|
end
|
251
197
|
end
|
data/lib/kuby/docker.rb
CHANGED
@@ -4,30 +4,32 @@ require 'kuby/docker/errors'
|
|
4
4
|
|
5
5
|
module Kuby
|
6
6
|
module Docker
|
7
|
-
|
8
|
-
|
9
|
-
autoload :
|
10
|
-
autoload :
|
11
|
-
autoload :
|
12
|
-
autoload :
|
13
|
-
autoload :
|
14
|
-
autoload :
|
15
|
-
autoload :
|
16
|
-
autoload :
|
17
|
-
autoload :
|
18
|
-
autoload :
|
19
|
-
autoload :
|
20
|
-
autoload :
|
21
|
-
autoload :
|
22
|
-
autoload :
|
23
|
-
autoload :
|
24
|
-
autoload :
|
25
|
-
autoload :
|
26
|
-
autoload :
|
27
|
-
autoload :
|
28
|
-
autoload :
|
29
|
-
autoload :
|
30
|
-
autoload :
|
31
|
-
autoload :
|
7
|
+
LATEST_TAG = T.let('latest'.freeze, String)
|
8
|
+
|
9
|
+
autoload :Alpine, 'kuby/docker/alpine'
|
10
|
+
autoload :AppImage, 'kuby/docker/app_image'
|
11
|
+
autoload :AssetsPhase, 'kuby/docker/assets_phase'
|
12
|
+
autoload :BundlerPhase, 'kuby/docker/bundler_phase'
|
13
|
+
autoload :CLI, 'kuby/docker/cli'
|
14
|
+
autoload :CopyPhase, 'kuby/docker/copy_phase'
|
15
|
+
autoload :Credentials, 'kuby/docker/credentials'
|
16
|
+
autoload :Debian, 'kuby/docker/debian'
|
17
|
+
autoload :Distro, 'kuby/docker/distro'
|
18
|
+
autoload :Dockerfile, 'kuby/docker/dockerfile'
|
19
|
+
autoload :DockerURI, 'kuby/docker/docker_uri'
|
20
|
+
autoload :Image, 'kuby/docker/image'
|
21
|
+
autoload :InlineLayer, 'kuby/docker/inline_layer'
|
22
|
+
autoload :Layer, 'kuby/docker/layer'
|
23
|
+
autoload :LayerStack, 'kuby/docker/layer_stack'
|
24
|
+
autoload :LocalTags, 'kuby/docker/local_tags'
|
25
|
+
autoload :Packages, 'kuby/docker/packages'
|
26
|
+
autoload :PackagePhase, 'kuby/docker/package_phase'
|
27
|
+
autoload :RemoteTags, 'kuby/docker/remote_tags'
|
28
|
+
autoload :SetupPhase, 'kuby/docker/setup_phase'
|
29
|
+
autoload :Spec, 'kuby/docker/spec'
|
30
|
+
autoload :TimestampedImage, 'kuby/docker/timestamped_image'
|
31
|
+
autoload :TimestampTag, 'kuby/docker/timestamp_tag'
|
32
|
+
autoload :WebserverPhase, 'kuby/docker/webserver_phase'
|
33
|
+
autoload :YarnPhase, 'kuby/docker/yarn_phase'
|
32
34
|
end
|
33
35
|
end
|
data/lib/kuby/docker/alpine.rb
CHANGED
@@ -0,0 +1,19 @@
|
|
1
|
+
|
2
|
+
# typed: strict
|
3
|
+
|
4
|
+
module Kuby
|
5
|
+
module Docker
|
6
|
+
class AppImage < ::Kuby::Docker::TimestampedImage
|
7
|
+
extend T::Sig
|
8
|
+
|
9
|
+
sig { params(build_args: T::Hash[String, String]).returns(AppImage) }
|
10
|
+
def build(build_args = {})
|
11
|
+
unless ENV.fetch('RAILS_MASTER_KEY', '').empty?
|
12
|
+
build_args['RAILS_MASTER_KEY'] = T.must(ENV['RAILS_MASTER_KEY'])
|
13
|
+
end
|
14
|
+
|
15
|
+
super(build_args)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/kuby/docker/cli.rb
CHANGED
@@ -53,19 +53,11 @@ module Kuby
|
|
53
53
|
config.fetch('auths', {}).keys
|
54
54
|
end
|
55
55
|
|
56
|
-
sig {
|
57
|
-
|
58
|
-
dockerfile: Dockerfile,
|
59
|
-
image_url: String,
|
60
|
-
tags: T::Array[String],
|
61
|
-
build_args: T::Hash[T.any(Symbol, String), String]
|
62
|
-
)
|
63
|
-
.void
|
64
|
-
}
|
65
|
-
def build(dockerfile:, image_url:, tags:, build_args: {})
|
56
|
+
sig { params(image: Image, build_args: T::Hash[T.any(Symbol, String), String]).void }
|
57
|
+
def build(image, build_args: {})
|
66
58
|
cmd = [
|
67
59
|
executable, 'build',
|
68
|
-
*tags.flat_map { |tag| ['-t', "#{image_url}:#{tag}"] },
|
60
|
+
*image.tags.flat_map { |tag| ['-t', "#{image.image_url}:#{tag}"] },
|
69
61
|
*build_args.flat_map do |arg, val|
|
70
62
|
['--build-arg', Shellwords.shellescape("#{arg}=#{val}")]
|
71
63
|
end,
|
@@ -73,7 +65,7 @@ module Kuby
|
|
73
65
|
]
|
74
66
|
|
75
67
|
open3_w(cmd) do |stdin, _wait_threads|
|
76
|
-
stdin.puts(dockerfile.to_s)
|
68
|
+
stdin.puts(image.dockerfile.to_s)
|
77
69
|
end
|
78
70
|
|
79
71
|
unless T.must(last_status).success?
|
@@ -1,11 +1,14 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strict
|
2
2
|
|
3
3
|
module Kuby
|
4
4
|
module Docker
|
5
5
|
class DockerURI
|
6
|
-
|
7
|
-
DEFAULT_REGISTRY_PORT = 443
|
6
|
+
extend T::Sig
|
8
7
|
|
8
|
+
DEFAULT_REGISTRY_HOST = T.let('index.docker.io'.freeze, String)
|
9
|
+
DEFAULT_REGISTRY_PORT = T.let(443, Integer)
|
10
|
+
|
11
|
+
sig { params(url: String).returns(DockerURI) }
|
9
12
|
def self.parse(url)
|
10
13
|
if idx = url.index('://')
|
11
14
|
url = url[(idx + 3)..-1] || ''
|
@@ -13,17 +16,25 @@ module Kuby
|
|
13
16
|
|
14
17
|
host_port, *path = url.split('/')
|
15
18
|
host, port, *path = if host_port =~ /[.:]/
|
16
|
-
hst, prt = host_port.split(':')
|
17
|
-
[hst, prt || DEFAULT_REGISTRY_PORT, *path]
|
19
|
+
hst, prt = T.must(host_port).split(':')
|
20
|
+
[T.must(hst), prt || DEFAULT_REGISTRY_PORT, *path]
|
18
21
|
else
|
19
22
|
[DEFAULT_REGISTRY_HOST, DEFAULT_REGISTRY_PORT, host_port, *path]
|
20
23
|
end
|
21
24
|
|
22
|
-
new(host, port.to_i, path.join('/'))
|
25
|
+
new(host.to_s, port.to_i, (path || []).join('/'))
|
23
26
|
end
|
24
27
|
|
25
|
-
|
28
|
+
sig { returns(String) }
|
29
|
+
attr_reader :host
|
30
|
+
|
31
|
+
sig { returns(Integer) }
|
32
|
+
attr_reader :port
|
33
|
+
|
34
|
+
sig { returns(String) }
|
35
|
+
attr_reader :path
|
26
36
|
|
37
|
+
sig { params(host: String, port: Integer, path: String).void }
|
27
38
|
def initialize(host, port, path)
|
28
39
|
@host = host
|
29
40
|
@port = port
|
data/lib/kuby/docker/errors.rb
CHANGED
@@ -6,25 +6,7 @@ module Kuby
|
|
6
6
|
class PushError < StandardError; end
|
7
7
|
class PullError < StandardError; end
|
8
8
|
class LoginError < StandardError; end
|
9
|
-
|
10
|
-
class MissingTagError < StandardError
|
11
|
-
extend T::Sig
|
12
|
-
|
13
|
-
sig { returns(String) }
|
14
|
-
attr_reader :tag
|
15
|
-
|
16
|
-
sig { params(tag: String).void }
|
17
|
-
def initialize(tag)
|
18
|
-
@tag = tag
|
19
|
-
@message = T.let(@message, T.nilable(String))
|
20
|
-
end
|
21
|
-
|
22
|
-
sig { returns(String) }
|
23
|
-
def message
|
24
|
-
@message ||= "Could not find tag '#{tag}'."
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
9
|
+
class MissingTagError < StandardError; end
|
28
10
|
class UnsupportedDistroError < StandardError; end
|
29
11
|
class MissingPackageError < StandardError; end
|
30
12
|
class MissingDistroError < StandardError; end
|