dash 3.1.5 → 3.2.1

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 (177) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +26 -6
  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 +15 -15
  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 +73 -49
  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 +25 -7
  18. data/lib/{kamal → dash}/cli/doctor/host_checks.rb +23 -23
  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 +87 -76
  27. data/lib/{kamal → dash}/cli/proxy/drift.rb +4 -4
  28. data/lib/{kamal → dash}/cli/proxy/loadbalancer_claim.rb +6 -6
  29. data/lib/{kamal → dash}/cli/proxy/loadbalancer_reboot.rb +23 -23
  30. data/lib/{kamal → dash}/cli/proxy/reboot.rb +15 -15
  31. data/lib/{kamal → dash}/cli/proxy.rb +172 -160
  32. data/lib/{kamal → dash}/cli/prune.rb +10 -10
  33. data/lib/{kamal → dash}/cli/registry.rb +13 -13
  34. data/lib/{kamal → dash}/cli/secrets.rb +3 -3
  35. data/lib/{kamal → dash}/cli/server.rb +15 -15
  36. data/lib/{kamal → dash}/cli/templates/deploy.yml +6 -6
  37. data/lib/dash/cli/templates/sample_hooks/docker-setup.sample +3 -0
  38. data/lib/dash/cli/templates/sample_hooks/post-app-boot.sample +3 -0
  39. data/lib/dash/cli/templates/sample_hooks/post-app-stop.sample +9 -0
  40. data/lib/dash/cli/templates/sample_hooks/post-deploy.sample +14 -0
  41. data/lib/dash/cli/templates/sample_hooks/post-proxy-deploy.sample +3 -0
  42. data/lib/dash/cli/templates/sample_hooks/post-proxy-reboot.sample +3 -0
  43. data/lib/dash/cli/templates/sample_hooks/pre-app-boot.sample +3 -0
  44. data/lib/{kamal → dash}/cli/templates/sample_hooks/pre-app-stop.sample +2 -2
  45. data/lib/{kamal → dash}/cli/templates/sample_hooks/pre-build.sample +8 -8
  46. data/lib/{kamal → dash}/cli/templates/sample_hooks/pre-connect.sample +8 -8
  47. data/lib/{kamal → dash}/cli/templates/sample_hooks/pre-deploy.sample +9 -9
  48. data/lib/dash/cli/templates/sample_hooks/pre-proxy-deploy.sample +3 -0
  49. data/lib/dash/cli/templates/sample_hooks/pre-proxy-reboot.sample +3 -0
  50. data/lib/dash/cli/templates/secrets +22 -0
  51. data/lib/{kamal → dash}/cli.rb +2 -2
  52. data/lib/{kamal → dash}/commander/specifics.rb +2 -2
  53. data/lib/{kamal → dash}/commander.rb +31 -23
  54. data/lib/{kamal → dash}/commands/accessory/proxy.rb +1 -1
  55. data/lib/{kamal → dash}/commands/accessory.rb +2 -2
  56. data/lib/{kamal → dash}/commands/app/assets.rb +1 -1
  57. data/lib/{kamal → dash}/commands/app/containers.rb +1 -1
  58. data/lib/{kamal → dash}/commands/app/error_pages.rb +2 -2
  59. data/lib/{kamal → dash}/commands/app/execution.rb +1 -1
  60. data/lib/{kamal → dash}/commands/app/images.rb +1 -1
  61. data/lib/{kamal → dash}/commands/app/logging.rb +1 -1
  62. data/lib/{kamal → dash}/commands/app/proxy.rb +1 -1
  63. data/lib/{kamal → dash}/commands/app.rb +1 -1
  64. data/lib/{kamal → dash}/commands/auditor.rb +3 -7
  65. data/lib/{kamal → dash}/commands/base.rb +39 -3
  66. data/lib/{kamal → dash}/commands/builder/base.rb +2 -2
  67. data/lib/{kamal → dash}/commands/builder/clone.rb +3 -3
  68. data/lib/{kamal → dash}/commands/builder/cloud.rb +1 -1
  69. data/lib/{kamal → dash}/commands/builder/hybrid.rb +1 -1
  70. data/lib/{kamal → dash}/commands/builder/local.rb +1 -1
  71. data/lib/{kamal → dash}/commands/builder/pack.rb +1 -1
  72. data/lib/{kamal → dash}/commands/builder/remote.rb +1 -1
  73. data/lib/{kamal → dash}/commands/builder.rb +7 -7
  74. data/lib/{kamal → dash}/commands/docker.rb +1 -1
  75. data/lib/{kamal → dash}/commands/hook.rb +1 -1
  76. data/lib/{kamal → dash}/commands/loadbalancer.rb +9 -8
  77. data/lib/{kamal → dash}/commands/lock.rb +2 -2
  78. data/lib/{kamal → dash}/commands/proxy/cert_transfer.rb +3 -3
  79. data/lib/{kamal → dash}/commands/proxy.rb +20 -10
  80. data/lib/{kamal → dash}/commands/prune.rb +1 -1
  81. data/lib/dash/commands/registry.rb +44 -0
  82. data/lib/{kamal → dash}/commands/server.rb +1 -5
  83. data/lib/dash/commands.rb +2 -0
  84. data/lib/{kamal → dash}/configuration/accessory.rb +11 -11
  85. data/lib/{kamal → dash}/configuration/alias.rb +3 -3
  86. data/lib/{kamal → dash}/configuration/boot.rb +2 -2
  87. data/lib/{kamal → dash}/configuration/builder.rb +7 -7
  88. data/lib/{kamal → dash}/configuration/docs/accessory.yml +6 -6
  89. data/lib/{kamal → dash}/configuration/docs/alias.yml +2 -2
  90. data/lib/{kamal → dash}/configuration/docs/boot.yml +1 -1
  91. data/lib/{kamal → dash}/configuration/docs/builder.yml +3 -3
  92. data/lib/{kamal → dash}/configuration/docs/configuration.yml +25 -18
  93. data/lib/{kamal → dash}/configuration/docs/env.yml +17 -17
  94. data/lib/{kamal → dash}/configuration/docs/proxy.yml +53 -30
  95. data/lib/{kamal → dash}/configuration/docs/registry.yml +6 -6
  96. data/lib/{kamal → dash}/configuration/docs/role.yml +1 -1
  97. data/lib/{kamal → dash}/configuration/docs/servers.yml +2 -2
  98. data/lib/{kamal → dash}/configuration/env/tag.rb +2 -2
  99. data/lib/{kamal → dash}/configuration/env.rb +5 -5
  100. data/lib/{kamal → dash}/configuration/loadbalancer.rb +3 -3
  101. data/lib/{kamal → dash}/configuration/logging.rb +3 -3
  102. data/lib/{kamal → dash}/configuration/output.rb +4 -4
  103. data/lib/{kamal → dash}/configuration/proxy/acme.rb +4 -3
  104. data/lib/{kamal → dash}/configuration/proxy/boot.rb +10 -8
  105. data/lib/{kamal → dash}/configuration/proxy/run.rb +14 -14
  106. data/lib/{kamal → dash}/configuration/proxy.rb +16 -16
  107. data/lib/{kamal → dash}/configuration/registry.rb +3 -3
  108. data/lib/{kamal → dash}/configuration/role/healthcheck.rb +3 -3
  109. data/lib/{kamal → dash}/configuration/role.rb +13 -13
  110. data/lib/{kamal → dash}/configuration/servers.rb +4 -4
  111. data/lib/{kamal → dash}/configuration/ssh.rb +3 -3
  112. data/lib/{kamal → dash}/configuration/sshkit.rb +2 -2
  113. data/lib/{kamal → dash}/configuration/validation.rb +2 -2
  114. data/lib/{kamal → dash}/configuration/validator/accessory.rb +1 -1
  115. data/lib/{kamal → dash}/configuration/validator/alias.rb +2 -2
  116. data/lib/{kamal → dash}/configuration/validator/builder.rb +1 -1
  117. data/lib/dash/configuration/validator/configuration.rb +6 -0
  118. data/lib/{kamal → dash}/configuration/validator/env.rb +2 -2
  119. data/lib/{kamal → dash}/configuration/validator/proxy.rb +8 -8
  120. data/lib/{kamal → dash}/configuration/validator/registry.rb +1 -1
  121. data/lib/{kamal → dash}/configuration/validator/role.rb +1 -1
  122. data/lib/{kamal → dash}/configuration/validator/servers.rb +1 -1
  123. data/lib/{kamal → dash}/configuration/validator.rb +4 -4
  124. data/lib/{kamal → dash}/configuration/volume.rb +2 -2
  125. data/lib/{kamal → dash}/configuration.rb +40 -30
  126. data/lib/{kamal → dash}/docker.rb +1 -1
  127. data/lib/{kamal → dash}/env_file.rb +1 -1
  128. data/lib/{kamal → dash}/git.rb +1 -1
  129. data/lib/{kamal → dash}/otel_shipper.rb +3 -3
  130. data/lib/{kamal → dash}/output/base_logger.rb +1 -1
  131. data/lib/{kamal → dash}/output/file_logger.rb +1 -1
  132. data/lib/{kamal → dash}/output/formatter.rb +1 -1
  133. data/lib/{kamal → dash}/output/otel_logger.rb +3 -3
  134. data/lib/dash/project_directory.rb +28 -0
  135. data/lib/{kamal → dash}/secrets/adapters/aws_secrets_manager.rb +1 -1
  136. data/lib/{kamal → dash}/secrets/adapters/base.rb +2 -2
  137. data/lib/{kamal → dash}/secrets/adapters/bitwarden.rb +1 -1
  138. data/lib/{kamal → dash}/secrets/adapters/bitwarden_secrets_manager.rb +1 -1
  139. data/lib/{kamal → dash}/secrets/adapters/doppler.rb +1 -1
  140. data/lib/{kamal → dash}/secrets/adapters/enpass.rb +3 -3
  141. data/lib/{kamal → dash}/secrets/adapters/gcp_secret_manager.rb +1 -1
  142. data/lib/{kamal → dash}/secrets/adapters/last_pass.rb +1 -1
  143. data/lib/{kamal → dash}/secrets/adapters/one_password.rb +2 -2
  144. data/lib/{kamal → dash}/secrets/adapters/passbolt.rb +1 -1
  145. data/lib/{kamal → dash}/secrets/adapters/test.rb +1 -1
  146. data/lib/{kamal → dash}/secrets/adapters.rb +2 -2
  147. data/lib/{kamal → dash}/secrets/dotenv/inline_command_substitution.rb +5 -3
  148. data/lib/{kamal → dash}/secrets.rb +6 -6
  149. data/lib/{kamal → dash}/tags.rb +8 -3
  150. data/lib/{kamal → dash}/utils/sensitive.rb +1 -1
  151. data/lib/{kamal → dash}/utils.rb +15 -5
  152. data/lib/dash/version.rb +3 -0
  153. data/lib/{kamal.rb → dash.rb} +5 -5
  154. metadata +171 -216
  155. data/bin/kamal +0 -18
  156. data/lib/kamal/cli/alias/command.rb +0 -10
  157. data/lib/kamal/cli/build/clone.rb +0 -59
  158. data/lib/kamal/cli/healthcheck/error.rb +0 -2
  159. data/lib/kamal/cli/templates/sample_hooks/docker-setup.sample +0 -3
  160. data/lib/kamal/cli/templates/sample_hooks/post-app-boot.sample +0 -3
  161. data/lib/kamal/cli/templates/sample_hooks/post-app-stop.sample +0 -9
  162. data/lib/kamal/cli/templates/sample_hooks/post-deploy.sample +0 -14
  163. data/lib/kamal/cli/templates/sample_hooks/post-proxy-deploy.sample +0 -3
  164. data/lib/kamal/cli/templates/sample_hooks/post-proxy-reboot.sample +0 -3
  165. data/lib/kamal/cli/templates/sample_hooks/pre-app-boot.sample +0 -3
  166. data/lib/kamal/cli/templates/sample_hooks/pre-proxy-deploy.sample +0 -3
  167. data/lib/kamal/cli/templates/sample_hooks/pre-proxy-reboot.sample +0 -3
  168. data/lib/kamal/cli/templates/secrets +0 -22
  169. data/lib/kamal/commands/registry.rb +0 -38
  170. data/lib/kamal/commands.rb +0 -2
  171. data/lib/kamal/configuration/validator/configuration.rb +0 -6
  172. data/lib/kamal/version.rb +0 -3
  173. /data/lib/{kamal → dash}/configuration/docs/logging.yml +0 -0
  174. /data/lib/{kamal → dash}/configuration/docs/output.yml +0 -0
  175. /data/lib/{kamal → dash}/configuration/docs/ssh.yml +0 -0
  176. /data/lib/{kamal → dash}/configuration/docs/sshkit.yml +0 -0
  177. /data/lib/{kamal → dash}/sshkit_with_ext.rb +0 -0
@@ -1,4 +1,4 @@
1
- class Kamal::Configuration::Validator::Registry < Kamal::Configuration::Validator
1
+ class Dash::Configuration::Validator::Registry < Dash::Configuration::Validator
2
2
  STRING_OR_ONE_ITEM_ARRAY_KEYS = [ "username", "password" ]
3
3
 
4
4
  def validate!
@@ -1,4 +1,4 @@
1
- class Kamal::Configuration::Validator::Role < Kamal::Configuration::Validator
1
+ class Dash::Configuration::Validator::Role < Dash::Configuration::Validator
2
2
  def validate!
3
3
  validate_type! config, Array, Hash
4
4
 
@@ -1,4 +1,4 @@
1
- class Kamal::Configuration::Validator::Servers < Kamal::Configuration::Validator
1
+ class Dash::Configuration::Validator::Servers < Dash::Configuration::Validator
2
2
  def validate!
3
3
  validate_type! config, Array, Hash, NilClass
4
4
 
@@ -1,4 +1,4 @@
1
- class Kamal::Configuration::Validator
1
+ class Dash::Configuration::Validator
2
2
  attr_reader :config, :example, :context
3
3
 
4
4
  def initialize(config, example:, context:)
@@ -91,7 +91,7 @@ class Kamal::Configuration::Validator
91
91
  else
92
92
  validate_type! value, type
93
93
  end
94
- rescue Kamal::ConfigurationError
94
+ rescue Dash::ConfigurationError
95
95
  type_error(Array, type)
96
96
  end
97
97
 
@@ -187,7 +187,7 @@ class Kamal::Configuration::Validator
187
187
  end
188
188
 
189
189
  def error(message)
190
- raise Kamal::ConfigurationError, "#{error_context}#{message}"
190
+ raise Dash::ConfigurationError, "#{error_context}#{message}"
191
191
  end
192
192
 
193
193
  def type_error(*expected_types)
@@ -245,7 +245,7 @@ class Kamal::Configuration::Validator
245
245
  validate_health_option_expansion!(options)
246
246
  end
247
247
 
248
- # Kamal::Utils::DOLLAR_SIGN_WITHOUT_SHELL_EXPANSION_REGEX escapes a bare `$` but exempts
248
+ # Dash::Utils::DOLLAR_SIGN_WITHOUT_SHELL_EXPANSION_REGEX escapes a bare `$` but exempts
249
249
  # `${...}`, leaving it for the deploy host's shell to expand at docker run time. Role env
250
250
  # never reaches that shell, so `${SOME_ENV}` in a health command silently becomes empty and
251
251
  # the container sits `starting` until deploy_timeout. Reject it where it is most likely written.
@@ -1,6 +1,6 @@
1
- class Kamal::Configuration::Volume
1
+ class Dash::Configuration::Volume
2
2
  attr_reader :host_path, :container_path, :options
3
- delegate :argumentize, to: Kamal::Utils
3
+ delegate :argumentize, to: Dash::Utils
4
4
 
5
5
  def initialize(host_path:, container_path:, options: nil)
6
6
  @host_path = host_path
@@ -5,11 +5,15 @@ require "active_support/core_ext/hash/keys"
5
5
  require "erb"
6
6
  require "net/ssh/proxy/jump"
7
7
 
8
- class Kamal::Configuration
8
+ class Dash::Configuration
9
9
  HOOKS_OUTPUT_LEVELS = [ :quiet, :verbose ].freeze
10
10
 
11
+ # The pre-3b name of #run_directory. Referenced only by the one-shot host
12
+ # migration in Dash::Commands::Base; nothing reads paths under it.
13
+ LEGACY_RUN_DIRECTORY = ".kamal"
14
+
11
15
  delegate :service, :labels, :hooks_path, to: :raw_config, allow_nil: true
12
- delegate :argumentize, :optionize, to: Kamal::Utils
16
+ delegate :argumentize, :optionize, to: Dash::Utils
13
17
 
14
18
  attr_reader :destination, :raw_config, :secrets
15
19
  attr_reader :accessories, :aliases, :boot, :builder, :env, :logging, :output, :proxy, :proxy_boot, :servers, :ssh, :sshkit, :registry
@@ -18,7 +22,7 @@ class Kamal::Configuration
18
22
 
19
23
  class << self
20
24
  def create_from(config_file:, destination: nil, version: nil)
21
- ENV["KAMAL_DESTINATION"] = destination
25
+ ENV["DASH_DESTINATION"] = ENV["KAMAL_DESTINATION"] = destination
22
26
 
23
27
  raw_config = load_raw_config(config_file: config_file, destination: destination)
24
28
 
@@ -56,9 +60,9 @@ class Kamal::Configuration
56
60
  @destination = destination
57
61
  @declared_version = version
58
62
 
59
- validate! raw_config, example: validation_yml.symbolize_keys, context: "", with: Kamal::Configuration::Validator::Configuration
63
+ validate! raw_config, example: validation_yml.symbolize_keys, context: "", with: Dash::Configuration::Validator::Configuration
60
64
 
61
- @secrets = Kamal::Secrets.new(destination: destination, secrets_path: secrets_path)
65
+ @secrets = Dash::Secrets.new(destination: destination, secrets_path: secrets_path)
62
66
 
63
67
  # Eager load config to validate it, these are first as they have dependencies later on
64
68
  @servers = Servers.new(config: self)
@@ -292,8 +296,14 @@ class Kamal::Configuration
292
296
  raw_config.stop_timeout
293
297
  end
294
298
 
299
+ # Where dash keeps its per-host state - app env and assets, the proxy's
300
+ # options/image/run_command files and apps-config bind mount, loadbalancer
301
+ # service claims, deploy locks and the audit log - under the SSH user's home.
302
+ # Renamed from `.kamal` in stage 3b of the server artifact rename
303
+ # (zoolutions/dash#118); hosts still on the old name are migrated in place by
304
+ # Dash::Commands::Base#ensure_run_directory.
295
305
  def run_directory
296
- ".kamal"
306
+ ".dash"
297
307
  end
298
308
 
299
309
  def apps_directory
@@ -313,11 +323,11 @@ class Kamal::Configuration
313
323
  end
314
324
 
315
325
  def hooks_path
316
- raw_config.hooks_path || ".kamal/hooks"
326
+ raw_config.hooks_path || Dash::ProjectDirectory.join("hooks")
317
327
  end
318
328
 
319
329
  def secrets_path
320
- raw_config.secrets_path || ".kamal/secrets"
330
+ raw_config.secrets_path || Dash::ProjectDirectory.join("secrets")
321
331
  end
322
332
 
323
333
  def asset_path
@@ -379,26 +389,26 @@ class Kamal::Configuration
379
389
 
380
390
  def ensure_required_keys_present
381
391
  %i[ service registry ].each do |key|
382
- raise Kamal::ConfigurationError, "Missing required configuration for #{key}" unless raw_config[key].present?
392
+ raise Dash::ConfigurationError, "Missing required configuration for #{key}" unless raw_config[key].present?
383
393
  end
384
394
 
385
- raise Kamal::ConfigurationError, "Missing required configuration for image" if image.blank?
395
+ raise Dash::ConfigurationError, "Missing required configuration for image" if image.blank?
386
396
 
387
397
  if raw_config.servers.nil?
388
- raise Kamal::ConfigurationError, "No servers or accessories specified" unless raw_config.accessories.present?
398
+ raise Dash::ConfigurationError, "No servers or accessories specified" unless raw_config.accessories.present?
389
399
  else
390
400
  unless role(primary_role_name).present?
391
- raise Kamal::ConfigurationError, "The primary_role #{primary_role_name} isn't defined"
401
+ raise Dash::ConfigurationError, "The primary_role #{primary_role_name} isn't defined"
392
402
  end
393
403
 
394
404
  if primary_role.hosts.empty?
395
- raise Kamal::ConfigurationError, "No servers specified for the #{primary_role.name} primary_role"
405
+ raise Dash::ConfigurationError, "No servers specified for the #{primary_role.name} primary_role"
396
406
  end
397
407
 
398
408
  unless allow_empty_roles?
399
409
  roles.each do |role|
400
410
  if role.hosts.empty?
401
- raise Kamal::ConfigurationError, "No servers specified for the #{role.name} role. You can ignore this with allow_empty_roles: true"
411
+ raise Dash::ConfigurationError, "No servers specified for the #{role.name} role. You can ignore this with allow_empty_roles: true"
402
412
  end
403
413
  end
404
414
  end
@@ -408,21 +418,21 @@ class Kamal::Configuration
408
418
  end
409
419
 
410
420
  def ensure_valid_service_name
411
- raise Kamal::ConfigurationError, "Service name can only include alphanumeric characters, hyphens, and underscores" unless raw_config[:service] =~ /^[a-z0-9_-]+$/i
421
+ raise Dash::ConfigurationError, "Service name can only include alphanumeric characters, hyphens, and underscores" unless raw_config[:service] =~ /^[a-z0-9_-]+$/i
412
422
 
413
423
  true
414
424
  end
415
425
 
416
426
  def ensure_valid_kamal_version
417
- if minimum_version && Gem::Version.new(minimum_version) > Gem::Version.new(Kamal::VERSION)
418
- raise Kamal::ConfigurationError, "Current version is #{Kamal::VERSION}, minimum required is #{minimum_version}"
427
+ if minimum_version && Gem::Version.new(minimum_version) > Gem::Version.new(Dash::VERSION)
428
+ raise Dash::ConfigurationError, "Current version is #{Dash::VERSION}, minimum required is #{minimum_version}"
419
429
  end
420
430
 
421
431
  true
422
432
  end
423
433
 
424
434
  def ensure_retain_containers_valid
425
- raise Kamal::ConfigurationError, "Must retain at least 1 container" if retain_containers < 1
435
+ raise Dash::ConfigurationError, "Must retain at least 1 container" if retain_containers < 1
426
436
 
427
437
  true
428
438
  end
@@ -431,7 +441,7 @@ class Kamal::Configuration
431
441
  hooks = %w[ pre-traefik-reboot post-traefik-reboot ].select { |hook_file| File.exist?(File.join(hooks_path, hook_file)) }
432
442
 
433
443
  if hooks.any?
434
- raise Kamal::ConfigurationError, "Found #{hooks.join(", ")}, these should be renamed to (pre|post)-proxy-reboot"
444
+ raise Dash::ConfigurationError, "Found #{hooks.join(", ")}, these should be renamed to (pre|post)-proxy-reboot"
435
445
  end
436
446
 
437
447
  true
@@ -451,7 +461,7 @@ class Kamal::Configuration
451
461
  return true if offenders.empty?
452
462
 
453
463
  warn "Non-proxied role(s) #{offenders.map(&:name).join(", ")} have no healthcheck. " \
454
- "Without one, Kamal accepts the container as ready #{readiness_delay}s after it merely starts " \
464
+ "Without one, dash accepts the container as ready #{readiness_delay}s after it merely starts " \
455
465
  "and then stops the previous container — traffic can be dropped. Add a `healthcheck:` block, " \
456
466
  "or opt out explicitly with `healthcheck: false`. This warning will become an error in a future release."
457
467
 
@@ -492,7 +502,7 @@ class Kamal::Configuration
492
502
 
493
503
  return true if offenders.empty?
494
504
 
495
- raise Kamal::ConfigurationError, "Role(s) #{offenders.map(&:name).join(", ")}: " \
505
+ raise Dash::ConfigurationError, "Role(s) #{offenders.map(&:name).join(", ")}: " \
496
506
  "proxy/sleep requires proxy/run/docker_socket - kamal-proxy can only stop and start containers " \
497
507
  "through the container runtime socket, and it is not mounted into the proxy without it"
498
508
  end
@@ -577,7 +587,7 @@ class Kamal::Configuration
577
587
  paced = roles.select(&:boot)
578
588
  return true if paced.empty? || boot.parallel_roles != false
579
589
 
580
- raise Kamal::ConfigurationError, "servers/#{paced.first.name}/boot cannot be combined with boot/parallel_roles: false, " \
590
+ raise Dash::ConfigurationError, "servers/#{paced.first.name}/boot cannot be combined with boot/parallel_roles: false, " \
581
591
  "which boots each host's roles in turn and so cannot pace one role's hosts. Remove one of them"
582
592
  end
583
593
 
@@ -602,7 +612,7 @@ class Kamal::Configuration
602
612
  hosts = roles.select(&:ssl?).flat_map { |role| role.proxy.hosts }
603
613
  duplicates = hosts.tally.filter_map { |host, count| host if count > 1 }
604
614
 
605
- raise Kamal::ConfigurationError, "Different roles can't share the same host for SSL: #{duplicates.join(", ")}" if duplicates.any?
615
+ raise Dash::ConfigurationError, "Different roles can't share the same host for SSL: #{duplicates.join(", ")}" if duplicates.any?
606
616
 
607
617
  true
608
618
  end
@@ -610,7 +620,7 @@ class Kamal::Configuration
610
620
  def ensure_local_registry_remote_builder_has_ssh_url
611
621
  if registry.local? && builder.remote?
612
622
  unless URI(builder.remote).scheme == "ssh"
613
- raise Kamal::ConfigurationError, "Local registry with remote builder requires an SSH URL (e.g., ssh://user@host)"
623
+ raise Dash::ConfigurationError, "Local registry with remote builder requires an SSH URL (e.g., ssh://user@host)"
614
624
  end
615
625
  end
616
626
 
@@ -621,7 +631,7 @@ class Kamal::Configuration
621
631
  all_hosts.each do |host|
622
632
  run_configs = proxy_runs(host)
623
633
  if run_configs.uniq.size > 1
624
- raise Kamal::ConfigurationError, "Conflicting proxy run configurations for host #{host}"
634
+ raise Dash::ConfigurationError, "Conflicting proxy run configurations for host #{host}"
625
635
  end
626
636
  end
627
637
  end
@@ -634,7 +644,7 @@ class Kamal::Configuration
634
644
  # accessories-only configuration has nothing to run it on.
635
645
  def ensure_valid_loadbalancer
636
646
  if proxy.loadbalancer == true && primary_role.nil?
637
- raise Kamal::ConfigurationError, "proxy/loadbalancer: can't be enabled without servers"
647
+ raise Dash::ConfigurationError, "proxy/loadbalancer: can't be enabled without servers"
638
648
  end
639
649
 
640
650
  true
@@ -656,16 +666,16 @@ class Kamal::Configuration
656
666
  def validate_hooks_output_level!(level, hook = nil)
657
667
  return if HOOKS_OUTPUT_LEVELS.include?(level)
658
668
  context = hook ? " for hook '#{hook}'" : ""
659
- raise Kamal::ConfigurationError, "Invalid hooks_output '#{level}'#{context}, must be one of: #{HOOKS_OUTPUT_LEVELS.join(', ')}"
669
+ raise Dash::ConfigurationError, "Invalid hooks_output '#{level}'#{context}, must be one of: #{HOOKS_OUTPUT_LEVELS.join(', ')}"
660
670
  end
661
671
 
662
672
  def git_version
663
673
  @git_version ||=
664
- if Kamal::Git.used?
665
- if Kamal::Git.uncommitted_changes.present? && !builder.git_clone?
674
+ if Dash::Git.used?
675
+ if Dash::Git.uncommitted_changes.present? && !builder.git_clone?
666
676
  uncommitted_suffix = "_uncommitted_#{SecureRandom.hex(8)}"
667
677
  end
668
- [ Kamal::Git.revision, uncommitted_suffix ].compact.join
678
+ [ Dash::Git.revision, uncommitted_suffix ].compact.join
669
679
  else
670
680
  raise "Can't use commit hash as version, no git repository found in #{Dir.pwd}"
671
681
  end
@@ -1,7 +1,7 @@
1
1
  require "tempfile"
2
2
  require "open3"
3
3
 
4
- module Kamal::Docker
4
+ module Dash::Docker
5
5
  extend self
6
6
  BUILD_CHECK_TAG = "kamal-local-build-check"
7
7
 
@@ -1,5 +1,5 @@
1
1
  # Encode an env hash as a string where secret values have been looked up and all values escaped for Docker.
2
- class Kamal::EnvFile
2
+ class Dash::EnvFile
3
3
  def initialize(env)
4
4
  @env = env
5
5
  end
@@ -1,4 +1,4 @@
1
- module Kamal::Git
1
+ module Dash::Git
2
2
  extend self
3
3
 
4
4
  def used?
@@ -4,7 +4,7 @@ require "json"
4
4
  require "securerandom"
5
5
  require "uri"
6
6
 
7
- class Kamal::OtelShipper
7
+ class Dash::OtelShipper
8
8
  BATCH_SIZE = 100
9
9
  FLUSH_INTERVAL = 5.seconds
10
10
 
@@ -38,7 +38,7 @@ class Kamal::OtelShipper
38
38
  @run_id = SecureRandom.uuid
39
39
  @resource_attributes = [
40
40
  { key: "service.name", value: { stringValue: "kamal" } },
41
- { key: "service.version", value: { stringValue: Kamal::VERSION } },
41
+ { key: "service.version", value: { stringValue: Dash::VERSION } },
42
42
  { key: "kamal.run_id", value: { stringValue: @run_id } },
43
43
  *tags.tags.map do |key, value|
44
44
  otel_key = OTEL_ATTRIBUTE_KEYS.fetch(key, "kamal.#{key}")
@@ -156,7 +156,7 @@ class Kamal::OtelShipper
156
156
  payload = {
157
157
  resourceLogs: [ {
158
158
  resource: { attributes: @resource_attributes },
159
- scopeLogs: [ { scope: { name: "kamal", version: Kamal::VERSION }, logRecords: records } ]
159
+ scopeLogs: [ { scope: { name: "kamal", version: Dash::VERSION }, logRecords: records } ]
160
160
  } ]
161
161
  }
162
162
 
@@ -1,6 +1,6 @@
1
1
  require "logger"
2
2
 
3
- class Kamal::Output::BaseLogger < ::Logger
3
+ class Dash::Output::BaseLogger < ::Logger
4
4
  def initialize
5
5
  super(nil)
6
6
  @subscription = ActiveSupport::Notifications.subscribe("modify.kamal", self)
@@ -1,4 +1,4 @@
1
- class Kamal::Output::FileLogger < Kamal::Output::BaseLogger
1
+ class Dash::Output::FileLogger < Dash::Output::BaseLogger
2
2
  attr_reader :path
3
3
 
4
4
  def self.build(settings:, config:)
@@ -1,4 +1,4 @@
1
- class Kamal::Output::Formatter < SSHKit::Formatter::Pretty
1
+ class Dash::Output::Formatter < SSHKit::Formatter::Pretty
2
2
  def initialize(output, logger)
3
3
  @logger = logger
4
4
  super(output)
@@ -1,16 +1,16 @@
1
- class Kamal::Output::OtelLogger < Kamal::Output::BaseLogger
1
+ class Dash::Output::OtelLogger < Dash::Output::BaseLogger
2
2
  def self.build(settings:, config:)
3
3
  raise ArgumentError, "OTel endpoint is required" unless settings["endpoint"]
4
4
  new(
5
5
  endpoint: settings["endpoint"],
6
- tags: Kamal::Tags.from_config(config).except(:service_version, :recorded_at),
6
+ tags: Dash::Tags.from_config(config).except(:service_version, :recorded_at),
7
7
  service: config.service
8
8
  )
9
9
  end
10
10
 
11
11
  def initialize(endpoint:, tags:, service: nil)
12
12
  @endpoint = endpoint
13
- @shipper = Kamal::OtelShipper.new(endpoint: endpoint, tags: tags)
13
+ @shipper = Dash::OtelShipper.new(endpoint: endpoint, tags: tags)
14
14
  @service = service
15
15
  super()
16
16
  end
@@ -0,0 +1,28 @@
1
+ # Where a project keeps its dash-owned files - secrets and hooks - in the
2
+ # operator's own repository. Renamed from `.kamal` in stage 3a of the server
3
+ # artifact rename (zoolutions/dash#118); `.kamal` stays readable until 5.0 so an
4
+ # upgrade doesn't turn every existing project into a missing-secret error.
5
+ #
6
+ # Deliberately not memoized: `dash migrate` moves the directory inside a single
7
+ # process, and a cached answer would be stale for the rest of that invocation.
8
+ class Dash::ProjectDirectory
9
+ CURRENT = ".dash"
10
+ LEGACY = ".kamal"
11
+
12
+ class << self
13
+ def path
14
+ legacy? ? LEGACY : CURRENT
15
+ end
16
+
17
+ # The predicate tests the directory rather than a specific file: a project
18
+ # holding only `secrets-common` or `secrets.<destination>` must still
19
+ # resolve, and Dash::Secrets synthesizes those names from the base path.
20
+ def legacy?
21
+ !Dir.exist?(CURRENT) && Dir.exist?(LEGACY)
22
+ end
23
+
24
+ def join(*parts)
25
+ File.join(path, *parts)
26
+ end
27
+ end
28
+ end
@@ -1,4 +1,4 @@
1
- class Kamal::Secrets::Adapters::AwsSecretsManager < Kamal::Secrets::Adapters::Base
1
+ class Dash::Secrets::Adapters::AwsSecretsManager < Dash::Secrets::Adapters::Base
2
2
  def requires_account?
3
3
  false
4
4
  end
@@ -1,5 +1,5 @@
1
- class Kamal::Secrets::Adapters::Base
2
- delegate :optionize, to: Kamal::Utils
1
+ class Dash::Secrets::Adapters::Base
2
+ delegate :optionize, to: Dash::Utils
3
3
 
4
4
  def fetch(secrets, account: nil, from: nil)
5
5
  raise RuntimeError, "Missing required option '--account'" if requires_account? && account.blank?
@@ -1,4 +1,4 @@
1
- class Kamal::Secrets::Adapters::Bitwarden < Kamal::Secrets::Adapters::Base
1
+ class Dash::Secrets::Adapters::Bitwarden < Dash::Secrets::Adapters::Base
2
2
  private
3
3
  def login(account)
4
4
  status = run_command("status")
@@ -1,4 +1,4 @@
1
- class Kamal::Secrets::Adapters::BitwardenSecretsManager < Kamal::Secrets::Adapters::Base
1
+ class Dash::Secrets::Adapters::BitwardenSecretsManager < Dash::Secrets::Adapters::Base
2
2
  def requires_account?
3
3
  false
4
4
  end
@@ -1,4 +1,4 @@
1
- class Kamal::Secrets::Adapters::Doppler < Kamal::Secrets::Adapters::Base
1
+ class Dash::Secrets::Adapters::Doppler < Dash::Secrets::Adapters::Base
2
2
  def requires_account?
3
3
  false
4
4
  end
@@ -4,11 +4,11 @@
4
4
  # Usage
5
5
  #
6
6
  # Fetch all password from FooBar item
7
- # `kamal secrets fetch --adapter enpass --from /Users/YOUR_USERNAME/Library/Containers/in.sinew.Enpass-Desktop/Data/Documents/Vaults/primary FooBar`
7
+ # `dash secrets fetch --adapter enpass --from /Users/YOUR_USERNAME/Library/Containers/in.sinew.Enpass-Desktop/Data/Documents/Vaults/primary FooBar`
8
8
  #
9
9
  # Fetch only DB_PASSWORD from FooBar item
10
- # `kamal secrets fetch --adapter enpass --from /Users/YOUR_USERNAME/Library/Containers/in.sinew.Enpass-Desktop/Data/Documents/Vaults/primary FooBar/DB_PASSWORD`
11
- class Kamal::Secrets::Adapters::Enpass < Kamal::Secrets::Adapters::Base
10
+ # `dash secrets fetch --adapter enpass --from /Users/YOUR_USERNAME/Library/Containers/in.sinew.Enpass-Desktop/Data/Documents/Vaults/primary FooBar/DB_PASSWORD`
11
+ class Dash::Secrets::Adapters::Enpass < Dash::Secrets::Adapters::Base
12
12
  def requires_account?
13
13
  false
14
14
  end
@@ -1,4 +1,4 @@
1
- class Kamal::Secrets::Adapters::GcpSecretManager < Kamal::Secrets::Adapters::Base
1
+ class Dash::Secrets::Adapters::GcpSecretManager < Dash::Secrets::Adapters::Base
2
2
  private
3
3
  def login(account)
4
4
  # Since only the account option is passed from the cli, we'll use it for both account and service account
@@ -1,4 +1,4 @@
1
- class Kamal::Secrets::Adapters::LastPass < Kamal::Secrets::Adapters::Base
1
+ class Dash::Secrets::Adapters::LastPass < Dash::Secrets::Adapters::Base
2
2
  private
3
3
  def login(account)
4
4
  unless loggedin?(account)
@@ -1,5 +1,5 @@
1
- class Kamal::Secrets::Adapters::OnePassword < Kamal::Secrets::Adapters::Base
2
- delegate :optionize, to: Kamal::Utils
1
+ class Dash::Secrets::Adapters::OnePassword < Dash::Secrets::Adapters::Base
2
+ delegate :optionize, to: Dash::Utils
3
3
 
4
4
  private
5
5
  def login(account)
@@ -1,4 +1,4 @@
1
- class Kamal::Secrets::Adapters::Passbolt < Kamal::Secrets::Adapters::Base
1
+ class Dash::Secrets::Adapters::Passbolt < Dash::Secrets::Adapters::Base
2
2
  def requires_account?
3
3
  false
4
4
  end
@@ -1,4 +1,4 @@
1
- class Kamal::Secrets::Adapters::Test < Kamal::Secrets::Adapters::Base
1
+ class Dash::Secrets::Adapters::Test < Dash::Secrets::Adapters::Base
2
2
  private
3
3
  def login(account)
4
4
  true
@@ -1,5 +1,5 @@
1
1
  require "active_support/core_ext/string/inflections"
2
- module Kamal::Secrets::Adapters
2
+ module Dash::Secrets::Adapters
3
3
  def self.lookup(name)
4
4
  name = "one_password" if name.downcase == "1password"
5
5
  name = "last_pass" if name.downcase == "lastpass"
@@ -9,7 +9,7 @@ module Kamal::Secrets::Adapters
9
9
  end
10
10
 
11
11
  def self.adapter_class(name)
12
- Object.const_get("Kamal::Secrets::Adapters::#{name.camelize}").new
12
+ Object.const_get("Dash::Secrets::Adapters::#{name.camelize}").new
13
13
  rescue NameError => e
14
14
  raise RuntimeError, "Unknown secrets adapter: #{name}"
15
15
  end
@@ -1,4 +1,4 @@
1
- class Kamal::Secrets::Dotenv::InlineCommandSubstitution
1
+ class Dash::Secrets::Dotenv::InlineCommandSubstitution
2
2
  # Unlike dotenv, this regex does not match escaped
3
3
  # parentheses when looking for command substitutions.
4
4
  INTERPOLATED_SHELL_COMMAND = /
@@ -29,7 +29,9 @@ class Kamal::Secrets::Dotenv::InlineCommandSubstitution
29
29
  $LAST_MATCH_INFO[0][1..]
30
30
  else
31
31
  command = ::Dotenv::Substitutions::Variable.call(command, env)
32
- if command =~ /\A\s*kamal\s*secrets\s+/
32
+ # Accept the legacy `kamal secrets` spelling too — secrets files
33
+ # written before the dash rename still use it.
34
+ if command =~ /\A\s*(dash|kamal)\s*secrets\s+/
33
35
  # Inline the command
34
36
  inline_secrets_command(command)
35
37
  else
@@ -41,7 +43,7 @@ class Kamal::Secrets::Dotenv::InlineCommandSubstitution
41
43
  end
42
44
 
43
45
  def inline_secrets_command(command)
44
- Kamal::Cli::Main.start(command.shellsplit[1..] + [ "--inline" ]).chomp
46
+ Dash::Cli::Main.start(command.shellsplit[1..] + [ "--inline" ]).chomp
45
47
  end
46
48
  end
47
49
  end
@@ -1,11 +1,11 @@
1
1
  require "dotenv"
2
2
 
3
- class Kamal::Secrets
4
- Kamal::Secrets::Dotenv::InlineCommandSubstitution.install!
3
+ class Dash::Secrets
4
+ Dash::Secrets::Dotenv::InlineCommandSubstitution.install!
5
5
 
6
- def initialize(destination: nil, secrets_path: ".kamal/secrets")
6
+ def initialize(destination: nil, secrets_path: nil)
7
7
  @destination = destination
8
- @secrets_path = secrets_path
8
+ @secrets_path = secrets_path || Dash::ProjectDirectory.join("secrets")
9
9
  @mutex = Mutex.new
10
10
  end
11
11
 
@@ -13,9 +13,9 @@ class Kamal::Secrets
13
13
  synchronized_fetch(key)
14
14
  rescue KeyError
15
15
  if secrets_files.present?
16
- raise Kamal::ConfigurationError, "Secret '#{key}' not found in #{secrets_files.join(", ")}"
16
+ raise Dash::ConfigurationError, "Secret '#{key}' not found in #{secrets_files.join(", ")}"
17
17
  else
18
- raise Kamal::ConfigurationError, "Secret '#{key}' not found, no secret files (#{secrets_filenames.join(", ")}) provided"
18
+ raise Dash::ConfigurationError, "Secret '#{key}' not found, no secret files (#{secrets_filenames.join(", ")}) provided"
19
19
  end
20
20
  end
21
21
 
@@ -1,6 +1,6 @@
1
1
  require "time"
2
2
 
3
- class Kamal::Tags
3
+ class Dash::Tags
4
4
  attr_reader :config, :tags
5
5
 
6
6
  class << self
@@ -10,7 +10,7 @@ class Kamal::Tags
10
10
 
11
11
  def default_tags(config)
12
12
  { recorded_at: Time.now.utc.iso8601,
13
- performer: Kamal::Git.email.presence || `whoami`.chomp,
13
+ performer: Dash::Git.email.presence || `whoami`.chomp,
14
14
  destination: config.destination,
15
15
  version: config.version,
16
16
  service_version: service_version(config),
@@ -26,8 +26,13 @@ class Kamal::Tags
26
26
  @tags = tags.compact
27
27
  end
28
28
 
29
+ # Both prefixes carry the same value: hooks are operator-written and apps read
30
+ # these at runtime, so the old names stay until 5.0 (zoolutions/dash#118).
29
31
  def env
30
- tags.transform_keys { |detail| "KAMAL_#{detail.upcase}" }
32
+ tags.each_with_object({}) do |(detail, value), env|
33
+ env["DASH_#{detail.upcase}"] = value
34
+ env["KAMAL_#{detail.upcase}"] = value
35
+ end
31
36
  end
32
37
 
33
38
  def to_s
@@ -1,7 +1,7 @@
1
1
  require "active_support/core_ext/module/delegation"
2
2
  require "sshkit"
3
3
 
4
- class Kamal::Utils::Sensitive
4
+ class Dash::Utils::Sensitive
5
5
  # So SSHKit knows to redact these values.
6
6
  include SSHKit::Redaction
7
7