Compare commits
14 Commits
v1.7.1
...
xiaohui-zh
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e7ebaa5abd | ||
|
|
b12de87388 | ||
|
|
1573cebadf | ||
|
|
85a2926cde | ||
|
|
58a51b079e | ||
|
|
f1f3fc566f | ||
|
|
9a1379be6c | ||
|
|
31d6c198da | ||
|
|
22afe4de77 | ||
|
|
b63982c3a7 | ||
|
|
9e12d32cc3 | ||
|
|
ff03891d47 | ||
|
|
f21dc30875 | ||
|
|
69fa7286e2 |
@@ -1,7 +1,7 @@
|
|||||||
PATH
|
PATH
|
||||||
remote: .
|
remote: .
|
||||||
specs:
|
specs:
|
||||||
kamal (1.7.1)
|
kamal (1.7.3)
|
||||||
activesupport (>= 7.0)
|
activesupport (>= 7.0)
|
||||||
base64 (~> 0.2)
|
base64 (~> 0.2)
|
||||||
bcrypt_pbkdf (~> 1.0)
|
bcrypt_pbkdf (~> 1.0)
|
||||||
|
|||||||
@@ -43,8 +43,8 @@ class Kamal::Cli::Build < Kamal::Cli::Base
|
|||||||
cli.create
|
cli.create
|
||||||
end
|
end
|
||||||
rescue SSHKit::Command::Failed => e
|
rescue SSHKit::Command::Failed => e
|
||||||
|
if e.message =~ /(context not found|no builder|does not exist)/
|
||||||
warn "Missing compatible builder, so creating a new one first"
|
warn "Missing compatible builder, so creating a new one first"
|
||||||
if e.message =~ /(context not found|no builder)/
|
|
||||||
cli.create
|
cli.create
|
||||||
else
|
else
|
||||||
raise
|
raise
|
||||||
|
|||||||
@@ -1,7 +1,13 @@
|
|||||||
#!/bin/sh
|
#!/usr/bin/env ruby
|
||||||
|
|
||||||
# A sample docker-setup hook
|
# 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
|
# Runs remotely
|
||||||
def record(line, **details)
|
def record(line, **details)
|
||||||
append \
|
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
|
audit_log_file
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ module Kamal::Commands::Builder::Clone
|
|||||||
end
|
end
|
||||||
|
|
||||||
def clone
|
def clone
|
||||||
git :clone, Kamal::Git.root, path: clone_directory
|
git :clone, Kamal::Git.root, "--recurse-submodules", path: clone_directory
|
||||||
end
|
end
|
||||||
|
|
||||||
def clone_reset_steps
|
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(:remote, "set-url", :origin, Kamal::Git.root, path: build_directory),
|
||||||
git(:fetch, :origin, path: build_directory),
|
git(:fetch, :origin, path: build_directory),
|
||||||
git(:reset, "--hard", Kamal::Git.revision, 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
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -31,9 +31,9 @@ class Kamal::Configuration::Validator
|
|||||||
validate_array_of! value, example_value.first.class
|
validate_array_of! value, example_value.first.class
|
||||||
elsif example_value.is_a?(Hash)
|
elsif example_value.is_a?(Hash)
|
||||||
case key.to_s
|
case key.to_s
|
||||||
when "options"
|
when "options", "args"
|
||||||
validate_type! value, Hash
|
validate_type! value, Hash
|
||||||
when "args", "labels"
|
when "labels"
|
||||||
validate_hash_of! value, example_value.first[1].class
|
validate_hash_of! value, example_value.first[1].class
|
||||||
else
|
else
|
||||||
validate_against_example! value, example_value
|
validate_against_example! value, example_value
|
||||||
|
|||||||
@@ -13,7 +13,8 @@ class Kamal::Tags
|
|||||||
performer: `whoami`.chomp,
|
performer: `whoami`.chomp,
|
||||||
destination: config.destination,
|
destination: config.destination,
|
||||||
version: config.version,
|
version: config.version,
|
||||||
service_version: service_version(config) }
|
service_version: service_version(config),
|
||||||
|
service: config.service }
|
||||||
end
|
end
|
||||||
|
|
||||||
def service_version(config)
|
def service_version(config)
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
module Kamal
|
module Kamal
|
||||||
VERSION = "1.7.1"
|
VERSION = "1.7.3"
|
||||||
end
|
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(:docker, "--version", "&&", :docker, :buildx, "version")
|
||||||
|
|
||||||
SSHKit::Backend::Abstract.any_instance.expects(:execute)
|
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"))
|
.raises(SSHKit::Command::Failed.new("fatal: destination path 'kamal' already exists and is not an empty directory"))
|
||||||
.then
|
.then
|
||||||
.returns(true)
|
.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, :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, :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, :clean, "-fdx")
|
||||||
|
SSHKit::Backend::Abstract.any_instance.expects(:execute).with(:git, "-C", build_directory, :submodule, :update, "--init")
|
||||||
|
|
||||||
SSHKit::Backend::Abstract.any_instance.expects(:execute)
|
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", ".")
|
.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(:docker, "--version", "&&", :docker, :buildx, "version")
|
||||||
|
|
||||||
SSHKit::Backend::Abstract.any_instance.expects(:execute)
|
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"))
|
.raises(SSHKit::Command::Failed.new("fatal: destination path 'kamal' already exists and is not an empty directory"))
|
||||||
.then
|
.then
|
||||||
.returns(true)
|
.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)
|
def assert_hook_ran(hook, output, version:, service_version:, hosts:, command:, subcommand: nil, runtime: false)
|
||||||
performer = `whoami`.strip
|
performer = `whoami`.strip
|
||||||
|
service = service_version.split("@").first
|
||||||
|
|
||||||
assert_match "Running the #{hook} hook...\n", output
|
assert_match "Running the #{hook} hook...\n", output
|
||||||
|
|
||||||
@@ -52,6 +53,7 @@ class CliTestCase < ActiveSupport::TestCase
|
|||||||
KAMAL_PERFORMER=\"#{performer}\"\s
|
KAMAL_PERFORMER=\"#{performer}\"\s
|
||||||
KAMAL_VERSION=\"#{version}\"\s
|
KAMAL_VERSION=\"#{version}\"\s
|
||||||
KAMAL_SERVICE_VERSION=\"#{service_version}\"\s
|
KAMAL_SERVICE_VERSION=\"#{service_version}\"\s
|
||||||
|
KAMAL_SERVICE=\"#{service}\"\s
|
||||||
KAMAL_HOSTS=\"#{hosts}\"\s
|
KAMAL_HOSTS=\"#{hosts}\"\s
|
||||||
KAMAL_COMMAND=\"#{command}\"\s
|
KAMAL_COMMAND=\"#{command}\"\s
|
||||||
#{"KAMAL_SUBCOMMAND=\\\"#{subcommand}\\\"\\s" if subcommand}
|
#{"KAMAL_SUBCOMMAND=\\\"#{subcommand}\\\"\\s" if subcommand}
|
||||||
|
|||||||
@@ -22,7 +22,8 @@ class CommandsHookTest < ActiveSupport::TestCase
|
|||||||
"KAMAL_RECORDED_AT" => @recorded_at,
|
"KAMAL_RECORDED_AT" => @recorded_at,
|
||||||
"KAMAL_PERFORMER" => @performer,
|
"KAMAL_PERFORMER" => @performer,
|
||||||
"KAMAL_VERSION" => "123",
|
"KAMAL_VERSION" => "123",
|
||||||
"KAMAL_SERVICE_VERSION" => "app@123" } }
|
"KAMAL_SERVICE_VERSION" => "app@123",
|
||||||
|
"KAMAL_SERVICE" => "app" } }
|
||||||
], new_command.run("foo")
|
], new_command.run("foo")
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -33,7 +34,8 @@ class CommandsHookTest < ActiveSupport::TestCase
|
|||||||
"KAMAL_RECORDED_AT" => @recorded_at,
|
"KAMAL_RECORDED_AT" => @recorded_at,
|
||||||
"KAMAL_PERFORMER" => @performer,
|
"KAMAL_PERFORMER" => @performer,
|
||||||
"KAMAL_VERSION" => "123",
|
"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")
|
], new_command(hooks_path: "custom/hooks/path").run("foo")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -111,6 +111,11 @@ class CommandsTraefikTest < ActiveSupport::TestCase
|
|||||||
new_command.run.join(" ")
|
new_command.run.join(" ")
|
||||||
end
|
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
|
test "traefik start" do
|
||||||
assert_equal \
|
assert_equal \
|
||||||
"docker container start traefik",
|
"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/remote: unknown key: foo", builder: { "remote" => { "foo" => "bar" } }
|
||||||
assert_error "builder/local: unknown key: foo", builder: { "local" => { "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/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" => [] } }
|
assert_error "builder/cache/options: should be a string", builder: { "cache" => { "options" => [] } }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
version: "3.7"
|
|
||||||
name: "kamal-test"
|
name: "kamal-test"
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
|
|||||||
Reference in New Issue
Block a user