dash 3.2.0 → 4.0.0

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.
Files changed (178) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/bin/dash +2 -2
  4. data/lib/{kamal → dash}/cli/accessory.rb +24 -24
  5. data/lib/dash/cli/alias/command.rb +10 -0
  6. data/lib/{kamal → dash}/cli/app/assets.rb +2 -2
  7. data/lib/{kamal → dash}/cli/app/boot.rb +16 -16
  8. data/lib/{kamal → dash}/cli/app/error_pages.rb +6 -6
  9. data/lib/{kamal → dash}/cli/app/rollout_boot.rb +6 -6
  10. data/lib/{kamal → dash}/cli/app/ssl_certificates.rb +3 -3
  11. data/lib/{kamal → dash}/cli/app.rb +87 -87
  12. data/lib/{kamal → dash}/cli/base.rb +72 -48
  13. data/lib/dash/cli/build/clone.rb +59 -0
  14. data/lib/{kamal → dash}/cli/build/port_forwarding.rb +1 -1
  15. data/lib/{kamal → dash}/cli/build.rb +45 -45
  16. data/lib/{kamal → dash}/cli/doctor/config_checks.rb +3 -3
  17. data/lib/{kamal → dash}/cli/doctor/endpoint_checks.rb +26 -8
  18. data/lib/{kamal → dash}/cli/doctor/host_checks.rb +22 -22
  19. data/lib/{kamal → dash}/cli/doctor.rb +9 -9
  20. data/lib/{kamal → dash}/cli/healthcheck/barrier.rb +2 -2
  21. data/lib/{kamal → dash}/cli/healthcheck/drift_error.rb +2 -2
  22. data/lib/dash/cli/healthcheck/error.rb +2 -0
  23. data/lib/{kamal → dash}/cli/healthcheck/poller.rb +7 -7
  24. data/lib/{kamal → dash}/cli/lock.rb +1 -1
  25. data/lib/dash/cli/main/migrate.rb +77 -0
  26. data/lib/{kamal → dash}/cli/main.rb +82 -71
  27. data/lib/{kamal → dash}/cli/proxy/drift.rb +3 -3
  28. data/lib/dash/cli/proxy/legacy_rename.rb +58 -0
  29. data/lib/{kamal → dash}/cli/proxy/loadbalancer_claim.rb +3 -3
  30. data/lib/{kamal → dash}/cli/proxy/loadbalancer_reboot.rb +23 -23
  31. data/lib/{kamal → dash}/cli/proxy/reboot.rb +21 -21
  32. data/lib/{kamal → dash}/cli/proxy.rb +178 -162
  33. data/lib/{kamal → dash}/cli/prune.rb +10 -10
  34. data/lib/{kamal → dash}/cli/registry.rb +11 -11
  35. data/lib/{kamal → dash}/cli/secrets.rb +3 -3
  36. data/lib/{kamal → dash}/cli/server.rb +14 -14
  37. data/lib/{kamal → dash}/cli/templates/deploy.yml +4 -4
  38. data/lib/dash/cli/templates/sample_hooks/docker-setup.sample +3 -0
  39. data/lib/dash/cli/templates/sample_hooks/post-app-boot.sample +3 -0
  40. data/lib/dash/cli/templates/sample_hooks/post-app-stop.sample +9 -0
  41. data/lib/dash/cli/templates/sample_hooks/post-deploy.sample +14 -0
  42. data/lib/dash/cli/templates/sample_hooks/post-proxy-deploy.sample +3 -0
  43. data/lib/dash/cli/templates/sample_hooks/post-proxy-reboot.sample +3 -0
  44. data/lib/dash/cli/templates/sample_hooks/pre-app-boot.sample +3 -0
  45. data/lib/{kamal → dash}/cli/templates/sample_hooks/pre-app-stop.sample +2 -2
  46. data/lib/{kamal → dash}/cli/templates/sample_hooks/pre-build.sample +8 -8
  47. data/lib/{kamal → dash}/cli/templates/sample_hooks/pre-connect.sample +8 -8
  48. data/lib/{kamal → dash}/cli/templates/sample_hooks/pre-deploy.sample +9 -9
  49. data/lib/dash/cli/templates/sample_hooks/pre-proxy-deploy.sample +3 -0
  50. data/lib/dash/cli/templates/sample_hooks/pre-proxy-reboot.sample +3 -0
  51. data/lib/{kamal → dash}/cli/templates/secrets +6 -6
  52. data/lib/{kamal → dash}/cli.rb +2 -2
  53. data/lib/{kamal → dash}/commander/specifics.rb +2 -2
  54. data/lib/{kamal → dash}/commander.rb +32 -24
  55. data/lib/{kamal → dash}/commands/accessory/proxy.rb +2 -2
  56. data/lib/{kamal → dash}/commands/accessory.rb +2 -2
  57. data/lib/{kamal → dash}/commands/app/assets.rb +1 -1
  58. data/lib/{kamal → dash}/commands/app/containers.rb +1 -1
  59. data/lib/{kamal → dash}/commands/app/error_pages.rb +2 -2
  60. data/lib/{kamal → dash}/commands/app/execution.rb +2 -2
  61. data/lib/{kamal → dash}/commands/app/images.rb +1 -1
  62. data/lib/{kamal → dash}/commands/app/logging.rb +1 -1
  63. data/lib/{kamal → dash}/commands/app/proxy.rb +2 -2
  64. data/lib/{kamal → dash}/commands/app.rb +2 -2
  65. data/lib/{kamal → dash}/commands/auditor.rb +3 -7
  66. data/lib/{kamal → dash}/commands/base.rb +39 -3
  67. data/lib/{kamal → dash}/commands/builder/base.rb +2 -2
  68. data/lib/{kamal → dash}/commands/builder/clone.rb +3 -3
  69. data/lib/{kamal → dash}/commands/builder/cloud.rb +1 -1
  70. data/lib/{kamal → dash}/commands/builder/hybrid.rb +1 -1
  71. data/lib/{kamal → dash}/commands/builder/local.rb +1 -1
  72. data/lib/{kamal → dash}/commands/builder/pack.rb +1 -1
  73. data/lib/{kamal → dash}/commands/builder/remote.rb +1 -1
  74. data/lib/{kamal → dash}/commands/builder.rb +7 -7
  75. data/lib/dash/commands/docker.rb +89 -0
  76. data/lib/{kamal → dash}/commands/hook.rb +1 -1
  77. data/lib/{kamal → dash}/commands/loadbalancer.rb +55 -24
  78. data/lib/{kamal → dash}/commands/lock.rb +3 -3
  79. data/lib/{kamal → dash}/commands/proxy/cert_transfer.rb +6 -6
  80. data/lib/dash/commands/proxy.rb +375 -0
  81. data/lib/{kamal → dash}/commands/prune.rb +2 -2
  82. data/lib/dash/commands/registry.rb +44 -0
  83. data/lib/{kamal → dash}/commands/server.rb +1 -5
  84. data/lib/dash/commands.rb +2 -0
  85. data/lib/{kamal → dash}/configuration/accessory.rb +13 -13
  86. data/lib/{kamal → dash}/configuration/alias.rb +3 -3
  87. data/lib/{kamal → dash}/configuration/boot.rb +2 -2
  88. data/lib/{kamal → dash}/configuration/builder.rb +7 -7
  89. data/lib/{kamal → dash}/configuration/docs/accessory.yml +3 -3
  90. data/lib/{kamal → dash}/configuration/docs/builder.yml +3 -3
  91. data/lib/{kamal → dash}/configuration/docs/configuration.yml +13 -6
  92. data/lib/{kamal → dash}/configuration/docs/env.yml +10 -10
  93. data/lib/{kamal → dash}/configuration/docs/proxy.yml +68 -45
  94. data/lib/{kamal → dash}/configuration/docs/registry.yml +5 -5
  95. data/lib/{kamal → dash}/configuration/env/tag.rb +2 -2
  96. data/lib/{kamal → dash}/configuration/env.rb +5 -5
  97. data/lib/{kamal → dash}/configuration/loadbalancer.rb +5 -5
  98. data/lib/{kamal → dash}/configuration/logging.rb +3 -3
  99. data/lib/{kamal → dash}/configuration/output.rb +4 -4
  100. data/lib/{kamal → dash}/configuration/proxy/acme.rb +9 -8
  101. data/lib/{kamal → dash}/configuration/proxy/boot.rb +9 -11
  102. data/lib/{kamal → dash}/configuration/proxy/run.rb +20 -20
  103. data/lib/{kamal → dash}/configuration/proxy.rb +51 -29
  104. data/lib/{kamal → dash}/configuration/registry.rb +3 -3
  105. data/lib/{kamal → dash}/configuration/role/healthcheck.rb +3 -3
  106. data/lib/{kamal → dash}/configuration/role.rb +14 -14
  107. data/lib/{kamal → dash}/configuration/servers.rb +4 -4
  108. data/lib/{kamal → dash}/configuration/ssh.rb +2 -2
  109. data/lib/{kamal → dash}/configuration/sshkit.rb +2 -2
  110. data/lib/{kamal → dash}/configuration/validation.rb +2 -2
  111. data/lib/{kamal → dash}/configuration/validator/accessory.rb +1 -1
  112. data/lib/{kamal → dash}/configuration/validator/alias.rb +2 -2
  113. data/lib/{kamal → dash}/configuration/validator/builder.rb +1 -1
  114. data/lib/dash/configuration/validator/configuration.rb +6 -0
  115. data/lib/{kamal → dash}/configuration/validator/env.rb +2 -2
  116. data/lib/{kamal → dash}/configuration/validator/proxy.rb +31 -31
  117. data/lib/{kamal → dash}/configuration/validator/registry.rb +1 -1
  118. data/lib/{kamal → dash}/configuration/validator/role.rb +1 -1
  119. data/lib/{kamal → dash}/configuration/validator/servers.rb +1 -1
  120. data/lib/{kamal → dash}/configuration/validator.rb +4 -4
  121. data/lib/{kamal → dash}/configuration/volume.rb +2 -2
  122. data/lib/{kamal → dash}/configuration.rb +47 -37
  123. data/lib/{kamal → dash}/docker.rb +1 -1
  124. data/lib/{kamal → dash}/env_file.rb +1 -1
  125. data/lib/{kamal → dash}/git.rb +1 -1
  126. data/lib/{kamal → dash}/otel_shipper.rb +3 -3
  127. data/lib/{kamal → dash}/output/base_logger.rb +1 -1
  128. data/lib/{kamal → dash}/output/file_logger.rb +1 -1
  129. data/lib/{kamal → dash}/output/formatter.rb +1 -1
  130. data/lib/{kamal → dash}/output/otel_logger.rb +3 -3
  131. data/lib/dash/project_directory.rb +28 -0
  132. data/lib/{kamal → dash}/secrets/adapters/aws_secrets_manager.rb +1 -1
  133. data/lib/{kamal → dash}/secrets/adapters/base.rb +2 -2
  134. data/lib/{kamal → dash}/secrets/adapters/bitwarden.rb +1 -1
  135. data/lib/{kamal → dash}/secrets/adapters/bitwarden_secrets_manager.rb +1 -1
  136. data/lib/{kamal → dash}/secrets/adapters/doppler.rb +1 -1
  137. data/lib/{kamal → dash}/secrets/adapters/enpass.rb +1 -1
  138. data/lib/{kamal → dash}/secrets/adapters/gcp_secret_manager.rb +1 -1
  139. data/lib/{kamal → dash}/secrets/adapters/last_pass.rb +1 -1
  140. data/lib/{kamal → dash}/secrets/adapters/one_password.rb +2 -2
  141. data/lib/{kamal → dash}/secrets/adapters/passbolt.rb +1 -1
  142. data/lib/{kamal → dash}/secrets/adapters/test.rb +1 -1
  143. data/lib/{kamal → dash}/secrets/adapters.rb +2 -2
  144. data/lib/{kamal → dash}/secrets/dotenv/inline_command_substitution.rb +2 -2
  145. data/lib/{kamal → dash}/secrets.rb +6 -6
  146. data/lib/{kamal → dash}/tags.rb +8 -3
  147. data/lib/{kamal → dash}/utils/sensitive.rb +1 -1
  148. data/lib/{kamal → dash}/utils.rb +16 -6
  149. data/lib/dash/version.rb +3 -0
  150. data/lib/{kamal.rb → dash.rb} +4 -4
  151. metadata +157 -154
  152. data/lib/kamal/cli/alias/command.rb +0 -10
  153. data/lib/kamal/cli/build/clone.rb +0 -59
  154. data/lib/kamal/cli/healthcheck/error.rb +0 -2
  155. data/lib/kamal/cli/templates/sample_hooks/docker-setup.sample +0 -3
  156. data/lib/kamal/cli/templates/sample_hooks/post-app-boot.sample +0 -3
  157. data/lib/kamal/cli/templates/sample_hooks/post-app-stop.sample +0 -9
  158. data/lib/kamal/cli/templates/sample_hooks/post-deploy.sample +0 -14
  159. data/lib/kamal/cli/templates/sample_hooks/post-proxy-deploy.sample +0 -3
  160. data/lib/kamal/cli/templates/sample_hooks/post-proxy-reboot.sample +0 -3
  161. data/lib/kamal/cli/templates/sample_hooks/pre-app-boot.sample +0 -3
  162. data/lib/kamal/cli/templates/sample_hooks/pre-proxy-deploy.sample +0 -3
  163. data/lib/kamal/cli/templates/sample_hooks/pre-proxy-reboot.sample +0 -3
  164. data/lib/kamal/commands/docker.rb +0 -55
  165. data/lib/kamal/commands/proxy.rb +0 -266
  166. data/lib/kamal/commands/registry.rb +0 -38
  167. data/lib/kamal/commands.rb +0 -2
  168. data/lib/kamal/configuration/validator/configuration.rb +0 -6
  169. data/lib/kamal/version.rb +0 -3
  170. /data/lib/{kamal → dash}/configuration/docs/alias.yml +0 -0
  171. /data/lib/{kamal → dash}/configuration/docs/boot.yml +0 -0
  172. /data/lib/{kamal → dash}/configuration/docs/logging.yml +0 -0
  173. /data/lib/{kamal → dash}/configuration/docs/output.yml +0 -0
  174. /data/lib/{kamal → dash}/configuration/docs/role.yml +0 -0
  175. /data/lib/{kamal → dash}/configuration/docs/servers.yml +0 -0
  176. /data/lib/{kamal → dash}/configuration/docs/ssh.yml +0 -0
  177. /data/lib/{kamal → dash}/configuration/docs/sshkit.yml +0 -0
  178. /data/lib/{kamal → dash}/sshkit_with_ext.rb +0 -0
@@ -1,7 +1,7 @@
1
1
  require "thor"
2
- require "kamal/sshkit_with_ext"
2
+ require "dash/sshkit_with_ext"
3
3
 
4
- module Kamal::Cli
4
+ module Dash::Cli
5
5
  class Base < Thor
6
6
  include SSHKit::DSL
7
7
 
@@ -16,7 +16,13 @@ module Kamal::Cli
16
16
  HOOK_MUTEX = Mutex.new
17
17
 
18
18
  def self.exit_on_failure?() true end
19
- def self.dynamic_command_class() Kamal::Cli::Alias::Command end
19
+ def self.dynamic_command_class() Dash::Cli::Alias::Command end
20
+
21
+ # One legacy-project-directory deprecation notice per process. Tests reset it
22
+ # in CliTestCase, the same way they reset the DASH singleton.
23
+ class << self
24
+ attr_accessor :legacy_project_directory_warned
25
+ end
20
26
 
21
27
  class_option :verbose, type: :boolean, aliases: "-v", desc: "Detailed logging"
22
28
  class_option :quiet, type: :boolean, aliases: "-q", desc: "Minimal logging"
@@ -37,7 +43,7 @@ module Kamal::Cli
37
43
  class_option :lock_wait_interval, type: :numeric, default: 15, desc: "Seconds between deploy lock polls when --lock-wait is set"
38
44
 
39
45
  def initialize(args = [], local_options = {}, config = {})
40
- if config[:current_command].is_a?(Kamal::Cli::Alias::Command)
46
+ if config[:current_command].is_a?(Dash::Cli::Alias::Command)
41
47
  # When Thor generates a dynamic command, it doesn't attempt to parse the arguments.
42
48
  # For our purposes, it means the arguments are passed in args rather than local_options.
43
49
  super([], args, config)
@@ -45,36 +51,39 @@ module Kamal::Cli
45
51
  super
46
52
  end
47
53
 
48
- initialize_commander unless KAMAL.configured?
54
+ unless DASH.configured?
55
+ initialize_commander
56
+ warn_on_legacy_project_directory(config[:current_command]&.name)
57
+ end
49
58
  end
50
59
 
51
- # Public so collaborators like Kamal::Cli::App::Boot can fire hooks, but not a Thor command.
60
+ # Public so collaborators like Dash::Cli::App::Boot can fire hooks, but not a Thor command.
52
61
  no_commands do
53
62
  def run_hook(hook, **extra_details)
54
- if !options[:skip_hooks] && KAMAL.hook.hook_exists?(hook)
63
+ if !options[:skip_hooks] && DASH.hook.hook_exists?(hook)
55
64
  details = {
56
- hosts: KAMAL.hosts.join(","),
57
- roles: KAMAL.specific_roles&.join(","),
58
- lock: KAMAL.holding_lock?.to_s,
65
+ hosts: DASH.hosts.join(","),
66
+ roles: DASH.specific_roles&.join(","),
67
+ lock: DASH.holding_lock?.to_s,
59
68
  command: command,
60
69
  subcommand: subcommand
61
70
  }.compact
62
71
 
63
- hooks_output = KAMAL.config.hooks_output_for(hook)
72
+ hooks_output = DASH.config.hooks_output_for(hook)
64
73
 
65
74
  # CLI flags override config: -q hides all, -v shows all
66
75
  # Config setting :verbose forces output, :quiet forces silence
67
- hook_verbosity = if KAMAL.verbosity == :info && hooks_output
76
+ hook_verbosity = if DASH.verbosity == :info && hooks_output
68
77
  VERBOSITY.fetch(hooks_output)
69
78
  else
70
- KAMAL.verbosity
79
+ DASH.verbosity
71
80
  end
72
81
 
73
82
  HOOK_MUTEX.synchronize do
74
- with_env KAMAL.hook.env(**details, **extra_details) do
75
- KAMAL.with_verbosity(hook_verbosity) do
83
+ with_env DASH.hook.env(**details, **extra_details) do
84
+ DASH.with_verbosity(hook_verbosity) do
76
85
  run_locally do
77
- execute *KAMAL.hook.run(hook)
86
+ execute *DASH.hook.run(hook)
78
87
  end
79
88
  end
80
89
  rescue SSHKit::Command::Failed => e
@@ -90,8 +99,23 @@ module Kamal::Cli
90
99
  options.merge(@_initializer.last[:class_options] || {})
91
100
  end
92
101
 
102
+ # Process-scoped rather than commander-scoped: Dash::Cli::Alias::Command
103
+ # resets DASH and re-enters Dash::Cli::Main.start, so an aliased command
104
+ # builds a second commander and would otherwise warn twice. `dash migrate`
105
+ # is exempt - telling an operator to run the command they are running is noise.
106
+ def warn_on_legacy_project_directory(command_name)
107
+ return if command_name == "migrate"
108
+ return if Dash::Cli::Base.legacy_project_directory_warned
109
+ return unless Dash::ProjectDirectory.legacy?
110
+
111
+ Dash::Cli::Base.legacy_project_directory_warned = true
112
+
113
+ say "Using the legacy #{Dash::ProjectDirectory::LEGACY}/ project directory. Run `dash migrate` to move it to " \
114
+ "#{Dash::ProjectDirectory::CURRENT}/ (#{Dash::ProjectDirectory::LEGACY}/ support is removed in dash 5.0).", :yellow
115
+ end
116
+
93
117
  def initialize_commander
94
- KAMAL.tap do |commander|
118
+ DASH.tap do |commander|
95
119
  if options[:verbose]
96
120
  ENV["VERBOSE"] = "1" # For backtraces via cli/start
97
121
  commander.verbosity = VERBOSITY[:verbose]
@@ -128,7 +152,7 @@ module Kamal::Cli
128
152
  # Deploy lock outside, server lock inside. Every caller acquires in that
129
153
  # order, and deploy locks are unique per destination, so no cycle forms.
130
154
  def modify(lock: false, server_lock: false)
131
- KAMAL.modify(command: command, subcommand: subcommand) do
155
+ DASH.modify(command: command, subcommand: subcommand) do
132
156
  guarded = -> { server_lock ? with_server_lock { yield } : yield }
133
157
 
134
158
  lock ? with_lock(&guarded) : guarded.call
@@ -137,21 +161,21 @@ module Kamal::Cli
137
161
 
138
162
  def say(message = "", *)
139
163
  super unless options[:raw]
140
- KAMAL.log(message.to_s)
164
+ DASH.log(message.to_s)
141
165
  end
142
166
 
143
167
  # Raw output is written straight to stdout for piping, so silence SSHKit's
144
168
  # command echoing that would otherwise corrupt the byte stream.
145
169
  def with_raw_output(raw, &block)
146
- raw ? KAMAL.with_verbosity(:error, &block) : block.call
170
+ raw ? DASH.with_verbosity(:error, &block) : block.call
147
171
  end
148
172
 
149
- # kamal-proxy is one container per host, shared by every destination
173
+ # dash-proxy is one container per host, shared by every destination
150
174
  # deployed there, but the deploy lock is per-destination — so two
151
175
  # destinations deploying at once take different locks and both mutate the
152
176
  # same proxy. Anything touching the proxy takes this lock as well.
153
177
  def with_server_lock
154
- if KAMAL.holding_server_lock?
178
+ if DASH.holding_server_lock?
155
179
  yield
156
180
  else
157
181
  acquire_server_lock
@@ -173,8 +197,8 @@ module Kamal::Cli
173
197
  def acquire_server_lock
174
198
  ensure_run_directory
175
199
 
176
- timeout = KAMAL.lock_wait_timeout
177
- interval = KAMAL.lock_wait_interval
200
+ timeout = DASH.lock_wait_timeout
201
+ interval = DASH.lock_wait_interval
178
202
  deadline = Time.now + timeout
179
203
  details_shown = false
180
204
 
@@ -187,7 +211,7 @@ module Kamal::Cli
187
211
 
188
212
  begin
189
213
  server_lock_hosts.each do |host|
190
- execute_lock_acquire(AUTOMATIC_DEPLOY_LOCK_MESSAGE, lock: KAMAL.server_lock, hosts: host)
214
+ execute_lock_acquire(AUTOMATIC_DEPLOY_LOCK_MESSAGE, lock: DASH.server_lock, hosts: host)
191
215
  held << host
192
216
  end
193
217
 
@@ -200,7 +224,7 @@ module Kamal::Cli
200
224
  # That means the lock is free, not that anything went wrong, so
201
225
  # it must never escape as LockMissingError and fail the deploy.
202
226
  status = begin
203
- capture_lock_status(lock: KAMAL.server_lock, hosts: server_lock_hosts.first)
227
+ capture_lock_status(lock: DASH.server_lock, hosts: server_lock_hosts.first)
204
228
  rescue LockMissingError
205
229
  nil
206
230
  end
@@ -227,14 +251,14 @@ module Kamal::Cli
227
251
  end
228
252
  end
229
253
 
230
- KAMAL.holding_server_lock = true
254
+ DASH.holding_server_lock = true
231
255
  end
232
256
 
233
257
  def release_server_lock
234
258
  say "Releasing the server lock...", :magenta
235
259
  release_server_lock_on(server_lock_hosts)
236
260
 
237
- KAMAL.holding_server_lock = false
261
+ DASH.holding_server_lock = false
238
262
  end
239
263
 
240
264
  # Only ever called with hosts this process actually locked, so a missing
@@ -242,18 +266,18 @@ module Kamal::Cli
242
266
  # another deploy's lock.
243
267
  def release_server_lock_on(hosts)
244
268
  Array(hosts).each do |host|
245
- execute_lock_release(lock: KAMAL.server_lock, hosts: host)
269
+ execute_lock_release(lock: DASH.server_lock, hosts: host)
246
270
  rescue LockMissingError
247
271
  nil
248
272
  end
249
273
  end
250
274
 
251
275
  def server_lock_hosts
252
- KAMAL.proxy_hosts.presence || KAMAL.hosts
276
+ DASH.proxy_hosts.presence || DASH.hosts
253
277
  end
254
278
 
255
279
  def with_lock
256
- if KAMAL.holding_lock?
280
+ if DASH.holding_lock?
257
281
  yield
258
282
  else
259
283
  acquire_lock
@@ -286,7 +310,7 @@ module Kamal::Cli
286
310
  def acquire_lock
287
311
  ensure_run_directory
288
312
 
289
- if KAMAL.lock_wait
313
+ if DASH.lock_wait
290
314
  acquire_lock_with_wait
291
315
  else
292
316
  raise_if_locked do
@@ -295,12 +319,12 @@ module Kamal::Cli
295
319
  end
296
320
  end
297
321
 
298
- KAMAL.holding_lock = true
322
+ DASH.holding_lock = true
299
323
  end
300
324
 
301
325
  def acquire_lock_with_wait
302
- timeout = KAMAL.lock_wait_timeout
303
- interval = KAMAL.lock_wait_interval
326
+ timeout = DASH.lock_wait_timeout
327
+ interval = DASH.lock_wait_interval
304
328
  deadline = Time.now + timeout
305
329
  details_shown = false
306
330
 
@@ -338,7 +362,7 @@ module Kamal::Cli
338
362
  say "Releasing the deploy lock...", :magenta
339
363
  execute_lock_release
340
364
 
341
- KAMAL.holding_lock = false
365
+ DASH.holding_lock = false
342
366
  end
343
367
 
344
368
  def raise_if_locked
@@ -349,21 +373,21 @@ module Kamal::Cli
349
373
  raise LockError, "Deploy lock found. Run 'dash lock help' for more information"
350
374
  end
351
375
 
352
- def execute_lock_acquire(message, lock: KAMAL.lock, hosts: KAMAL.primary_host)
353
- on(hosts) { execute *lock.acquire(message, KAMAL.config.version), verbosity: :debug }
376
+ def execute_lock_acquire(message, lock: DASH.lock, hosts: DASH.primary_host)
377
+ on(hosts) { execute *lock.acquire(message, DASH.config.version), verbosity: :debug }
354
378
  rescue SSHKit::Runner::ExecuteError => e
355
379
  raise LockHeldError if e.message =~ /cannot create directory/
356
380
  raise
357
381
  end
358
382
 
359
- def execute_lock_release(lock: KAMAL.lock, hosts: KAMAL.primary_host)
383
+ def execute_lock_release(lock: DASH.lock, hosts: DASH.primary_host)
360
384
  on(hosts) { execute *lock.release, verbosity: :debug }
361
385
  rescue SSHKit::Runner::ExecuteError => e
362
386
  raise LockMissingError if e.message =~ /No such file or directory/
363
387
  raise
364
388
  end
365
389
 
366
- def capture_lock_status(lock: KAMAL.lock, hosts: KAMAL.primary_host)
390
+ def capture_lock_status(lock: DASH.lock, hosts: DASH.primary_host)
367
391
  status = nil
368
392
  on(hosts) { status = capture_with_debug(*lock.status) }
369
393
  status
@@ -379,19 +403,19 @@ module Kamal::Cli
379
403
  end
380
404
 
381
405
  def pre_connect_if_required
382
- if !KAMAL.connected?
406
+ if !DASH.connected?
383
407
  run_hook "pre-connect", secrets: true unless options[:skip_hooks]
384
- KAMAL.connected = true
408
+ DASH.connected = true
385
409
  end
386
410
  end
387
411
 
388
412
  def command
389
413
  @kamal_command ||= begin
390
414
  invocation_class, invocation_commands = *first_invocation
391
- if invocation_class == Kamal::Cli::Main
415
+ if invocation_class == Dash::Cli::Main
392
416
  invocation_commands[0]
393
417
  else
394
- Kamal::Cli::Main.subcommand_classes.find { |command, clazz| clazz == invocation_class }[0]
418
+ Dash::Cli::Main.subcommand_classes.find { |command, clazz| clazz == invocation_class }[0]
395
419
  end
396
420
  end
397
421
  end
@@ -399,7 +423,7 @@ module Kamal::Cli
399
423
  def subcommand
400
424
  @kamal_subcommand ||= begin
401
425
  invocation_class, invocation_commands = *first_invocation
402
- invocation_commands[0] if invocation_class != Kamal::Cli::Main
426
+ invocation_commands[0] if invocation_class != Dash::Cli::Main
403
427
  end
404
428
  end
405
429
 
@@ -412,8 +436,8 @@ module Kamal::Cli
412
436
  end
413
437
 
414
438
  def ensure_run_directory
415
- on(KAMAL.hosts) do
416
- execute(*KAMAL.server.ensure_run_directory)
439
+ on(DASH.hosts) do
440
+ execute(*DASH.server.ensure_run_directory)
417
441
  end
418
442
  end
419
443
 
@@ -429,7 +453,7 @@ module Kamal::Cli
429
453
  def ensure_docker_installed
430
454
  run_locally do
431
455
  begin
432
- execute *KAMAL.builder.ensure_docker_installed
456
+ execute *DASH.builder.ensure_docker_installed
433
457
  rescue SSHKit::Command::Failed => e
434
458
  error = e.message =~ /command not found/ ?
435
459
  "Docker is not installed locally" :
@@ -0,0 +1,59 @@
1
+ class Dash::Cli::Build::Clone
2
+ attr_reader :sshkit
3
+ delegate :info, :error, :execute, :capture_with_info, to: :sshkit
4
+
5
+ def initialize(sshkit)
6
+ @sshkit = sshkit
7
+ end
8
+
9
+ def prepare
10
+ begin
11
+ clone_repo
12
+ rescue SSHKit::Command::Failed => e
13
+ if e.message =~ /already exists and is not an empty directory/
14
+ reset
15
+ else
16
+ raise Dash::Cli::Build::BuildError, "Failed to clone repo: #{e.message}"
17
+ end
18
+ end
19
+
20
+ validate!
21
+ rescue Dash::Cli::Build::BuildError => e
22
+ error "Error preparing clone: #{e.message}, deleting and retrying..."
23
+
24
+ FileUtils.rm_rf DASH.config.builder.clone_directory
25
+ clone_repo
26
+ validate!
27
+ end
28
+
29
+ private
30
+ def clone_repo
31
+ info "Cloning repo into build directory `#{DASH.config.builder.build_directory}`..."
32
+
33
+ FileUtils.mkdir_p DASH.config.builder.clone_directory
34
+ execute *DASH.builder.clone
35
+ end
36
+
37
+ def reset
38
+ info "Resetting local clone as `#{DASH.config.builder.build_directory}` already exists..."
39
+
40
+ DASH.builder.clone_reset_steps.each { |step| execute *step }
41
+ rescue SSHKit::Command::Failed => e
42
+ raise Dash::Cli::Build::BuildError, "Failed to clone repo: #{e.message}"
43
+ end
44
+
45
+ def validate!
46
+ status = capture_with_info(*DASH.builder.clone_status).strip
47
+
48
+ unless status.empty?
49
+ raise Dash::Cli::Build::BuildError, "Clone in #{DASH.config.builder.build_directory} is dirty, #{status}"
50
+ end
51
+
52
+ revision = capture_with_info(*DASH.builder.clone_revision).strip
53
+ if revision != Dash::Git.revision
54
+ raise Dash::Cli::Build::BuildError, "Clone in #{DASH.config.builder.build_directory} is not on the correct revision, expected `#{Dash::Git.revision}` but got `#{revision}`"
55
+ end
56
+ rescue SSHKit::Command::Failed => e
57
+ raise Dash::Cli::Build::BuildError, "Failed to validate clone: #{e.message}"
58
+ end
59
+ end
@@ -1,6 +1,6 @@
1
1
  require "concurrent/atomic/count_down_latch"
2
2
 
3
- class Kamal::Cli::Build::PortForwarding
3
+ class Dash::Cli::Build::PortForwarding
4
4
  attr_reader :hosts, :port, :ssh_options
5
5
 
6
6
  def initialize(hosts, port, **ssh_options)
@@ -1,4 +1,4 @@
1
- class Kamal::Cli::Build < Kamal::Cli::Base
1
+ class Dash::Cli::Build < Dash::Cli::Base
2
2
  class BuildError < StandardError; end
3
3
 
4
4
  desc "deliver", "Build app and push app image to registry then pull image on servers"
@@ -18,14 +18,14 @@ class Kamal::Cli::Build < Kamal::Cli::Base
18
18
  pre_connect_if_required
19
19
 
20
20
  ensure_docker_installed
21
- setup_local_registry if KAMAL.registry.local?
22
- login_to_registry_locally unless KAMAL.registry.local?
21
+ setup_local_registry if DASH.registry.local?
22
+ login_to_registry_locally unless DASH.registry.local?
23
23
 
24
24
  run_hook "pre-build"
25
25
 
26
- uncommitted_changes = Kamal::Git.uncommitted_changes
26
+ uncommitted_changes = Dash::Git.uncommitted_changes
27
27
 
28
- if KAMAL.config.builder.git_clone?
28
+ if DASH.config.builder.git_clone?
29
29
  if uncommitted_changes.present?
30
30
  say "Building from a local git clone, so ignoring these uncommitted changes:\n #{uncommitted_changes}", :yellow
31
31
  end
@@ -38,10 +38,10 @@ class Kamal::Cli::Build < Kamal::Cli::Base
38
38
  end
39
39
 
40
40
  forward_local_registry_port_for_remote_builder do
41
- with_env(KAMAL.config.builder.secrets) do
41
+ with_env(DASH.config.builder.secrets) do
42
42
  run_locally do
43
43
  begin
44
- execute *KAMAL.builder.inspect_builder
44
+ execute *DASH.builder.inspect_builder
45
45
  rescue SSHKit::Command::Failed => e
46
46
  if e.message =~ /(context not found|no builder|no compatible builder|does not exist)/
47
47
  warn "Missing compatible builder, so creating a new one first"
@@ -57,10 +57,10 @@ class Kamal::Cli::Build < Kamal::Cli::Base
57
57
  end
58
58
 
59
59
  # Get the command here to ensure the Dir.chdir doesn't interfere with it
60
- push = KAMAL.builder.push(cli.options[:output], no_cache: cli.options[:no_cache])
60
+ push = DASH.builder.push(cli.options[:output], no_cache: cli.options[:no_cache])
61
61
 
62
- KAMAL.with_verbosity(:debug) do
63
- Dir.chdir(KAMAL.config.builder.build_directory) { execute *push, env: KAMAL.builder.push_env }
62
+ DASH.with_verbosity(:debug) do
63
+ Dir.chdir(DASH.config.builder.build_directory) { execute *push, env: DASH.builder.push_env }
64
64
  end
65
65
  end
66
66
  end
@@ -69,31 +69,31 @@ class Kamal::Cli::Build < Kamal::Cli::Base
69
69
 
70
70
  desc "pull", "Pull app image from registry onto servers"
71
71
  def pull
72
- login_to_registry_remotely unless KAMAL.registry.local?
72
+ login_to_registry_remotely unless DASH.registry.local?
73
73
 
74
- forward_local_registry_port(KAMAL.hosts, **KAMAL.config.ssh.options) do
74
+ forward_local_registry_port(DASH.hosts, **DASH.config.ssh.options) do
75
75
  if (first_hosts = mirror_hosts).any?
76
76
  #  Pull on a single host per mirror first to seed them
77
77
  say "Pulling image on #{first_hosts.join(", ")} to seed the #{"mirror".pluralize(first_hosts.count)}...", :magenta
78
78
  pull_on_hosts(first_hosts)
79
79
  say "Pulling image on remaining hosts...", :magenta
80
- pull_on_hosts(KAMAL.app_hosts - first_hosts)
80
+ pull_on_hosts(DASH.app_hosts - first_hosts)
81
81
  else
82
- pull_on_hosts(KAMAL.app_hosts)
82
+ pull_on_hosts(DASH.app_hosts)
83
83
  end
84
84
  end
85
85
  end
86
86
 
87
87
  desc "create", "Create a build setup"
88
88
  def create
89
- if (remote_host = KAMAL.config.builder.remote)
89
+ if (remote_host = DASH.config.builder.remote)
90
90
  connect_to_remote_host(remote_host)
91
91
  end
92
92
 
93
93
  run_locally do
94
94
  begin
95
- debug "Using builder: #{KAMAL.builder.name}"
96
- execute *KAMAL.builder.create
95
+ debug "Using builder: #{DASH.builder.name}"
96
+ execute *DASH.builder.create
97
97
  rescue SSHKit::Command::Failed => e
98
98
  if e.message =~ /stderr=(.*)/
99
99
  error "Couldn't create remote builder: #{$1}"
@@ -108,16 +108,16 @@ class Kamal::Cli::Build < Kamal::Cli::Base
108
108
  desc "remove", "Remove build setup"
109
109
  def remove
110
110
  run_locally do
111
- debug "Using builder: #{KAMAL.builder.name}"
112
- execute *KAMAL.builder.remove
111
+ debug "Using builder: #{DASH.builder.name}"
112
+ execute *DASH.builder.remove
113
113
  end
114
114
  end
115
115
 
116
116
  desc "details", "Show build setup"
117
117
  def details
118
118
  run_locally do
119
- puts "Builder: #{KAMAL.builder.name}"
120
- puts capture(*KAMAL.builder.info)
119
+ puts "Builder: #{DASH.builder.name}"
120
+ puts capture(*DASH.builder.info)
121
121
  end
122
122
  end
123
123
 
@@ -129,9 +129,9 @@ class Kamal::Cli::Build < Kamal::Cli::Base
129
129
 
130
130
  ensure_docker_installed
131
131
 
132
- docker_included_files = Set.new(Kamal::Docker.included_files)
133
- git_uncommitted_files = Set.new(Kamal::Git.uncommitted_files)
134
- git_untracked_files = Set.new(Kamal::Git.untracked_files)
132
+ docker_included_files = Set.new(Dash::Docker.included_files)
133
+ git_uncommitted_files = Set.new(Dash::Git.uncommitted_files)
134
+ git_untracked_files = Set.new(Dash::Git.untracked_files)
135
135
 
136
136
  docker_uncommitted_files = docker_included_files & git_uncommitted_files
137
137
  if docker_uncommitted_files.any?
@@ -147,10 +147,10 @@ class Kamal::Cli::Build < Kamal::Cli::Base
147
147
  say
148
148
  end
149
149
 
150
- with_env(KAMAL.config.builder.secrets) do
150
+ with_env(DASH.config.builder.secrets) do
151
151
  run_locally do
152
- build = KAMAL.builder.push(cli.options[:output], tag_as_dirty: true, no_cache: cli.options[:no_cache])
153
- KAMAL.with_verbosity(:debug) do
152
+ build = DASH.builder.push(cli.options[:output], tag_as_dirty: true, no_cache: cli.options[:no_cache])
153
+ DASH.with_verbosity(:debug) do
154
154
  execute(*build)
155
155
  end
156
156
  end
@@ -172,10 +172,10 @@ class Kamal::Cli::Build < Kamal::Cli::Base
172
172
  end
173
173
 
174
174
  def mirror_hosts
175
- if KAMAL.app_hosts.many?
175
+ if DASH.app_hosts.many?
176
176
  mirror_hosts = Concurrent::Hash.new
177
- on(KAMAL.app_hosts) do |host|
178
- first_mirror = capture_with_info(*KAMAL.builder.first_mirror).strip.presence
177
+ on(DASH.app_hosts) do |host|
178
+ first_mirror = capture_with_info(*DASH.builder.first_mirror).strip.presence
179
179
  mirror_hosts[first_mirror] ||= host.to_s if first_mirror
180
180
  rescue SSHKit::Command::Failed => e
181
181
  raise unless e.message =~ /error calling index: reflect: slice index out of range/
@@ -188,34 +188,34 @@ class Kamal::Cli::Build < Kamal::Cli::Base
188
188
 
189
189
  def pull_on_hosts(hosts)
190
190
  on(hosts) do
191
- execute *KAMAL.auditor.record("Pulled image with version #{KAMAL.config.version}"), verbosity: :debug
192
- execute *KAMAL.builder.clean, raise_on_non_zero_exit: false
193
- execute *KAMAL.builder.pull
194
- execute *KAMAL.builder.validate_image
191
+ execute *DASH.auditor.record("Pulled image with version #{DASH.config.version}"), verbosity: :debug
192
+ execute *DASH.builder.clean, raise_on_non_zero_exit: false
193
+ execute *DASH.builder.pull
194
+ execute *DASH.builder.validate_image
195
195
  end
196
196
  end
197
197
 
198
198
  def setup_local_registry
199
199
  run_locally do
200
- execute *KAMAL.registry.setup
200
+ execute *DASH.registry.setup
201
201
  end
202
202
  end
203
203
 
204
204
  def login_to_registry_locally
205
205
  run_locally do
206
- execute *KAMAL.registry.login
206
+ execute *DASH.registry.login
207
207
  end
208
208
  end
209
209
 
210
210
  def login_to_registry_remotely
211
- on(KAMAL.app_hosts) do
212
- execute *KAMAL.registry.login
211
+ on(DASH.app_hosts) do
212
+ execute *DASH.registry.login
213
213
  end
214
214
  end
215
215
 
216
216
  def forward_local_registry_port_for_remote_builder(&block)
217
- if KAMAL.builder.remote?
218
- remote_uri = URI(KAMAL.config.builder.remote)
217
+ if DASH.builder.remote?
218
+ remote_uri = URI(DASH.config.builder.remote)
219
219
  forward_local_registry_port([ remote_uri.host ], **remote_builder_ssh_options(remote_uri), &block)
220
220
  else
221
221
  yield
@@ -223,9 +223,9 @@ class Kamal::Cli::Build < Kamal::Cli::Base
223
223
  end
224
224
 
225
225
  def forward_local_registry_port(hosts, **ssh_options, &block)
226
- if KAMAL.config.registry.local?
226
+ if DASH.config.registry.local?
227
227
  say "Setting up local registry port forwarding to #{hosts.join(', ')}..."
228
- PortForwarding.new(hosts, KAMAL.config.registry.local_port, **ssh_options).forward(&block)
228
+ PortForwarding.new(hosts, DASH.config.registry.local_port, **ssh_options).forward(&block)
229
229
  else
230
230
  yield
231
231
  end
@@ -234,9 +234,9 @@ class Kamal::Cli::Build < Kamal::Cli::Base
234
234
  def remote_builder_ssh_options(remote_uri)
235
235
  { user: remote_uri.user,
236
236
  port: remote_uri.port,
237
- keepalive: KAMAL.config.ssh.options[:keepalive],
238
- keepalive_interval: KAMAL.config.ssh.options[:keepalive_interval],
239
- logger: KAMAL.config.ssh.options[:logger]
237
+ keepalive: DASH.config.ssh.options[:keepalive],
238
+ keepalive_interval: DASH.config.ssh.options[:keepalive_interval],
239
+ logger: DASH.config.ssh.options[:logger]
240
240
  }.compact
241
241
  end
242
242
  end
@@ -1,17 +1,17 @@
1
1
  # Checks that only read the configuration — no SSH, no network. They report problems
2
2
  # that are visible in deploy.yml alone, so they still run when every host is unreachable.
3
- class Kamal::Cli::Doctor::ConfigChecks
3
+ class Dash::Cli::Doctor::ConfigChecks
4
4
  def run
5
5
  readiness_results
6
6
  end
7
7
 
8
8
  private
9
9
  def result(check, target, status, detail)
10
- Kamal::Cli::Doctor::Result.new(check, target, status, detail)
10
+ Dash::Cli::Doctor::Result.new(check, target, status, detail)
11
11
  end
12
12
 
13
13
  def readiness_results
14
- KAMAL.roles.map { |role| readiness_check(role) }
14
+ DASH.roles.map { |role| readiness_check(role) }
15
15
  end
16
16
 
17
17
  def readiness_check(role)