kamal 2.0.0.alpha → 2.0.0.beta2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/lib/kamal/cli/accessory.rb +44 -20
- data/lib/kamal/cli/app/boot.rb +22 -16
- data/lib/kamal/cli/app.rb +37 -3
- data/lib/kamal/cli/base.rb +21 -49
- data/lib/kamal/cli/build.rb +21 -14
- data/lib/kamal/cli/healthcheck/barrier.rb +2 -0
- data/lib/kamal/cli/healthcheck/poller.rb +18 -39
- data/lib/kamal/cli/lock.rb +2 -3
- data/lib/kamal/cli/main.rb +54 -51
- data/lib/kamal/cli/proxy.rb +213 -0
- data/lib/kamal/cli/prune.rb +0 -1
- data/lib/kamal/cli/secrets.rb +36 -0
- data/lib/kamal/cli/server.rb +0 -2
- data/lib/kamal/cli/templates/deploy.yml +0 -11
- data/lib/kamal/cli/templates/sample_hooks/post-proxy-reboot.sample +3 -0
- data/lib/kamal/cli/templates/secrets +16 -0
- data/lib/kamal/cli.rb +1 -0
- data/lib/kamal/commander/specifics.rb +3 -3
- data/lib/kamal/commander.rb +17 -9
- data/lib/kamal/commands/accessory.rb +7 -7
- data/lib/kamal/commands/app/assets.rb +8 -8
- data/lib/kamal/commands/app/execution.rb +1 -0
- data/lib/kamal/commands/app/proxy.rb +16 -0
- data/lib/kamal/commands/app.rb +7 -15
- data/lib/kamal/commands/auditor.rb +6 -3
- data/lib/kamal/commands/base.rb +8 -0
- data/lib/kamal/commands/builder/base.rb +2 -6
- data/lib/kamal/commands/builder/hybrid.rb +1 -1
- data/lib/kamal/commands/builder/remote.rb +27 -4
- data/lib/kamal/commands/builder.rb +1 -1
- data/lib/kamal/commands/docker.rb +4 -0
- data/lib/kamal/commands/hook.rb +8 -2
- data/lib/kamal/commands/lock.rb +2 -6
- data/lib/kamal/commands/proxy.rb +72 -0
- data/lib/kamal/commands/prune.rb +1 -9
- data/lib/kamal/commands/server.rb +11 -1
- data/lib/kamal/configuration/accessory.rb +14 -2
- data/lib/kamal/configuration/builder.rb +9 -3
- data/lib/kamal/configuration/docs/builder.yml +20 -10
- data/lib/kamal/configuration/docs/configuration.yml +16 -16
- data/lib/kamal/configuration/docs/env.yml +10 -11
- data/lib/kamal/configuration/docs/proxy.yml +100 -0
- data/lib/kamal/configuration/docs/registry.yml +4 -2
- data/lib/kamal/configuration/docs/role.yml +3 -5
- data/lib/kamal/configuration/env/tag.rb +4 -3
- data/lib/kamal/configuration/env.rb +10 -17
- data/lib/kamal/configuration/proxy.rb +66 -0
- data/lib/kamal/configuration/registry.rb +3 -2
- data/lib/kamal/configuration/role.rb +63 -94
- data/lib/kamal/configuration/validator/builder.rb +2 -0
- data/lib/kamal/configuration/validator/proxy.rb +11 -0
- data/lib/kamal/configuration/validator.rb +3 -1
- data/lib/kamal/configuration.rb +80 -33
- data/lib/kamal/env_file.rb +4 -0
- data/lib/kamal/secrets/adapters/base.rb +18 -0
- data/lib/kamal/secrets/adapters/bitwarden.rb +64 -0
- data/lib/kamal/secrets/adapters/last_pass.rb +30 -0
- data/lib/kamal/secrets/adapters/one_password.rb +61 -0
- data/lib/kamal/secrets/adapters/test.rb +10 -0
- data/lib/kamal/secrets/adapters.rb +14 -0
- data/lib/kamal/secrets/dotenv/inline_command_substitution.rb +32 -0
- data/lib/kamal/secrets.rb +37 -0
- data/lib/kamal/sshkit_with_ext.rb +1 -0
- data/lib/kamal/utils.rb +12 -0
- data/lib/kamal/version.rb +1 -1
- data/lib/kamal.rb +3 -1
- metadata +23 -16
- data/lib/kamal/cli/env.rb +0 -54
- data/lib/kamal/cli/templates/sample_hooks/post-traefik-reboot.sample +0 -3
- data/lib/kamal/cli/templates/template.env +0 -2
- data/lib/kamal/cli/traefik.rb +0 -122
- data/lib/kamal/commands/app/cord.rb +0 -22
- data/lib/kamal/commands/traefik.rb +0 -85
- data/lib/kamal/configuration/docs/healthcheck.yml +0 -59
- data/lib/kamal/configuration/docs/traefik.yml +0 -62
- data/lib/kamal/configuration/healthcheck.rb +0 -63
- data/lib/kamal/configuration/traefik.rb +0 -60
- /data/lib/kamal/cli/templates/sample_hooks/{pre-traefik-reboot.sample → pre-proxy-reboot.sample} +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4ecbda147c5d6acff593f449f0ba0aa0f721bbbe56fbe2718819a55539ff5a66
|
4
|
+
data.tar.gz: 5d83d711f125217fd1d0d1f1ef82807d8fe1e7a04bdb0bb73c22a2614037720b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '049f3a8e91a724d1d43d9cea996231b362fd0f3bb325c3488827c1d83aec07c6f50a6cf5f4206ea80632d8901438c20b731f3170be665a5026081d7417f099a1'
|
7
|
+
data.tar.gz: fc061ceab3bff080b5f24f3206df556c756c9122be125eccd85591bf36a7740c957df77244af1ee72d7770ed7052895e59336d6cb5f794abb300437ba2e057b7
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Kamal: Deploy web apps anywhere
|
2
2
|
|
3
|
-
From bare metal to cloud VMs, deploy web apps anywhere with zero downtime. Kamal
|
3
|
+
From bare metal to cloud VMs, deploy web apps anywhere with zero downtime. Kamal uses [kamal-proxy](https://github.com/basecamp/kamal-proxy) to seamlessly switch requests between containers. Works seamlessly across multiple servers, using SSHKit to execute commands. Originally built for Rails apps, Kamal will work with any type of web app that can be containerized with Docker.
|
4
4
|
|
5
5
|
➡️ See [kamal-deploy.org](https://kamal-deploy.org) for documentation on [installation](https://kamal-deploy.org/docs/installation), [configuration](https://kamal-deploy.org/docs/configuration), and [commands](https://kamal-deploy.org/docs/commands).
|
6
6
|
|
data/lib/kamal/cli/accessory.rb
CHANGED
@@ -1,17 +1,20 @@
|
|
1
1
|
class Kamal::Cli::Accessory < Kamal::Cli::Base
|
2
2
|
desc "boot [NAME]", "Boot new accessory service on host (use NAME=all to boot all accessories)"
|
3
|
-
def boot(name,
|
3
|
+
def boot(name, prepare: true)
|
4
4
|
with_lock do
|
5
5
|
if name == "all"
|
6
6
|
KAMAL.accessory_names.each { |accessory_name| boot(accessory_name) }
|
7
7
|
else
|
8
|
+
prepare(name) if prepare
|
9
|
+
|
8
10
|
with_accessory(name) do |accessory, hosts|
|
9
11
|
directories(name)
|
10
12
|
upload(name)
|
11
13
|
|
12
14
|
on(hosts) do
|
13
|
-
execute *KAMAL.registry.login if login
|
14
15
|
execute *KAMAL.auditor.record("Booted #{name} accessory"), verbosity: :debug
|
16
|
+
execute *accessory.ensure_env_directory
|
17
|
+
upload! accessory.secrets_io, accessory.secrets_path, mode: "0600"
|
15
18
|
execute *accessory.run
|
16
19
|
end
|
17
20
|
end
|
@@ -55,15 +58,10 @@ class Kamal::Cli::Accessory < Kamal::Cli::Base
|
|
55
58
|
if name == "all"
|
56
59
|
KAMAL.accessory_names.each { |accessory_name| reboot(accessory_name) }
|
57
60
|
else
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
stop(name)
|
64
|
-
remove_container(name)
|
65
|
-
boot(name, login: false)
|
66
|
-
end
|
61
|
+
prepare(name)
|
62
|
+
stop(name)
|
63
|
+
remove_container(name)
|
64
|
+
boot(name, prepare: false)
|
67
65
|
end
|
68
66
|
end
|
69
67
|
end
|
@@ -95,10 +93,8 @@ class Kamal::Cli::Accessory < Kamal::Cli::Base
|
|
95
93
|
desc "restart [NAME]", "Restart existing accessory container on host"
|
96
94
|
def restart(name)
|
97
95
|
with_lock do
|
98
|
-
|
99
|
-
|
100
|
-
start(name)
|
101
|
-
end
|
96
|
+
stop(name)
|
97
|
+
start(name)
|
102
98
|
end
|
103
99
|
end
|
104
100
|
|
@@ -222,6 +218,25 @@ class Kamal::Cli::Accessory < Kamal::Cli::Base
|
|
222
218
|
end
|
223
219
|
end
|
224
220
|
|
221
|
+
desc "upgrade", "Upgrade accessories from Kamal 1.x to 2.0 (restart them in 'kamal' network)"
|
222
|
+
option :rolling, type: :boolean, default: false, desc: "Upgrade one host at a time"
|
223
|
+
option :confirmed, aliases: "-y", type: :boolean, default: false, desc: "Proceed without confirmation question"
|
224
|
+
def upgrade(name)
|
225
|
+
confirming "This will restart all accessories" do
|
226
|
+
with_lock do
|
227
|
+
host_groups = options[:rolling] ? KAMAL.accessory_hosts : [ KAMAL.accessory_hosts ]
|
228
|
+
host_groups.each do |hosts|
|
229
|
+
host_list = Array(hosts).join(",")
|
230
|
+
KAMAL.with_specific_hosts(hosts) do
|
231
|
+
say "Upgrading #{name} accessories on #{host_list}...", :magenta
|
232
|
+
reboot name
|
233
|
+
say "Upgraded #{name} accessories on #{host_list}...", :magenta
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
225
240
|
private
|
226
241
|
def with_accessory(name)
|
227
242
|
if KAMAL.config.accessory(name)
|
@@ -249,11 +264,20 @@ class Kamal::Cli::Accessory < Kamal::Cli::Base
|
|
249
264
|
end
|
250
265
|
|
251
266
|
def remove_accessory(name)
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
267
|
+
stop(name)
|
268
|
+
remove_container(name)
|
269
|
+
remove_image(name)
|
270
|
+
remove_service_directory(name)
|
271
|
+
end
|
272
|
+
|
273
|
+
def prepare(name)
|
274
|
+
with_accessory(name) do |accessory, hosts|
|
275
|
+
on(hosts) do
|
276
|
+
execute *KAMAL.registry.login
|
277
|
+
execute *KAMAL.docker.create_network
|
278
|
+
rescue SSHKit::Command::Failed => e
|
279
|
+
raise unless e.message.include?("already exists")
|
280
|
+
end
|
257
281
|
end
|
258
282
|
end
|
259
283
|
end
|
data/lib/kamal/cli/app/boot.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
class Kamal::Cli::App::Boot
|
2
2
|
attr_reader :host, :role, :version, :barrier, :sshkit
|
3
|
-
delegate :execute, :capture_with_info, :capture_with_pretty_json, :info, :error, to: :sshkit
|
4
|
-
delegate :
|
3
|
+
delegate :execute, :capture_with_info, :capture_with_pretty_json, :info, :error, :upload!, to: :sshkit
|
4
|
+
delegate :assets?, :running_proxy?, to: :role
|
5
5
|
|
6
6
|
def initialize(host, role, sshkit, version, barrier)
|
7
7
|
@host = host
|
@@ -45,11 +45,22 @@ class Kamal::Cli::App::Boot
|
|
45
45
|
|
46
46
|
def start_new_version
|
47
47
|
audit "Booted app version #{version}"
|
48
|
-
|
49
|
-
execute *app.tie_cord(role.cord_host_file) if uses_cord?
|
50
48
|
hostname = "#{host.to_s[0...51].gsub(/\.+$/, '')}-#{SecureRandom.hex(6)}"
|
49
|
+
|
50
|
+
execute *app.ensure_env_directory
|
51
|
+
upload! role.secrets_io(host), role.secrets_path, mode: "0600"
|
52
|
+
|
51
53
|
execute *app.run(hostname: hostname)
|
52
|
-
|
54
|
+
if running_proxy?
|
55
|
+
endpoint = capture_with_info(*app.container_id_for_version(version)).strip
|
56
|
+
raise Kamal::Cli::BootError, "Failed to get endpoint for #{role} on #{host}, did the container boot?" if endpoint.empty?
|
57
|
+
execute *app.deploy(target: endpoint)
|
58
|
+
else
|
59
|
+
Kamal::Cli::Healthcheck::Poller.wait_for_healthy(pause_after_ready: true) { capture_with_info(*app.status(version: version)) }
|
60
|
+
end
|
61
|
+
rescue => e
|
62
|
+
error "Failed to boot #{role} on #{host}"
|
63
|
+
raise e
|
53
64
|
end
|
54
65
|
|
55
66
|
def stop_new_version
|
@@ -57,16 +68,7 @@ class Kamal::Cli::App::Boot
|
|
57
68
|
end
|
58
69
|
|
59
70
|
def stop_old_version(version)
|
60
|
-
if uses_cord?
|
61
|
-
cord = capture_with_info(*app.cord(version: version), raise_on_non_zero_exit: false).strip
|
62
|
-
if cord.present?
|
63
|
-
execute *app.cut_cord(cord)
|
64
|
-
Kamal::Cli::Healthcheck::Poller.wait_for_unhealthy(pause_after_ready: true) { capture_with_info(*app.status(version: version)) }
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
71
|
execute *app.stop(version: version), raise_on_non_zero_exit: false
|
69
|
-
|
70
72
|
execute *app.clean_up_assets if assets?
|
71
73
|
end
|
72
74
|
|
@@ -88,8 +90,12 @@ class Kamal::Cli::App::Boot
|
|
88
90
|
def close_barrier
|
89
91
|
if barrier.close
|
90
92
|
info "First #{KAMAL.primary_role} container is unhealthy on #{host}, not booting any other roles"
|
91
|
-
|
92
|
-
|
93
|
+
begin
|
94
|
+
error capture_with_info(*app.logs(version: version))
|
95
|
+
error capture_with_info(*app.container_health_log(version: version))
|
96
|
+
rescue SSHKit::Command::Failed
|
97
|
+
error "Could not fetch logs for #{version}"
|
98
|
+
end
|
93
99
|
end
|
94
100
|
end
|
95
101
|
|
data/lib/kamal/cli/app.rb
CHANGED
@@ -4,7 +4,7 @@ class Kamal::Cli::App < Kamal::Cli::Base
|
|
4
4
|
with_lock do
|
5
5
|
say "Get most recent version available as an image...", :magenta unless options[:version]
|
6
6
|
using_version(version_or_latest) do |version|
|
7
|
-
say "Start container with version #{version}
|
7
|
+
say "Start container with version #{version} (or reboot if already running)...", :magenta
|
8
8
|
|
9
9
|
# Assets are prepared in a separate step to ensure they are on all hosts before booting
|
10
10
|
on(KAMAL.hosts) do
|
@@ -38,8 +38,17 @@ class Kamal::Cli::App < Kamal::Cli::Base
|
|
38
38
|
roles = KAMAL.roles_on(host)
|
39
39
|
|
40
40
|
roles.each do |role|
|
41
|
+
app = KAMAL.app(role: role, host: host)
|
41
42
|
execute *KAMAL.auditor.record("Started app version #{KAMAL.config.version}"), verbosity: :debug
|
42
|
-
execute *
|
43
|
+
execute *app.start, raise_on_non_zero_exit: false
|
44
|
+
|
45
|
+
if role.running_proxy?
|
46
|
+
version = capture_with_info(*app.current_running_version, raise_on_non_zero_exit: false).strip
|
47
|
+
endpoint = capture_with_info(*app.container_id_for_version(version)).strip
|
48
|
+
raise Kamal::Cli::BootError, "Failed to get endpoint for #{role} on #{host}, did the container boot?" if endpoint.empty?
|
49
|
+
|
50
|
+
execute *app.deploy(target: endpoint)
|
51
|
+
end
|
43
52
|
end
|
44
53
|
end
|
45
54
|
end
|
@@ -52,8 +61,18 @@ class Kamal::Cli::App < Kamal::Cli::Base
|
|
52
61
|
roles = KAMAL.roles_on(host)
|
53
62
|
|
54
63
|
roles.each do |role|
|
64
|
+
app = KAMAL.app(role: role, host: host)
|
55
65
|
execute *KAMAL.auditor.record("Stopped app", role: role), verbosity: :debug
|
56
|
-
|
66
|
+
|
67
|
+
if role.running_proxy?
|
68
|
+
version = capture_with_info(*app.current_running_version, raise_on_non_zero_exit: false).strip
|
69
|
+
endpoint = capture_with_info(*app.container_id_for_version(version)).strip
|
70
|
+
if endpoint.present?
|
71
|
+
execute *app.remove(target: endpoint), raise_on_non_zero_exit: false
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
execute *app.stop, raise_on_non_zero_exit: false
|
57
76
|
end
|
58
77
|
end
|
59
78
|
end
|
@@ -212,6 +231,7 @@ class Kamal::Cli::App < Kamal::Cli::Base
|
|
212
231
|
stop
|
213
232
|
remove_containers
|
214
233
|
remove_images
|
234
|
+
remove_app_directory
|
215
235
|
end
|
216
236
|
end
|
217
237
|
|
@@ -253,6 +273,20 @@ class Kamal::Cli::App < Kamal::Cli::Base
|
|
253
273
|
end
|
254
274
|
end
|
255
275
|
|
276
|
+
desc "remove_app_directory", "Remove the service directory from servers", hide: true
|
277
|
+
def remove_app_directory
|
278
|
+
with_lock do
|
279
|
+
on(KAMAL.hosts) do |host|
|
280
|
+
roles = KAMAL.roles_on(host)
|
281
|
+
|
282
|
+
roles.each do |role|
|
283
|
+
execute *KAMAL.auditor.record("Removed #{KAMAL.config.app_directory} on all servers", role: role), verbosity: :debug
|
284
|
+
execute *KAMAL.server.remove_app_directory, raise_on_non_zero_exit: false
|
285
|
+
end
|
286
|
+
end
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
256
290
|
desc "version", "Show app version currently running on servers"
|
257
291
|
def version
|
258
292
|
on(KAMAL.hosts) do |host|
|
data/lib/kamal/cli/base.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require "thor"
|
2
|
-
require "dotenv"
|
3
2
|
require "kamal/sshkit_with_ext"
|
4
3
|
|
5
4
|
module Kamal::Cli
|
@@ -31,53 +30,15 @@ module Kamal::Cli
|
|
31
30
|
else
|
32
31
|
super
|
33
32
|
end
|
34
|
-
|
35
|
-
load_env
|
36
|
-
initialize_commander(options_with_subcommand_class_options)
|
33
|
+
initialize_commander unless KAMAL.configured?
|
37
34
|
end
|
38
35
|
|
39
36
|
private
|
40
|
-
def reload_env
|
41
|
-
reset_env
|
42
|
-
load_env
|
43
|
-
end
|
44
|
-
|
45
|
-
def load_env
|
46
|
-
if destination = options[:destination]
|
47
|
-
Dotenv.load(".env.#{destination}", ".env")
|
48
|
-
else
|
49
|
-
Dotenv.load(".env")
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
def reset_env
|
54
|
-
replace_env @original_env
|
55
|
-
end
|
56
|
-
|
57
|
-
def replace_env(env)
|
58
|
-
ENV.clear
|
59
|
-
ENV.update(env)
|
60
|
-
end
|
61
|
-
|
62
|
-
def with_original_env
|
63
|
-
keeping_current_env do
|
64
|
-
reset_env
|
65
|
-
yield
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
def keeping_current_env
|
70
|
-
current_env = ENV.to_h.dup
|
71
|
-
yield
|
72
|
-
ensure
|
73
|
-
replace_env(current_env)
|
74
|
-
end
|
75
|
-
|
76
37
|
def options_with_subcommand_class_options
|
77
38
|
options.merge(@_initializer.last[:class_options] || {})
|
78
39
|
end
|
79
40
|
|
80
|
-
def initialize_commander
|
41
|
+
def initialize_commander
|
81
42
|
KAMAL.tap do |commander|
|
82
43
|
if options[:verbose]
|
83
44
|
ENV["VERBOSE"] = "1" # For backtraces via cli/start
|
@@ -112,8 +73,6 @@ module Kamal::Cli
|
|
112
73
|
if KAMAL.holding_lock?
|
113
74
|
yield
|
114
75
|
else
|
115
|
-
ensure_run_and_locks_directory
|
116
|
-
|
117
76
|
acquire_lock
|
118
77
|
|
119
78
|
begin
|
@@ -142,6 +101,8 @@ module Kamal::Cli
|
|
142
101
|
end
|
143
102
|
|
144
103
|
def acquire_lock
|
104
|
+
ensure_run_directory
|
105
|
+
|
145
106
|
raise_if_locked do
|
146
107
|
say "Acquiring the deploy lock...", :magenta
|
147
108
|
on(KAMAL.primary_host) { execute *KAMAL.lock.acquire("Automatic deploy lock", KAMAL.config.version), verbosity: :debug }
|
@@ -174,8 +135,10 @@ module Kamal::Cli
|
|
174
135
|
details = { hosts: KAMAL.hosts.join(","), command: command, subcommand: subcommand }
|
175
136
|
|
176
137
|
say "Running the #{hook} hook...", :magenta
|
177
|
-
|
178
|
-
|
138
|
+
with_env KAMAL.hook.env(**details, **extra_details) do
|
139
|
+
run_locally do
|
140
|
+
execute *KAMAL.hook.run(hook)
|
141
|
+
end
|
179
142
|
rescue SSHKit::Command::Failed => e
|
180
143
|
raise HookError.new("Hook `#{hook}` failed:\n#{e.message}")
|
181
144
|
end
|
@@ -213,14 +176,23 @@ module Kamal::Cli
|
|
213
176
|
instance_variable_get("@_invocations").first
|
214
177
|
end
|
215
178
|
|
216
|
-
def
|
179
|
+
def reset_invocation(cli_class)
|
180
|
+
instance_variable_get("@_invocations")[cli_class].pop
|
181
|
+
end
|
182
|
+
|
183
|
+
def ensure_run_directory
|
217
184
|
on(KAMAL.hosts) do
|
218
185
|
execute(*KAMAL.server.ensure_run_directory)
|
219
186
|
end
|
187
|
+
end
|
220
188
|
|
221
|
-
|
222
|
-
|
223
|
-
|
189
|
+
def with_env(env)
|
190
|
+
current_env = ENV.to_h.dup
|
191
|
+
ENV.update(env)
|
192
|
+
yield
|
193
|
+
ensure
|
194
|
+
ENV.clear
|
195
|
+
ENV.update(current_env)
|
224
196
|
end
|
225
197
|
end
|
226
198
|
end
|
data/lib/kamal/cli/build.rb
CHANGED
@@ -30,23 +30,30 @@ class Kamal::Cli::Build < Kamal::Cli::Base
|
|
30
30
|
say "Building with uncommitted changes:\n #{uncommitted_changes}", :yellow
|
31
31
|
end
|
32
32
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
33
|
+
with_env(KAMAL.config.builder.secrets) do
|
34
|
+
run_locally do
|
35
|
+
begin
|
36
|
+
execute *KAMAL.builder.inspect_builder
|
37
|
+
rescue SSHKit::Command::Failed => e
|
38
|
+
if e.message =~ /(context not found|no builder|no compatible builder|does not exist)/
|
39
|
+
warn "Missing compatible builder, so creating a new one first"
|
40
|
+
begin
|
41
|
+
cli.remove
|
42
|
+
rescue SSHKit::Command::Failed
|
43
|
+
raise unless e.message =~ /(context not found|no builder|does not exist)/
|
44
|
+
end
|
45
|
+
cli.create
|
46
|
+
else
|
47
|
+
raise
|
48
|
+
end
|
42
49
|
end
|
43
|
-
end
|
44
50
|
|
45
|
-
|
46
|
-
|
51
|
+
# Get the command here to ensure the Dir.chdir doesn't interfere with it
|
52
|
+
push = KAMAL.builder.push
|
47
53
|
|
48
|
-
|
49
|
-
|
54
|
+
KAMAL.with_verbosity(:debug) do
|
55
|
+
Dir.chdir(KAMAL.config.builder.build_directory) { execute *push }
|
56
|
+
end
|
50
57
|
end
|
51
58
|
end
|
52
59
|
end
|
@@ -1,51 +1,30 @@
|
|
1
1
|
module Kamal::Cli::Healthcheck::Poller
|
2
2
|
extend self
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
def wait_for_healthy(pause_after_ready: false, &block)
|
4
|
+
def wait_for_healthy(role, &block)
|
8
5
|
attempt = 1
|
9
|
-
|
6
|
+
timeout_at = Time.now + KAMAL.config.deploy_timeout
|
7
|
+
readiness_delay = KAMAL.config.readiness_delay
|
10
8
|
|
11
9
|
begin
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
if attempt <= max_attempts
|
22
|
-
info "#{e.message}, retrying in #{attempt}s (attempt #{attempt}/#{max_attempts})..."
|
23
|
-
sleep attempt
|
24
|
-
attempt += 1
|
25
|
-
retry
|
26
|
-
else
|
27
|
-
raise
|
10
|
+
status = block.call
|
11
|
+
|
12
|
+
if status == "running"
|
13
|
+
# Wait for the readiness delay and confirm it is still running
|
14
|
+
if readiness_delay > 0
|
15
|
+
info "Container is running, waiting for readiness delay of #{readiness_delay} seconds"
|
16
|
+
sleep readiness_delay
|
17
|
+
status = block.call
|
18
|
+
end
|
28
19
|
end
|
29
|
-
end
|
30
20
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
def wait_for_unhealthy(pause_after_ready: false, &block)
|
35
|
-
attempt = 1
|
36
|
-
max_attempts = KAMAL.config.healthcheck.max_attempts
|
37
|
-
|
38
|
-
begin
|
39
|
-
case status = block.call
|
40
|
-
when "unhealthy"
|
41
|
-
sleep TRAEFIK_UPDATE_DELAY if pause_after_ready
|
42
|
-
else
|
43
|
-
raise Kamal::Cli::Healthcheck::Error, "container not unhealthy (#{status})"
|
21
|
+
unless %w[ running healthy ].include?(status)
|
22
|
+
raise Kamal::Cli::Healthcheck::Error, "container not ready after #{KAMAL.config.deploy_timeout} seconds (#{status})"
|
44
23
|
end
|
45
24
|
rescue Kamal::Cli::Healthcheck::Error => e
|
46
|
-
|
47
|
-
|
48
|
-
sleep attempt
|
25
|
+
time_left = timeout_at - Time.now
|
26
|
+
if time_left > 0
|
27
|
+
sleep [ attempt, time_left ].min
|
49
28
|
attempt += 1
|
50
29
|
retry
|
51
30
|
else
|
@@ -53,7 +32,7 @@ module Kamal::Cli::Healthcheck::Poller
|
|
53
32
|
end
|
54
33
|
end
|
55
34
|
|
56
|
-
info "Container is
|
35
|
+
info "Container is healthy!"
|
57
36
|
end
|
58
37
|
|
59
38
|
private
|
data/lib/kamal/cli/lock.rb
CHANGED
@@ -3,7 +3,6 @@ class Kamal::Cli::Lock < Kamal::Cli::Base
|
|
3
3
|
def status
|
4
4
|
handle_missing_lock do
|
5
5
|
on(KAMAL.primary_host) do
|
6
|
-
execute *KAMAL.server.ensure_run_directory
|
7
6
|
puts capture_with_debug(*KAMAL.lock.status)
|
8
7
|
end
|
9
8
|
end
|
@@ -13,9 +12,10 @@ class Kamal::Cli::Lock < Kamal::Cli::Base
|
|
13
12
|
option :message, aliases: "-m", type: :string, desc: "A lock message", required: true
|
14
13
|
def acquire
|
15
14
|
message = options[:message]
|
15
|
+
ensure_run_directory
|
16
|
+
|
16
17
|
raise_if_locked do
|
17
18
|
on(KAMAL.primary_host) do
|
18
|
-
execute *KAMAL.server.ensure_run_directory
|
19
19
|
execute *KAMAL.lock.acquire(message, KAMAL.config.version), verbosity: :debug
|
20
20
|
end
|
21
21
|
say "Acquired the deploy lock"
|
@@ -26,7 +26,6 @@ class Kamal::Cli::Lock < Kamal::Cli::Base
|
|
26
26
|
def release
|
27
27
|
handle_missing_lock do
|
28
28
|
on(KAMAL.primary_host) do
|
29
|
-
execute *KAMAL.server.ensure_run_directory
|
30
29
|
execute *KAMAL.lock.release, verbosity: :debug
|
31
30
|
end
|
32
31
|
say "Released the deploy lock"
|