kuby-core 0.11.0 → 0.11.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 63e975e73abc299262e996d4bc336f951633d993c8fe56ce997543fb442abe57
4
- data.tar.gz: 1a662d6ff200ecf2b9b8fdd7446d0936329599d940afd06800166537bf82005e
3
+ metadata.gz: 231bc8c37af35418336ba5bb5853049e0d9192932a65eeb3e81a0471b5761953
4
+ data.tar.gz: 9a4e4426e1d183505f09fac2761601c101c92423761647484c1dae3c3a75e235
5
5
  SHA512:
6
- metadata.gz: 30d01ba9e76b0bc79c0d22c63ab65a4edbec0f35add876935233402ae6c96077adeb1b91cef3003858f0534441b1939beae31872860ba453ef3b9ef13aa84d76
7
- data.tar.gz: bb75588789e02dc6bf4135ab59fb401d1ce8e07d8169460ff86282128d1ea610e01de01c44e564c4a9196959a9f6975640f0c14407bd3d02e8257499b0723099
6
+ metadata.gz: 64bd169c3454d196efcf0a21f400107ca8b8c584a20793a8ccf232767aba7ae52fab27307f01e104186b73f537d12907afc86c901538f86266773dacb740cbaa
7
+ data.tar.gz: a54f9fa2eb0cdbfe52a0d4799c1f4fa9bd4677bef8ef4ed4f11caa4690d28f077918a0feb76926b94923ee6ba00e5065d8edabb1997d829d4f7ff5f9b9832708
@@ -1,3 +1,25 @@
1
+ ## 0.11.6
2
+ * Fix Rails generator.
3
+ - Causing `undefined method 'module_parent_name'`. Apparently `module_parent_name` wasn't introduced until Rails 6.
4
+
5
+ ## 0.11.5
6
+ * Raise friendlier error when attempting to add Docker credentials in the development environment.
7
+ * Raise friendlier error when attempting to set a username and password for SQLite databases.
8
+
9
+ ## 0.11.4
10
+ * Fix bug causing crash when running CLI commands.
11
+ - Turns out was caused by adding a Sorbet type annotation inside an anonymous singleton class and forgetting to extend `T::Sig`. Thanks @lazyatom!
12
+
13
+ ## 0.11.3
14
+ * I've gone back and forth a few times on this, but I decided to put the initializer code back into the Rails generator.
15
+
16
+ ## 0.11.2
17
+ * Attempt to auto-require the requested provider if it isn't registered.
18
+ * Adjust error message when provider can't be found to include reminder to add a require statement.
19
+
20
+ ## 0.11.1
21
+ * Use integers for ports instead of strings to appease Kubernetes.
22
+
1
23
  ## 0.11.0
2
24
  * Defer evaluation of database config until after Kuby has been configured.
3
25
  - The issue that prompted this was that the `database` block was being evaluated before the Rails root had been set via `root`. Kuby couldn't find database.yml in a non-standard location and blew up with an error.
@@ -59,8 +59,10 @@ module Kuby
59
59
  tls_enabled false
60
60
 
61
61
  database do
62
- user(DEFAULT_DB_USER) if respond_to?(:user)
63
- password(DEFAULT_DB_PASSWORD) if respond_to?(:password)
62
+ if requires_credentials?
63
+ user(DEFAULT_DB_USER)
64
+ password(DEFAULT_DB_PASSWORD)
65
+ end
64
66
  end
65
67
  end
66
68
 
@@ -1,10 +1,30 @@
1
- # typed: false
1
+ # typed: strict
2
+
2
3
  require 'logger'
3
4
  require 'colorized_string'
4
5
 
5
6
  module Kuby
6
7
  class BasicLogger < Logger
7
- def initialize(*args)
8
+ extend T::Sig
9
+
10
+ sig {
11
+ override.params(
12
+ logdev: T.any(String, IO, StringIO, NilClass),
13
+ shift_age: Integer,
14
+ shift_size: Integer,
15
+ level: Integer,
16
+ progname: T.nilable(String),
17
+ formatter: T.nilable(FormatterProcType),
18
+ datetime_format: T.nilable(String),
19
+ shift_period_suffix: T.nilable(String)
20
+ ).void
21
+ }
22
+ def initialize(
23
+ logdev, shift_age = 0, shift_size = 1048576, level: DEBUG,
24
+ progname: nil, formatter: nil, datetime_format: nil,
25
+ shift_period_suffix: '%Y%m%d')
26
+ @logdev = T.let(@logdev, T.nilable(Logger::LogDevice))
27
+
8
28
  super
9
29
 
10
30
  self.formatter = proc do |_severity, _datetime, _progname, msg|
@@ -12,23 +32,51 @@ module Kuby
12
32
  end
13
33
  end
14
34
 
15
- def info(msg, *args)
16
- super(ColorizedString[msg].yellow, *args)
35
+ sig {
36
+ override.params(
37
+ progname_or_msg: T.untyped,
38
+ block: T.nilable(T.proc.returns(T.untyped))
39
+ ).void
40
+ }
41
+ def info(progname_or_msg = nil, &block)
42
+ if block
43
+ super(progname_or_msg) { ColorizedString[block.call].yellow }
44
+ else
45
+ super(ColorizedString[progname_or_msg].yellow)
46
+ end
17
47
  end
18
48
 
19
- def fatal(msg, *args)
20
- super(ColorizedString[msg].red, *args)
49
+ sig {
50
+ override.params(
51
+ progname_or_msg: T.untyped,
52
+ block: T.nilable(T.proc.returns(T.untyped))
53
+ ).void
54
+ }
55
+ def fatal(progname_or_msg, &block)
56
+ if block
57
+ super(progname_or_msg) { ColorizedString[block.call].red }
58
+ else
59
+ super(ColorizedString[progname_or_msg].red)
60
+ end
21
61
  end
22
62
 
23
63
  # adhere to the "CLI" interface
24
- def with_pipes(out = STDOUT, err = STDERR)
25
- previous_logdev = @logdev || STDERR
64
+ sig {
65
+ params(
66
+ out: T.any(IO, StringIO),
67
+ err: T.any(IO, StringIO),
68
+ block: T.proc.void
69
+ ).void
70
+ }
71
+ def with_pipes(out = STDOUT, err = STDERR, &block)
72
+ previous_logdev = @logdev&.dev || STDERR
26
73
  reopen(err)
27
74
  yield
28
75
  ensure
29
76
  reopen(previous_logdev)
30
77
  end
31
78
 
79
+ sig { returns(T.nilable(Process::Status)) }
32
80
  def last_status
33
81
  nil
34
82
  end
@@ -1,24 +1,39 @@
1
- # typed: true
1
+ # typed: strict
2
+
2
3
  require 'open3'
3
4
  require 'thread'
4
5
 
5
6
  module Kuby
6
7
  class CLIBase
8
+ extend T::Sig
9
+
10
+ sig { returns(T.nilable(Process::Status)) }
7
11
  def last_status
8
12
  Thread.current[status_key]
9
13
  end
10
14
 
15
+ sig { params(block: T.proc.params(cmd: String).void).void }
11
16
  def before_execute(&block)
17
+ @before_execute = T.let(@before_execute, T.nilable(T::Array[T.proc.params(cmd: String).void]))
12
18
  @before_execute ||= []
13
19
  @before_execute << block
14
20
  end
15
21
 
22
+ sig { params(block: T.proc.params(cmd: String).void).void }
16
23
  def after_execute(&block)
24
+ @after_execute = T.let(@after_execute, T.nilable(T::Array[T.proc.params(cmd: String).void]))
17
25
  @after_execute ||= []
18
26
  @after_execute << block
19
27
  end
20
28
 
21
- def with_pipes(out = STDOUT, err = STDERR)
29
+ sig {
30
+ params(
31
+ out: T.any(IO, StringIO),
32
+ err: T.any(IO, StringIO),
33
+ block: T.proc.void
34
+ ).void
35
+ }
36
+ def with_pipes(out = STDOUT, err = STDERR, &block)
22
37
  previous_stdout = self.stdout
23
38
  previous_stderr = self.stderr
24
39
  self.stdout = out
@@ -29,29 +44,39 @@ module Kuby
29
44
  self.stderr = previous_stderr
30
45
  end
31
46
 
47
+ sig { returns(T.nilable(T.any(IO, StringIO))) }
32
48
  def stdout
33
49
  Thread.current[stdout_key] || STDOUT
34
50
  end
35
51
 
52
+ sig { params(new_stdout: T.nilable(T.any(IO, StringIO))).void }
36
53
  def stdout=(new_stdout)
37
54
  Thread.current[stdout_key] = new_stdout
38
55
  end
39
56
 
57
+ sig { returns(T.nilable(T.any(IO, StringIO))) }
40
58
  def stderr
41
59
  Thread.current[stderr_key] || STDERR
42
60
  end
43
61
 
62
+ sig { params(new_stderr: T.nilable(T.any(IO, StringIO))).void }
44
63
  def stderr=(new_stderr)
45
64
  Thread.current[stderr_key] = new_stderr
46
65
  end
47
66
 
48
67
  private
49
68
 
50
- def open3_w(env, cmd, opts = {}, &block)
69
+ sig {
70
+ params(
71
+ cmd: T::Array[String],
72
+ block: T.proc.params(stdin: IO).void
73
+ ).void
74
+ }
75
+ def open3_w(cmd, &block)
51
76
  run_before_callbacks(cmd)
52
77
  cmd_s = cmd.join(' ')
53
78
 
54
- Open3.popen3(env, cmd_s, opts) do |p_stdin, p_stdout, p_stderr, wait_thread|
79
+ Open3.popen3(cmd_s) do |p_stdin, p_stdout, p_stderr, wait_thread|
55
80
  Thread.new(stdout) do |t_stdout|
56
81
  begin
57
82
  p_stdout.each { |line| t_stdout.puts(line) }
@@ -66,21 +91,23 @@ module Kuby
66
91
  end
67
92
  end
68
93
 
69
- yield(p_stdin).tap do
70
- p_stdin.close
71
- self.last_status = wait_thread.value
72
- run_after_callbacks(cmd)
73
- wait_thread.join
74
- end
94
+ yield(p_stdin)
95
+
96
+ p_stdin.close
97
+ self.last_status = T.cast(wait_thread.value, Process::Status)
98
+ run_after_callbacks(cmd)
99
+ wait_thread.join
75
100
  end
76
101
  end
77
102
 
103
+ sig { params(cmd: T::Array[String]).void }
78
104
  def execc(cmd)
79
105
  run_before_callbacks(cmd)
80
106
  cmd_s = cmd.join(' ')
81
107
  exec(cmd_s)
82
108
  end
83
109
 
110
+ sig { params(cmd: T::Array[String]).void }
84
111
  def systemm(cmd)
85
112
  if stdout == STDOUT && stderr == STDERR
86
113
  systemm_default(cmd)
@@ -89,6 +116,7 @@ module Kuby
89
116
  end
90
117
  end
91
118
 
119
+ sig { params(cmd: T::Array[String]).void }
92
120
  def systemm_default(cmd)
93
121
  run_before_callbacks(cmd)
94
122
  cmd_s = cmd.join(' ')
@@ -98,6 +126,7 @@ module Kuby
98
126
  end
99
127
  end
100
128
 
129
+ sig { params(cmd: T::Array[String]).void }
101
130
  def systemm_open3(cmd)
102
131
  run_before_callbacks(cmd)
103
132
  cmd_s = cmd.join(' ')
@@ -118,12 +147,14 @@ module Kuby
118
147
  end
119
148
 
120
149
  p_stdin.close
121
- self.last_status = wait_thread.value
150
+ self.last_status = T.cast(wait_thread.value, Process::Status)
122
151
  run_after_callbacks(cmd)
123
152
  wait_thread.join
124
153
  end
125
154
  end
126
155
 
156
+
157
+ sig { params(cmd: T::Array[String]).returns(String) }
127
158
  def backticks(cmd)
128
159
  if stdout == STDOUT && stderr == STDERR
129
160
  backticks_default(cmd)
@@ -132,6 +163,7 @@ module Kuby
132
163
  end
133
164
  end
134
165
 
166
+ sig { params(cmd: T::Array[String]).returns(String) }
135
167
  def backticks_default(cmd)
136
168
  run_before_callbacks(cmd)
137
169
  cmd_s = cmd.join(' ')
@@ -141,6 +173,7 @@ module Kuby
141
173
  end
142
174
  end
143
175
 
176
+ sig { params(cmd: T::Array[String]).returns(String) }
144
177
  def backticks_open3(cmd)
145
178
  run_before_callbacks(cmd)
146
179
  cmd_s = cmd.join(' ')
@@ -162,7 +195,7 @@ module Kuby
162
195
  end
163
196
 
164
197
  p_stdin.close
165
- self.last_status = wait_thread.value
198
+ self.last_status = T.cast(wait_thread.value, Process::Status)
166
199
  run_after_callbacks(cmd)
167
200
  wait_thread.join
168
201
  end
@@ -170,26 +203,32 @@ module Kuby
170
203
  result.string
171
204
  end
172
205
 
206
+ sig { params(cmd: T::Array[String]).void }
173
207
  def run_before_callbacks(cmd)
174
208
  (@before_execute || []).each { |cb| cb.call(cmd) }
175
209
  end
176
210
 
211
+ sig { params(cmd: T::Array[String]).void }
177
212
  def run_after_callbacks(cmd)
178
213
  (@after_execute || []).each { |cb| cb.call(cmd, last_status) }
179
214
  end
180
215
 
216
+ sig { params(status: Process::Status).void }
181
217
  def last_status=(status)
182
218
  Thread.current[status_key] = status
183
219
  end
184
220
 
221
+ sig { returns(Symbol) }
185
222
  def status_key
186
223
  raise NotImplementedError, "#{__method__} must be defined in derived classes"
187
224
  end
188
225
 
226
+ sig { returns(Symbol) }
189
227
  def stdout_key
190
228
  raise NotImplementedError, "#{__method__} must be defined in derived classes"
191
229
  end
192
230
 
231
+ sig { returns(Symbol) }
193
232
  def stderr_key
194
233
  raise NotImplementedError, "#{__method__} must be defined in derived classes"
195
234
  end
@@ -1,9 +1,11 @@
1
- # typed: true
1
+ # typed: strict
2
+
2
3
  require 'kuby/version'
3
4
  require 'gli'
4
5
 
5
6
  module Kuby
6
7
  class Commands
8
+ extend T::Sig
7
9
  extend GLI::App
8
10
 
9
11
  # GLI doesn't have a wildcard option, so it's impossible to tell it to
@@ -17,8 +19,12 @@ module Kuby
17
19
  # avoid the usual series of cryptic alias_method calls (note that there
18
20
  # is no singleton class version of #prepend in the Ruby language).
19
21
  singleton_class.send(:prepend, Module.new do
22
+ extend T::Sig
23
+
24
+ sig { params(args: T::Array[String]).void }
20
25
  def run(args)
21
26
  if idx = args.index('rails') || idx = args.index('rake')
27
+ @rails_options = T.let(@rails_options, T.nilable(T::Array[String]))
22
28
  @rails_options = args[idx..-1]
23
29
  super(args[0..idx])
24
30
  else
@@ -27,10 +33,12 @@ module Kuby
27
33
  end
28
34
  end)
29
35
 
36
+ sig { returns(Kuby::Tasks) }
30
37
  def self.tasks
31
38
  Kuby::Tasks.new(Kuby.environment)
32
39
  end
33
40
 
41
+ sig { void }
34
42
  def self.must_be_dev_env!
35
43
  unless Kuby.environment.development?
36
44
  fail "Command not supported in the '#{Kuby.environment.name}' environment"
@@ -67,6 +75,7 @@ module Kuby
67
75
  rc.action do |global_options, options, args|
68
76
  must_be_dev_env!
69
77
  exit 1 unless tasks.dev_deployment_ok
78
+ @rails_options = T.let(@rails_options, T.nilable(T::Array[String]))
70
79
  Kuby::RailsCommands.run(@rails_options)
71
80
  end
72
81
 
@@ -1,12 +1,24 @@
1
- # typed: true
1
+ # typed: strict
2
+
2
3
  module Kuby
3
4
  class Definition
5
+ extend T::Sig
6
+
7
+ sig { returns(String) }
4
8
  attr_reader :app_name
5
9
 
10
+ sig { params(app_name: String, block: T.nilable(T.proc.void)).void }
6
11
  def initialize(app_name, &block)
7
12
  @app_name = app_name
13
+ @environments = T.let(@environments, T.nilable(T::Hash[Symbol, Environment]))
8
14
  end
9
15
 
16
+ sig {
17
+ params(
18
+ name: Symbol,
19
+ block: T.nilable(T.proc.void)
20
+ ).returns(Environment)
21
+ }
10
22
  def environment(name = Kuby.env, &block)
11
23
  name = name.to_s
12
24
 
@@ -16,9 +28,10 @@ module Kuby
16
28
  environments[name].instance_eval(&block)
17
29
  end
18
30
 
19
- environments[name]
31
+ T.must(environments[name])
20
32
  end
21
33
 
34
+ sig { returns(T::Hash[Symbol, Environment]) }
22
35
  def environments
23
36
  @environments ||= {}
24
37
  end
@@ -1,19 +1,34 @@
1
- # typed: true
1
+ # typed: strict
2
+
2
3
  module Kuby
3
4
  class Spinner
4
- PIECES = %w(- \\ | /).freeze
5
- INTERVAL = 0.2 # seconds
6
-
7
- def self.spin(message)
5
+ extend T::Sig
6
+
7
+ PIECES = T.let(%w(- \\ | /).freeze, T::Array[String])
8
+ INTERVAL = T.let(0.2, Float) # seconds
9
+
10
+ sig {
11
+ params(
12
+ message: String,
13
+ block: T.proc.params(spinner: Spinner).void
14
+ )
15
+ .void
16
+ }
17
+ def self.spin(message, &block)
8
18
  yield new(message)
9
19
  end
10
20
 
11
- attr_reader :message, :status
21
+ sig { returns(String) }
22
+ attr_reader :message
23
+
24
+ sig { returns(Symbol) }
25
+ attr_reader :status
12
26
 
27
+ sig { params(message: String).void }
13
28
  def initialize(message)
14
- @message = message
15
- @status = :running
16
- @thread = Thread.new do
29
+ @message = T.let(message, String)
30
+ @status = T.let(:running, Symbol)
31
+ @thread = T.let(Thread.new do
17
32
  counter = 0
18
33
 
19
34
  while true
@@ -33,14 +48,16 @@ module Kuby
33
48
  end
34
49
 
35
50
  puts
36
- end
51
+ end, Thread)
37
52
  end
38
53
 
54
+ sig { void }
39
55
  def success
40
56
  @status = :success
41
57
  @thread.join
42
58
  end
43
59
 
60
+ sig { void }
44
61
  def failure
45
62
  @status = :failure
46
63
  @thread.join
@@ -48,66 +65,116 @@ module Kuby
48
65
  end
49
66
 
50
67
  class SetupTask
51
- attr_reader :message, :callable
68
+ extend T::Sig
52
69
 
70
+ sig { returns(String) }
71
+ attr_reader :message
72
+
73
+ sig { returns(T.proc.void) }
74
+ attr_reader :callable
75
+
76
+ sig { params(message: String, callable: T.proc.void).void }
53
77
  def initialize(message, callable)
54
78
  @message = message
55
79
  @callable = callable
56
80
  end
57
81
 
82
+ sig { void }
58
83
  def run
59
84
  callable.call
60
85
  end
61
86
  end
62
87
 
63
88
  class Pipe
64
- attr_reader :name, :cli, :out, :err
89
+ extend T::Sig
90
+
91
+ sig { returns(Symbol) }
92
+ attr_reader :name
93
+
94
+ sig { returns(T.untyped) }
95
+ attr_reader :cli
65
96
 
97
+ sig { returns(StringIO) }
98
+ attr_reader :out
99
+
100
+ sig { returns(StringIO) }
101
+ attr_reader :err
102
+
103
+ sig { params(name: Symbol, cli: T.untyped).void }
66
104
  def initialize(name, cli)
67
- @name = name
68
- @cli = cli
69
- @out = StringIO.new
70
- @err = StringIO.new
105
+ @name = T.let(name, Symbol)
106
+ @cli = T.let(cli, T.untyped)
107
+ @out = T.let(StringIO.new, StringIO)
108
+ @err = T.let(StringIO.new, StringIO)
71
109
  end
72
110
 
111
+ sig { params(block: T.proc.void).void }
73
112
  def wrap(&block)
74
113
  cli.with_pipes(out, err) do
75
114
  block.call
76
115
  end
77
116
  end
78
117
 
118
+ sig { returns(T::Boolean) }
79
119
  def success?
80
120
  cli.last_status.nil? || cli.last_status.success?
81
121
  end
82
122
  end
83
123
 
84
124
  class Pipes
125
+ extend T::Sig
126
+ extend T::Generic
127
+
85
128
  include Enumerable
86
129
 
87
- attr_reader :pipes, :ex
130
+ Elem = type_member(fixed: Pipe)
131
+
132
+ sig { returns(T::Array[Pipe]) }
133
+ attr_reader :pipes
88
134
 
135
+ sig { returns(T.nilable(StandardError)) }
136
+ attr_reader :ex
137
+
138
+ sig { params(clis: T::Hash[Symbol, T.untyped]).returns(Pipes) }
89
139
  def self.build(clis)
90
140
  new(clis.map { |name, cli| Pipe.new(name, cli) })
91
141
  end
92
142
 
143
+ sig { params(pipes: T::Array[Pipe]).void }
93
144
  def initialize(pipes)
94
- @pipes = pipes
145
+ @ex = T.let(@ex, T.nilable(StandardError))
146
+ @pipes = T.let(pipes, T::Array[Pipe])
95
147
  end
96
148
 
149
+ sig {
150
+ override.params(
151
+ block: T.proc.params(package: Pipe).void
152
+ )
153
+ .void
154
+ }
97
155
  def each(&block)
98
156
  pipes.each(&block)
99
157
  end
100
158
 
159
+ sig { params(block: T.proc.void).void }
101
160
  def wrap(&block)
102
161
  do_wrap(pipes, &block)
103
162
  end
104
163
 
164
+ sig { returns(T::Boolean) }
105
165
  def success?
106
166
  pipes.all?(&:success?) && !ex
107
167
  end
108
168
 
109
169
  private
110
170
 
171
+ sig {
172
+ params(
173
+ remaining_pipes: T::Array[Pipe],
174
+ block: T.proc.void
175
+ )
176
+ .void
177
+ }
111
178
  def do_wrap(remaining_pipes, &block)
112
179
  if remaining_pipes.empty?
113
180
  begin
@@ -119,20 +186,28 @@ module Kuby
119
186
  return
120
187
  end
121
188
 
122
- remaining_pipes[0].wrap do
123
- do_wrap(remaining_pipes[1..-1], &block)
189
+ T.must(remaining_pipes[0]).wrap do
190
+ do_wrap(T.must(remaining_pipes[1..-1]), &block)
124
191
  end
125
192
  end
126
193
  end
127
194
 
128
195
  class SetupTaskList
129
- attr_reader :tasks, :clis
196
+ extend T::Sig
197
+
198
+ sig { returns(T::Array[SetupTask]) }
199
+ attr_reader :tasks
130
200
 
201
+ sig { returns T::Hash[Symbol, T.untyped] }
202
+ attr_reader :clis
203
+
204
+ sig { params(tasks: T::Array[SetupTask], clis: T::Hash[Symbol, T.untyped]).void }
131
205
  def initialize(tasks, clis)
132
206
  @tasks = tasks
133
207
  @clis = clis
134
208
  end
135
209
 
210
+ sig { void }
136
211
  def run
137
212
  tasks.each do |task|
138
213
  pipes = Pipes.build(clis)
@@ -160,6 +235,7 @@ module Kuby
160
235
 
161
236
  private
162
237
 
238
+ sig { params(pipe: Pipe).void }
163
239
  def print_streams(pipe)
164
240
  unless pipe.out.string.strip.empty?
165
241
  puts("========= #{pipe.name.upcase} STDOUT ========")
@@ -172,27 +248,37 @@ module Kuby
172
248
  end
173
249
  end
174
250
 
251
+ sig { params(ex: T.nilable(StandardError)).void }
175
252
  def print_error(ex)
176
253
  return unless ex
177
254
  puts("========= RUBY ERROR ========")
178
255
  puts(ex.message)
179
- puts(ex.backtrace.join("\n"))
256
+ puts(T.must(ex.backtrace).join("\n"))
180
257
  end
181
258
  end
182
259
 
183
260
  class DevSetup
261
+ extend T::Sig
262
+
263
+ sig { returns(Environment) }
184
264
  attr_reader :environment
185
265
 
266
+ sig { params(environment: Environment).void }
186
267
  def initialize(environment)
187
- @environment = environment
268
+ @environment = T.let(environment, Environment)
269
+ @setup_tasks = T.let(@setup_tasks, T.nilable(T::Array[SetupTask]))
270
+ @clis = T.let(@clis, T.nilable(T::Hash[Symbol, T.untyped]))
271
+ @tasks = T.let(@tasks, T.nilable(Tasks))
188
272
  end
189
273
 
274
+ sig { void }
190
275
  def run
191
276
  SetupTaskList.new(setup_tasks, clis).run
192
277
  end
193
278
 
194
279
  private
195
280
 
281
+ sig { returns(T::Array[SetupTask]) }
196
282
  def setup_tasks
197
283
  @setup_tasks ||= [
198
284
  SetupTask.new(
@@ -231,14 +317,17 @@ module Kuby
231
317
  ]
232
318
  end
233
319
 
320
+ sig { returns(Kubernetes::Spec) }
234
321
  def kubernetes
235
322
  environment.kubernetes
236
323
  end
237
324
 
325
+ sig { returns(Docker::Spec) }
238
326
  def docker
239
327
  environment.docker
240
328
  end
241
329
 
330
+ sig { returns T::Hash[Symbol, T.untyped] }
242
331
  def clis
243
332
  @clis ||= {
244
333
  kubectl: kubernetes.provider.kubernetes_cli,
@@ -249,6 +338,7 @@ module Kuby
249
338
  }
250
339
  end
251
340
 
341
+ sig { returns(Tasks) }
252
342
  def tasks
253
343
  @tasks ||= Kuby::Tasks.new(environment)
254
344
  end
@@ -35,13 +35,13 @@ module Kuby
35
35
  executable, 'login', url, '--username', username, '--password-stdin'
36
36
  ]
37
37
 
38
- open3_w({}, cmd) do |stdin, _wait_threads|
38
+ open3_w(cmd) do |stdin, _wait_threads|
39
39
  stdin.puts(password)
40
40
  end
41
41
 
42
- unless last_status.success?
42
+ unless T.must(last_status).success?
43
43
  raise LoginError, 'build failed: docker command exited with '\
44
- "status code #{last_status.exitstatus}"
44
+ "status code #{T.must(last_status).exitstatus}"
45
45
  end
46
46
  end
47
47
 
@@ -72,13 +72,13 @@ module Kuby
72
72
  '-f-', '.'
73
73
  ]
74
74
 
75
- open3_w({}, cmd) do |stdin, _wait_threads|
75
+ open3_w(cmd) do |stdin, _wait_threads|
76
76
  stdin.puts(dockerfile.to_s)
77
77
  end
78
78
 
79
- unless last_status.success?
79
+ unless T.must(last_status).success?
80
80
  raise BuildError, 'build failed: docker command exited with '\
81
- "status code #{last_status.exitstatus}"
81
+ "status code #{T.must(last_status).exitstatus}"
82
82
  end
83
83
  end
84
84
 
@@ -124,9 +124,9 @@ module Kuby
124
124
  executable, 'push', "#{image_url}:#{tag}"
125
125
  ])
126
126
 
127
- unless last_status.success?
127
+ unless T.must(last_status).success?
128
128
  raise PushError, 'push failed: docker command exited with '\
129
- "status code #{last_status.exitstatus}"
129
+ "status code #{T.must(last_status).exitstatus}"
130
130
  end
131
131
  end
132
132
 
@@ -136,9 +136,9 @@ module Kuby
136
136
  executable, 'pull', "#{image_url}:#{tag}"
137
137
  ])
138
138
 
139
- unless last_status.success?
139
+ unless T.must(last_status).success?
140
140
  raise PullError, 'pull failed: docker command exited with '\
141
- "status code #{last_status.exitstatus}"
141
+ "status code #{T.must(last_status).exitstatus}"
142
142
  end
143
143
  end
144
144
 
@@ -5,16 +5,16 @@ module Kuby
5
5
  class WebserverDevPhase < Layer
6
6
  extend T::Sig
7
7
 
8
- DEFAULT_PORT = T.let('3000'.freeze, String)
8
+ DEFAULT_PORT = T.let(3000, Integer)
9
9
 
10
- sig { params(port: String).void }
10
+ sig { params(port: Integer).void }
11
11
  attr_writer :port
12
12
 
13
13
  sig { params(environment: Environment).void }
14
14
  def initialize(environment)
15
15
  super
16
16
 
17
- @port = T.let(@port, T.nilable(String))
17
+ @port = T.let(@port, T.nilable(Integer))
18
18
  end
19
19
 
20
20
  sig { override.params(dockerfile: Dockerfile).void }
@@ -22,7 +22,7 @@ module Kuby
22
22
  dockerfile.expose(port)
23
23
  end
24
24
 
25
- sig { returns(String) }
25
+ sig { returns(Integer) }
26
26
  def port
27
27
  @port || DEFAULT_PORT
28
28
  end
@@ -75,7 +75,7 @@ module Kuby
75
75
  @distro_spec = nil
76
76
  end
77
77
 
78
- sig { params(port: String).void }
78
+ sig { params(port: Integer).void }
79
79
  def port(port)
80
80
  webserver_phase.port = port
81
81
  end
@@ -115,6 +115,13 @@ module Kuby
115
115
  layer_stack.includes?(name)
116
116
  end
117
117
 
118
+ sig {
119
+ params(block: T.nilable(T.proc.void)).returns(Credentials)
120
+ }
121
+ def credentials(&block)
122
+ raise 'Docker credentials are not supported in the development environment'
123
+ end
124
+
118
125
  sig { returns(Dockerfile) }
119
126
  def to_dockerfile
120
127
  Dockerfile.new.tap do |df|
@@ -10,10 +10,10 @@ module Kuby
10
10
  class Command
11
11
  extend T::Sig
12
12
 
13
- sig { returns(T::Array[String]) }
13
+ sig { returns(T::Array[T.any(String, Integer)]) }
14
14
  attr_reader :args
15
15
 
16
- sig { params(args: T::Array[String]).void }
16
+ sig { params(args: T::Array[T.any(String, Integer)]).void }
17
17
  def initialize(args)
18
18
  @args = args
19
19
  end
@@ -143,9 +143,9 @@ module Kuby
143
143
  add Copy.new(source, dest, from: from)
144
144
  end
145
145
 
146
- sig { params(args: String).void }
147
- def expose(*args)
148
- add Expose.new(args)
146
+ sig { params(port: Integer).void }
147
+ def expose(port)
148
+ add Expose.new([port])
149
149
  end
150
150
 
151
151
  sig { params(args: String).void }
@@ -164,11 +164,11 @@ module Kuby
164
164
  Digest::SHA256.hexdigest(to_s)
165
165
  end
166
166
 
167
- sig { returns(T::Array[String]) }
167
+ 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.must(c.args.first) }
171
+ .map { |c| T.cast(c.args.first, Integer) }
172
172
  end
173
173
 
174
174
  sig { params(pos: Integer, block: T.proc.void).void }
@@ -78,7 +78,7 @@ module Kuby
78
78
  copy_phase << path
79
79
  end
80
80
 
81
- sig { params(port: String).void }
81
+ sig { params(port: Integer).void }
82
82
  def port(port)
83
83
  webserver_phase.port = port
84
84
  end
@@ -30,7 +30,7 @@ module Kuby
30
30
  'puma',
31
31
  '--workers', '4',
32
32
  '--bind', 'tcp://0.0.0.0',
33
- '--port', phase.port,
33
+ '--port', phase.port.to_s,
34
34
  '--pidfile', './server.pid',
35
35
  './config.ru'
36
36
  )
@@ -39,10 +39,10 @@ module Kuby
39
39
  end
40
40
  end
41
41
 
42
- DEFAULT_PORT = T.let('8080', String)
42
+ DEFAULT_PORT = T.let(8080, Integer)
43
43
  WEBSERVER_MAP = T.let({ puma: Puma }.freeze, T::Hash[Symbol, T.class_of(Webserver)])
44
44
 
45
- sig { params(port: String).void }
45
+ sig { params(port: Integer).void }
46
46
  attr_writer :port
47
47
 
48
48
  sig { returns(T.nilable(Symbol)) }
@@ -55,7 +55,7 @@ module Kuby
55
55
  def initialize(environment)
56
56
  super
57
57
 
58
- @port = T.let(@port, T.nilable(String))
58
+ @port = T.let(@port, T.nilable(Integer))
59
59
  @webserver = T.let(@webserver, T.nilable(Symbol))
60
60
  end
61
61
 
@@ -68,7 +68,7 @@ module Kuby
68
68
  ws_class.new(self).apply_to(dockerfile)
69
69
  end
70
70
 
71
- sig { returns(String) }
71
+ sig { returns(Integer) }
72
72
  def port
73
73
  @port || DEFAULT_PORT
74
74
  end
@@ -18,13 +18,28 @@ module Kuby
18
18
 
19
19
  def provider(provider_name = nil, &block)
20
20
  if provider_name
21
- if @provider || provider_klass = Kuby.providers[provider_name]
22
- @provider ||= provider_klass.new(environment)
21
+ provider_klass = Kuby.providers[provider_name]
22
+
23
+ unless provider_klass
24
+ begin
25
+ # attempt to auto-require
26
+ require "kuby/#{provider_name}"
27
+ provider_klass = Kuby.providers[provider_name]
28
+ rescue LoadError
29
+ end
30
+ end
31
+
32
+ if provider_klass
33
+ if !@provider || !@provider.is_a?(provider_klass)
34
+ @provider = provider_klass.new(environment)
35
+ end
36
+
23
37
  @provider.configure(&block)
24
38
  else
25
39
  msg = if provider_name
26
40
  "no provider registered with name #{provider_name}, "\
27
- 'do you need to add a gem to your Gemfile?'
41
+ 'do you need to add a gem to your Gemfile and/or a '\
42
+ 'require statement to your Kuby config?'
28
43
  else
29
44
  'no provider configured'
30
45
  end
@@ -3,7 +3,25 @@ require 'rails/generators'
3
3
  require 'rails/generators/base'
4
4
 
5
5
  class KubyGenerator < Rails::Generators::Base
6
+ def create_initializer_file
7
+ create_file(
8
+ File.join(*%w(config initializers kuby.rb)),
9
+ <<~END
10
+ require 'kuby'
11
+ Kuby.load!
12
+ END
13
+ )
14
+ end
15
+
6
16
  def create_config_file
17
+ app_class = Rails.application.class
18
+
19
+ app_name = if app_class.respond_to?(:module_parent_name)
20
+ app_class.module_parent_name
21
+ else
22
+ app_class.parent_name
23
+ end
24
+
7
25
  create_file(
8
26
  'kuby.rb',
9
27
  <<~END
@@ -11,7 +29,7 @@ class KubyGenerator < Rails::Generators::Base
11
29
  require 'active_support/encrypted_configuration'
12
30
 
13
31
  # Define a production Kuby deploy environment
14
- Kuby.define('#{Rails.application.class.module_parent_name}') do
32
+ Kuby.define('#{app_name}') do
15
33
  environment(:production) do
16
34
  # Because the Rails environment isn't always loaded when
17
35
  # your Kuby config is loaded, provide access to Rails
@@ -1,4 +1,5 @@
1
1
  # typed: false
2
+
2
3
  require 'kube-dsl'
3
4
  require 'kuby/kube-db'
4
5
 
@@ -15,6 +16,10 @@ module Kuby
15
16
  @configs = configs
16
17
  end
17
18
 
19
+ def requires_credentials?
20
+ true
21
+ end
22
+
18
23
  def name
19
24
  :mysql
20
25
  end
@@ -33,7 +33,6 @@ module Kuby
33
33
  @asset_url = DEFAULT_ASSET_URL
34
34
  @packs_url = DEFAULT_PACKS_URL
35
35
  @asset_path = DEFAULT_ASSET_PATH
36
- # @database = Database.get(self)
37
36
  end
38
37
 
39
38
  def configure(&block)
@@ -1,4 +1,5 @@
1
1
  # typed: false
2
+
2
3
  require 'kube-dsl'
3
4
  require 'kuby/kube-db'
4
5
 
@@ -18,6 +19,10 @@ module Kuby
18
19
  password(config['password'])
19
20
  end
20
21
 
22
+ def requires_credentials?
23
+ true
24
+ end
25
+
21
26
  def name
22
27
  :postgres
23
28
  end
@@ -1,4 +1,5 @@
1
1
  # typed: true
2
+
2
3
  module Kuby
3
4
  module Plugins
4
5
  module RailsApp
@@ -14,6 +15,18 @@ module Kuby
14
15
  environment.docker.package_phase.add(:sqlite_client)
15
16
  end
16
17
 
18
+ def requires_credentials?
19
+ false
20
+ end
21
+
22
+ def user(_user)
23
+ raise 'SQLite databases do not require a username or password'
24
+ end
25
+
26
+ def password(_password)
27
+ raise 'SQLite databases do not require a username or password'
28
+ end
29
+
17
30
  def name
18
31
  :sqlite
19
32
  end
@@ -1,5 +1,5 @@
1
- # typed: strict
1
+ # typed: true
2
2
 
3
3
  module Kuby
4
- VERSION = '0.11.0'
4
+ VERSION = '0.11.6'.freeze
5
5
  end
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.11.0
4
+ version: 0.11.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cameron Dutro
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-10-05 00:00:00.000000000 Z
11
+ date: 2020-10-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: colorize