Compare commits
19 Commits
v1.7.0
...
xiaohui-zh
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e7ebaa5abd | ||
|
|
b12de87388 | ||
|
|
1573cebadf | ||
|
|
85a2926cde | ||
|
|
58a51b079e | ||
|
|
f1f3fc566f | ||
|
|
9a1379be6c | ||
|
|
31d6c198da | ||
|
|
22afe4de77 | ||
|
|
b63982c3a7 | ||
|
|
9e12d32cc3 | ||
|
|
ff03891d47 | ||
|
|
f21dc30875 | ||
|
|
69fa7286e2 | ||
|
|
4697f89441 | ||
|
|
dde637ffff | ||
|
|
f8f88af534 | ||
|
|
f6a9698f55 | ||
|
|
3da7fad9ee |
@@ -1,7 +1,7 @@
|
||||
PATH
|
||||
remote: .
|
||||
specs:
|
||||
kamal (1.7.0)
|
||||
kamal (1.7.3)
|
||||
activesupport (>= 7.0)
|
||||
base64 (~> 0.2)
|
||||
bcrypt_pbkdf (~> 1.0)
|
||||
|
||||
@@ -14,7 +14,7 @@ class Kamal::Cli::App < Kamal::Cli::Base
|
||||
end
|
||||
|
||||
# Primary hosts and roles are returned first, so they can open the barrier
|
||||
barrier = Kamal::Cli::Healthcheck::Barrier.new if KAMAL.roles.many?
|
||||
barrier = Kamal::Cli::Healthcheck::Barrier.new
|
||||
|
||||
on(KAMAL.hosts, **KAMAL.boot_strategy) do |host|
|
||||
KAMAL.roles_on(host).each do |role|
|
||||
|
||||
@@ -72,7 +72,7 @@ class Kamal::Cli::App::Boot
|
||||
|
||||
def release_barrier
|
||||
if barrier.open
|
||||
info "First #{KAMAL.primary_role} container is healthy on #{host}, booting other roles"
|
||||
info "First #{KAMAL.primary_role} container is healthy on #{host}, booting any other roles"
|
||||
end
|
||||
end
|
||||
|
||||
@@ -87,7 +87,7 @@ class Kamal::Cli::App::Boot
|
||||
|
||||
def close_barrier
|
||||
if barrier.close
|
||||
info "First #{KAMAL.primary_role} container is unhealthy on #{host}, not booting other roles"
|
||||
info "First #{KAMAL.primary_role} container is unhealthy on #{host}, not booting any other roles"
|
||||
error capture_with_info(*app.logs(version: version))
|
||||
error capture_with_info(*app.container_health_log(version: version))
|
||||
end
|
||||
|
||||
@@ -43,8 +43,8 @@ class Kamal::Cli::Build < Kamal::Cli::Base
|
||||
cli.create
|
||||
end
|
||||
rescue SSHKit::Command::Failed => e
|
||||
warn "Missing compatible builder, so creating a new one first"
|
||||
if e.message =~ /(context not found|no builder)/
|
||||
if e.message =~ /(context not found|no builder|does not exist)/
|
||||
warn "Missing compatible builder, so creating a new one first"
|
||||
cli.create
|
||||
else
|
||||
raise
|
||||
|
||||
@@ -11,6 +11,7 @@ class Kamal::Cli::Main < Kamal::Cli::Base
|
||||
|
||||
say "Evaluate and push env files...", :magenta
|
||||
invoke "kamal:cli:main:envify", [], invoke_options
|
||||
invoke "kamal:cli:env:push", [], invoke_options
|
||||
|
||||
invoke "kamal:cli:accessory:boot", [ "all" ], invoke_options
|
||||
deploy
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
#!/bin/sh
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
# A sample docker-setup hook
|
||||
#
|
||||
# Sets up a Docker network which can then be used by the application’s containers
|
||||
# Sets up a Docker network on defined hosts which can then be used by the application’s containers
|
||||
|
||||
ssh user@example.com docker network create kamal
|
||||
hosts = ENV["KAMAL_HOSTS"].split(",")
|
||||
|
||||
hosts.each do |ip|
|
||||
destination = "root@#{ip}"
|
||||
puts "Creating a Docker network \"kamal\" on #{destination}"
|
||||
`ssh #{destination} docker network create kamal`
|
||||
end
|
||||
|
||||
@@ -9,7 +9,7 @@ class Kamal::Commands::Auditor < Kamal::Commands::Base
|
||||
# Runs remotely
|
||||
def record(line, **details)
|
||||
append \
|
||||
[ :echo, audit_tags(**details).except(:version, :service_version).to_s, line ],
|
||||
[ :echo, audit_tags(**details).except(:version, :service_version, :service).to_s, line ],
|
||||
audit_log_file
|
||||
end
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ module Kamal::Commands::Builder::Clone
|
||||
end
|
||||
|
||||
def clone
|
||||
git :clone, Kamal::Git.root, path: clone_directory
|
||||
git :clone, Kamal::Git.root, "--recurse-submodules", path: clone_directory
|
||||
end
|
||||
|
||||
def clone_reset_steps
|
||||
@@ -14,7 +14,8 @@ module Kamal::Commands::Builder::Clone
|
||||
git(:remote, "set-url", :origin, Kamal::Git.root, path: build_directory),
|
||||
git(:fetch, :origin, path: build_directory),
|
||||
git(:reset, "--hard", Kamal::Git.revision, path: build_directory),
|
||||
git(:clean, "-fdx", path: build_directory)
|
||||
git(:clean, "-fdx", path: build_directory),
|
||||
git(:submodule, :update, "--init", path: build_directory)
|
||||
]
|
||||
end
|
||||
|
||||
|
||||
@@ -31,9 +31,9 @@ class Kamal::Configuration::Validator
|
||||
validate_array_of! value, example_value.first.class
|
||||
elsif example_value.is_a?(Hash)
|
||||
case key.to_s
|
||||
when "options"
|
||||
when "options", "args"
|
||||
validate_type! value, Hash
|
||||
when "args", "labels"
|
||||
when "labels"
|
||||
validate_hash_of! value, example_value.first[1].class
|
||||
else
|
||||
validate_against_example! value, example_value
|
||||
|
||||
@@ -13,7 +13,8 @@ class Kamal::Tags
|
||||
performer: `whoami`.chomp,
|
||||
destination: config.destination,
|
||||
version: config.version,
|
||||
service_version: service_version(config) }
|
||||
service_version: service_version(config),
|
||||
service: config.service }
|
||||
end
|
||||
|
||||
def service_version(config)
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
module Kamal
|
||||
VERSION = "1.7.0"
|
||||
VERSION = "1.7.3"
|
||||
end
|
||||
|
||||
@@ -42,7 +42,7 @@ class CliBuildTest < CliTestCase
|
||||
SSHKit::Backend::Abstract.any_instance.expects(:execute).with(:docker, "--version", "&&", :docker, :buildx, "version")
|
||||
|
||||
SSHKit::Backend::Abstract.any_instance.expects(:execute)
|
||||
.with(:git, "-C", "#{Dir.tmpdir}/kamal-clones/app-#{pwd_sha}", :clone, Dir.pwd)
|
||||
.with(:git, "-C", "#{Dir.tmpdir}/kamal-clones/app-#{pwd_sha}", :clone, Dir.pwd, "--recurse-submodules")
|
||||
.raises(SSHKit::Command::Failed.new("fatal: destination path 'kamal' already exists and is not an empty directory"))
|
||||
.then
|
||||
.returns(true)
|
||||
@@ -50,6 +50,7 @@ class CliBuildTest < CliTestCase
|
||||
SSHKit::Backend::Abstract.any_instance.expects(:execute).with(:git, "-C", build_directory, :fetch, :origin)
|
||||
SSHKit::Backend::Abstract.any_instance.expects(:execute).with(:git, "-C", build_directory, :reset, "--hard", Kamal::Git.revision)
|
||||
SSHKit::Backend::Abstract.any_instance.expects(:execute).with(:git, "-C", build_directory, :clean, "-fdx")
|
||||
SSHKit::Backend::Abstract.any_instance.expects(:execute).with(:git, "-C", build_directory, :submodule, :update, "--init")
|
||||
|
||||
SSHKit::Backend::Abstract.any_instance.expects(:execute)
|
||||
.with(:docker, :buildx, :build, "--push", "--platform", "linux/amd64,linux/arm64", "--builder", "kamal-app-multiarch", "-t", "dhh/app:999", "-t", "dhh/app:latest", "--label", "service=\"app\"", "--file", "Dockerfile", ".")
|
||||
@@ -88,7 +89,7 @@ class CliBuildTest < CliTestCase
|
||||
SSHKit::Backend::Abstract.any_instance.expects(:execute).with(:docker, "--version", "&&", :docker, :buildx, "version")
|
||||
|
||||
SSHKit::Backend::Abstract.any_instance.expects(:execute)
|
||||
.with(:git, "-C", "#{Dir.tmpdir}/kamal-clones/app-#{pwd_sha}", :clone, Dir.pwd)
|
||||
.with(:git, "-C", "#{Dir.tmpdir}/kamal-clones/app-#{pwd_sha}", :clone, Dir.pwd, "--recurse-submodules")
|
||||
.raises(SSHKit::Command::Failed.new("fatal: destination path 'kamal' already exists and is not an empty directory"))
|
||||
.then
|
||||
.returns(true)
|
||||
|
||||
@@ -43,6 +43,7 @@ class CliTestCase < ActiveSupport::TestCase
|
||||
|
||||
def assert_hook_ran(hook, output, version:, service_version:, hosts:, command:, subcommand: nil, runtime: false)
|
||||
performer = `whoami`.strip
|
||||
service = service_version.split("@").first
|
||||
|
||||
assert_match "Running the #{hook} hook...\n", output
|
||||
|
||||
@@ -52,6 +53,7 @@ class CliTestCase < ActiveSupport::TestCase
|
||||
KAMAL_PERFORMER=\"#{performer}\"\s
|
||||
KAMAL_VERSION=\"#{version}\"\s
|
||||
KAMAL_SERVICE_VERSION=\"#{service_version}\"\s
|
||||
KAMAL_SERVICE=\"#{service}\"\s
|
||||
KAMAL_HOSTS=\"#{hosts}\"\s
|
||||
KAMAL_COMMAND=\"#{command}\"\s
|
||||
#{"KAMAL_SUBCOMMAND=\\\"#{subcommand}\\\"\\s" if subcommand}
|
||||
|
||||
@@ -6,6 +6,7 @@ class CliMainTest < CliTestCase
|
||||
|
||||
Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:server:bootstrap", [], invoke_options)
|
||||
Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:main:envify", [], invoke_options)
|
||||
Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:env:push", [], invoke_options)
|
||||
Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:accessory:boot", [ "all" ], invoke_options)
|
||||
Kamal::Cli::Main.any_instance.expects(:deploy)
|
||||
|
||||
@@ -19,6 +20,7 @@ class CliMainTest < CliTestCase
|
||||
invoke_options = { "config_file" => "test/fixtures/deploy_simple.yml", "version" => "999", "skip_hooks" => false }
|
||||
|
||||
Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:server:bootstrap", [], invoke_options)
|
||||
Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:env:push", [], invoke_options)
|
||||
Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:main:envify", [], invoke_options)
|
||||
Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:accessory:boot", [ "all" ], invoke_options)
|
||||
# deploy
|
||||
|
||||
@@ -22,7 +22,8 @@ class CommandsHookTest < ActiveSupport::TestCase
|
||||
"KAMAL_RECORDED_AT" => @recorded_at,
|
||||
"KAMAL_PERFORMER" => @performer,
|
||||
"KAMAL_VERSION" => "123",
|
||||
"KAMAL_SERVICE_VERSION" => "app@123" } }
|
||||
"KAMAL_SERVICE_VERSION" => "app@123",
|
||||
"KAMAL_SERVICE" => "app" } }
|
||||
], new_command.run("foo")
|
||||
end
|
||||
|
||||
@@ -33,7 +34,8 @@ class CommandsHookTest < ActiveSupport::TestCase
|
||||
"KAMAL_RECORDED_AT" => @recorded_at,
|
||||
"KAMAL_PERFORMER" => @performer,
|
||||
"KAMAL_VERSION" => "123",
|
||||
"KAMAL_SERVICE_VERSION" => "app@123" } }
|
||||
"KAMAL_SERVICE_VERSION" => "app@123",
|
||||
"KAMAL_SERVICE" => "app" } }
|
||||
], new_command(hooks_path: "custom/hooks/path").run("foo")
|
||||
end
|
||||
|
||||
|
||||
@@ -111,6 +111,11 @@ class CommandsTraefikTest < ActiveSupport::TestCase
|
||||
new_command.run.join(" ")
|
||||
end
|
||||
|
||||
test "run with args array" do
|
||||
@config[:traefik]["args"] = { "entrypoints.web.forwardedheaders.trustedips" => %w[ 127.0.0.1 127.0.0.2 ] }
|
||||
assert_equal "docker run --name traefik --detach --restart unless-stopped --publish 80:80 --volume /var/run/docker.sock:/var/run/docker.sock --env-file .kamal/env/traefik/traefik.env --log-opt max-size=\"10m\" --label traefik.http.routers.catchall.entryPoints=\"http\" --label traefik.http.routers.catchall.rule=\"PathPrefix(\\`/\\`)\" --label traefik.http.routers.catchall.service=\"unavailable\" --label traefik.http.routers.catchall.priority=\"1\" --label traefik.http.services.unavailable.loadbalancer.server.port=\"0\" traefik:test --providers.docker --log.level=\"DEBUG\" --entrypoints.web.forwardedheaders.trustedips=\"127.0.0.1\" --entrypoints.web.forwardedheaders.trustedips=\"127.0.0.2\"", new_command.run.join(" ")
|
||||
end
|
||||
|
||||
test "traefik start" do
|
||||
assert_equal \
|
||||
"docker container start traefik",
|
||||
|
||||
@@ -94,7 +94,7 @@ class ConfigurationValidationTest < ActiveSupport::TestCase
|
||||
assert_error "builder/remote: unknown key: foo", builder: { "remote" => { "foo" => "bar" } }
|
||||
assert_error "builder/local: unknown key: foo", builder: { "local" => { "foo" => "bar" } }
|
||||
assert_error "builder/remote/arch: should be a string", builder: { "remote" => { "arch" => [] } }
|
||||
assert_error "builder/args/foo: should be a string", builder: { "args" => { "foo" => [] } }
|
||||
assert_error "builder/args: should be a hash", builder: { "args" => [ "foo" ] }
|
||||
assert_error "builder/cache/options: should be a string", builder: { "cache" => { "options" => [] } }
|
||||
end
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ class BrokenDeployTest < IntegrationTest
|
||||
private
|
||||
def assert_failed_deploy(output)
|
||||
assert_match "Waiting for the first healthy web container before booting workers on vm3...", output
|
||||
assert_match /First web container is unhealthy on vm[12], not booting other roles/, output
|
||||
assert_match /First web container is unhealthy on vm[12], not booting any other roles/, output
|
||||
assert_match "First web container is unhealthy, not booting workers on vm3", output
|
||||
assert_match "nginx: [emerg] unexpected end of file, expecting \";\" or \"}\" in /etc/nginx/conf.d/default.conf:2", output
|
||||
assert_match 'ERROR {"Status":"unhealthy","FailingStreak":0,"Log":[]}', output
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
version: "3.7"
|
||||
name: "kamal-test"
|
||||
|
||||
volumes:
|
||||
|
||||
Reference in New Issue
Block a user