Add Rubocop
- Pull in the 37signals house style - Autofix violations - Add to CI
This commit is contained in:
15
.github/workflows/ci.yml
vendored
15
.github/workflows/ci.yml
vendored
@@ -5,6 +5,21 @@ on:
|
|||||||
- main
|
- main
|
||||||
pull_request:
|
pull_request:
|
||||||
jobs:
|
jobs:
|
||||||
|
rubocop:
|
||||||
|
name: RuboCop
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
BUNDLE_ONLY: rubocop
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup Ruby and install gems
|
||||||
|
uses: ruby/setup-ruby@v1
|
||||||
|
with:
|
||||||
|
ruby-version: 3.3.0
|
||||||
|
bundler-cache: true
|
||||||
|
- name: Run Rubocop
|
||||||
|
run: bundle exec rubocop --parallel
|
||||||
tests:
|
tests:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
|
|||||||
1
.rubocop.yml
Normal file
1
.rubocop.yml
Normal file
@@ -0,0 +1 @@
|
|||||||
|
inherit_gem: { rubocop-37signals: rubocop.yml }
|
||||||
6
Gemfile
6
Gemfile
@@ -1,4 +1,8 @@
|
|||||||
source 'https://rubygems.org'
|
source "https://rubygems.org"
|
||||||
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
|
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
|
||||||
|
|
||||||
gemspec
|
gemspec
|
||||||
|
|
||||||
|
group :rubocop do
|
||||||
|
gem "rubocop-37signals", github: "basecamp/house-style", require: false
|
||||||
|
end
|
||||||
|
|||||||
47
Gemfile.lock
47
Gemfile.lock
@@ -1,3 +1,13 @@
|
|||||||
|
GIT
|
||||||
|
remote: https://github.com/basecamp/house-style.git
|
||||||
|
revision: a9ca7e4ab80b72c1a10053c50efefe8cd275e3b8
|
||||||
|
specs:
|
||||||
|
rubocop-37signals (1.0.0)
|
||||||
|
rubocop
|
||||||
|
rubocop-minitest
|
||||||
|
rubocop-performance
|
||||||
|
rubocop-rails
|
||||||
|
|
||||||
PATH
|
PATH
|
||||||
remote: .
|
remote: .
|
||||||
specs:
|
specs:
|
||||||
@@ -42,6 +52,7 @@ GEM
|
|||||||
minitest (>= 5.1)
|
minitest (>= 5.1)
|
||||||
mutex_m
|
mutex_m
|
||||||
tzinfo (~> 2.0)
|
tzinfo (~> 2.0)
|
||||||
|
ast (2.4.2)
|
||||||
base64 (0.2.0)
|
base64 (0.2.0)
|
||||||
bcrypt_pbkdf (1.1.0)
|
bcrypt_pbkdf (1.1.0)
|
||||||
bigdecimal (3.1.5)
|
bigdecimal (3.1.5)
|
||||||
@@ -63,6 +74,8 @@ GEM
|
|||||||
irb (1.11.0)
|
irb (1.11.0)
|
||||||
rdoc
|
rdoc
|
||||||
reline (>= 0.3.8)
|
reline (>= 0.3.8)
|
||||||
|
json (2.7.1)
|
||||||
|
language_server-protocol (3.17.0.3)
|
||||||
loofah (2.22.0)
|
loofah (2.22.0)
|
||||||
crass (~> 1.0.2)
|
crass (~> 1.0.2)
|
||||||
nokogiri (>= 1.12.0)
|
nokogiri (>= 1.12.0)
|
||||||
@@ -79,6 +92,10 @@ GEM
|
|||||||
racc (~> 1.4)
|
racc (~> 1.4)
|
||||||
nokogiri (1.16.0-x86_64-linux)
|
nokogiri (1.16.0-x86_64-linux)
|
||||||
racc (~> 1.4)
|
racc (~> 1.4)
|
||||||
|
parallel (1.24.0)
|
||||||
|
parser (3.3.0.5)
|
||||||
|
ast (~> 2.4.1)
|
||||||
|
racc
|
||||||
psych (5.1.2)
|
psych (5.1.2)
|
||||||
stringio
|
stringio
|
||||||
racc (1.7.3)
|
racc (1.7.3)
|
||||||
@@ -105,11 +122,39 @@ GEM
|
|||||||
rake (>= 12.2)
|
rake (>= 12.2)
|
||||||
thor (~> 1.0, >= 1.2.2)
|
thor (~> 1.0, >= 1.2.2)
|
||||||
zeitwerk (~> 2.6)
|
zeitwerk (~> 2.6)
|
||||||
|
rainbow (3.1.1)
|
||||||
rake (13.1.0)
|
rake (13.1.0)
|
||||||
rdoc (6.6.2)
|
rdoc (6.6.2)
|
||||||
psych (>= 4.0.0)
|
psych (>= 4.0.0)
|
||||||
|
regexp_parser (2.9.0)
|
||||||
reline (0.4.2)
|
reline (0.4.2)
|
||||||
io-console (~> 0.5)
|
io-console (~> 0.5)
|
||||||
|
rexml (3.2.6)
|
||||||
|
rubocop (1.61.0)
|
||||||
|
json (~> 2.3)
|
||||||
|
language_server-protocol (>= 3.17.0)
|
||||||
|
parallel (~> 1.10)
|
||||||
|
parser (>= 3.3.0.2)
|
||||||
|
rainbow (>= 2.2.2, < 4.0)
|
||||||
|
regexp_parser (>= 1.8, < 3.0)
|
||||||
|
rexml (>= 3.2.5, < 4.0)
|
||||||
|
rubocop-ast (>= 1.30.0, < 2.0)
|
||||||
|
ruby-progressbar (~> 1.7)
|
||||||
|
unicode-display_width (>= 2.4.0, < 3.0)
|
||||||
|
rubocop-ast (1.31.1)
|
||||||
|
parser (>= 3.3.0.4)
|
||||||
|
rubocop-minitest (0.34.5)
|
||||||
|
rubocop (>= 1.39, < 2.0)
|
||||||
|
rubocop-ast (>= 1.30.0, < 2.0)
|
||||||
|
rubocop-performance (1.20.2)
|
||||||
|
rubocop (>= 1.48.1, < 2.0)
|
||||||
|
rubocop-ast (>= 1.30.0, < 2.0)
|
||||||
|
rubocop-rails (2.24.0)
|
||||||
|
activesupport (>= 4.2.0)
|
||||||
|
rack (>= 1.1)
|
||||||
|
rubocop (>= 1.33.0, < 2.0)
|
||||||
|
rubocop-ast (>= 1.31.1, < 2.0)
|
||||||
|
ruby-progressbar (1.13.0)
|
||||||
ruby2_keywords (0.0.5)
|
ruby2_keywords (0.0.5)
|
||||||
sshkit (1.21.7)
|
sshkit (1.21.7)
|
||||||
mutex_m
|
mutex_m
|
||||||
@@ -119,6 +164,7 @@ GEM
|
|||||||
thor (1.3.0)
|
thor (1.3.0)
|
||||||
tzinfo (2.0.6)
|
tzinfo (2.0.6)
|
||||||
concurrent-ruby (~> 1.0)
|
concurrent-ruby (~> 1.0)
|
||||||
|
unicode-display_width (2.5.0)
|
||||||
webrick (1.8.1)
|
webrick (1.8.1)
|
||||||
zeitwerk (2.6.12)
|
zeitwerk (2.6.12)
|
||||||
|
|
||||||
@@ -132,6 +178,7 @@ DEPENDENCIES
|
|||||||
kamal!
|
kamal!
|
||||||
mocha
|
mocha
|
||||||
railties
|
railties
|
||||||
|
rubocop-37signals!
|
||||||
|
|
||||||
BUNDLED WITH
|
BUNDLED WITH
|
||||||
2.4.3
|
2.4.3
|
||||||
|
|||||||
@@ -177,7 +177,7 @@ class Kamal::Cli::Accessory < Kamal::Cli::Base
|
|||||||
if name == "all"
|
if name == "all"
|
||||||
KAMAL.accessory_names.each { |accessory_name| remove(accessory_name) }
|
KAMAL.accessory_names.each { |accessory_name| remove(accessory_name) }
|
||||||
else
|
else
|
||||||
if options[:confirmed] || ask("This will remove all containers, images and data directories for #{name}. Are you sure?", limited_to: %w( y N ), default: "N") == "y"
|
if options[:confirmed] || ask("This will remove all containers, images and data directories for #{name}. Are you sure?", limited_to: %w[ y N ], default: "N") == "y"
|
||||||
with_accessory(name) do
|
with_accessory(name) do
|
||||||
stop(name)
|
stop(name)
|
||||||
remove_container(name)
|
remove_container(name)
|
||||||
|
|||||||
@@ -207,7 +207,7 @@ class Kamal::Cli::App < Kamal::Cli::Base
|
|||||||
run_locally do
|
run_locally do
|
||||||
info "Following logs on #{KAMAL.primary_host}..."
|
info "Following logs on #{KAMAL.primary_host}..."
|
||||||
|
|
||||||
KAMAL.specific_roles ||= ["web"]
|
KAMAL.specific_roles ||= [ "web" ]
|
||||||
role = KAMAL.roles_on(KAMAL.primary_host).first
|
role = KAMAL.roles_on(KAMAL.primary_host).first
|
||||||
|
|
||||||
info KAMAL.app(role: role).follow_logs(host: KAMAL.primary_host, lines: lines, grep: grep)
|
info KAMAL.app(role: role).follow_logs(host: KAMAL.primary_host, lines: lines, grep: grep)
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ module Kamal::Cli
|
|||||||
def print_runtime
|
def print_runtime
|
||||||
started_at = Time.now
|
started_at = Time.now
|
||||||
yield
|
yield
|
||||||
return Time.now - started_at
|
Time.now - started_at
|
||||||
ensure
|
ensure
|
||||||
runtime = Time.now - started_at
|
runtime = Time.now - started_at
|
||||||
puts " Finished all in #{sprintf("%.1f seconds", runtime)}"
|
puts " Finished all in #{sprintf("%.1f seconds", runtime)}"
|
||||||
@@ -181,5 +181,5 @@ module Kamal::Cli
|
|||||||
execute(*KAMAL.server.ensure_run_directory)
|
execute(*KAMAL.server.ensure_run_directory)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -197,7 +197,7 @@ class Kamal::Cli::Main < Kamal::Cli::Base
|
|||||||
option :confirmed, aliases: "-y", type: :boolean, default: false, desc: "Proceed without confirmation question"
|
option :confirmed, aliases: "-y", type: :boolean, default: false, desc: "Proceed without confirmation question"
|
||||||
def remove
|
def remove
|
||||||
mutating do
|
mutating do
|
||||||
if options[:confirmed] || ask("This will remove all containers and images. Are you sure?", limited_to: %w( y N ), default: "N") == "y"
|
if options[:confirmed] || ask("This will remove all containers and images. Are you sure?", limited_to: %w[ y N ], default: "N") == "y"
|
||||||
invoke "kamal:cli:traefik:remove", [], options.without(:confirmed)
|
invoke "kamal:cli:traefik:remove", [], options.without(:confirmed)
|
||||||
invoke "kamal:cli:app:remove", [], options.without(:confirmed)
|
invoke "kamal:cli:app:remove", [], options.without(:confirmed)
|
||||||
invoke "kamal:cli:accessory:remove", [ "all" ], options
|
invoke "kamal:cli:accessory:remove", [ "all" ], options
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ class Kamal::Cli::Traefik < Kamal::Cli::Base
|
|||||||
option :rolling, type: :boolean, default: false, desc: "Reboot traefik on hosts in sequence, rather than in parallel"
|
option :rolling, type: :boolean, default: false, desc: "Reboot traefik on hosts in sequence, rather than in parallel"
|
||||||
def reboot
|
def reboot
|
||||||
mutating do
|
mutating do
|
||||||
host_groups = options[:rolling] ? KAMAL.traefik_hosts : [KAMAL.traefik_hosts]
|
host_groups = options[:rolling] ? KAMAL.traefik_hosts : [ KAMAL.traefik_hosts ]
|
||||||
host_groups.each do |hosts|
|
host_groups.each do |hosts|
|
||||||
host_list = Array(hosts).join(",")
|
host_list = Array(hosts).join(",")
|
||||||
run_hook "pre-traefik-reboot", hosts: host_list
|
run_hook "pre-traefik-reboot", hosts: host_list
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ class Kamal::Commands::Accessory < Kamal::Commands::Base
|
|||||||
end
|
end
|
||||||
|
|
||||||
def remove_env_file
|
def remove_env_file
|
||||||
[:rm, "-f", accessory_config.host_env_file_path]
|
[ :rm, "-f", accessory_config.host_env_file_path ]
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ class Kamal::Commands::App < Kamal::Commands::Base
|
|||||||
"--detach",
|
"--detach",
|
||||||
"--restart unless-stopped",
|
"--restart unless-stopped",
|
||||||
"--name", container_name,
|
"--name", container_name,
|
||||||
*(["--hostname", hostname] if hostname),
|
*([ "--hostname", hostname ] if hostname),
|
||||||
"-e", "KAMAL_CONTAINER_NAME=\"#{container_name}\"",
|
"-e", "KAMAL_CONTAINER_NAME=\"#{container_name}\"",
|
||||||
"-e", "KAMAL_VERSION=\"#{config.version}\"",
|
"-e", "KAMAL_VERSION=\"#{config.version}\"",
|
||||||
*role.env_args,
|
*role.env_args,
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ module Kamal::Commands::App::Assets
|
|||||||
|
|
||||||
combine \
|
combine \
|
||||||
make_directory(role.asset_extracted_path),
|
make_directory(role.asset_extracted_path),
|
||||||
[*docker(:stop, "-t 1", asset_container, "2> /dev/null"), "|| true"],
|
[ *docker(:stop, "-t 1", asset_container, "2> /dev/null"), "|| true" ],
|
||||||
docker(:run, "--name", asset_container, "--detach", "--rm", config.latest_image, "sleep 1000000"),
|
docker(:run, "--name", asset_container, "--detach", "--rm", config.latest_image, "sleep 1000000"),
|
||||||
docker(:cp, "-L", "#{asset_container}:#{role.asset_path}/.", role.asset_extracted_path),
|
docker(:cp, "-L", "#{asset_container}:#{role.asset_path}/.", role.asset_extracted_path),
|
||||||
docker(:stop, "-t 1", asset_container),
|
docker(:stop, "-t 1", asset_container),
|
||||||
@@ -17,7 +17,7 @@ module Kamal::Commands::App::Assets
|
|||||||
old_extracted_path, old_volume_path = role.asset_extracted_path(old_version), role.asset_volume(old_version).host_path
|
old_extracted_path, old_volume_path = role.asset_extracted_path(old_version), role.asset_volume(old_version).host_path
|
||||||
end
|
end
|
||||||
|
|
||||||
commands = [make_directory(new_volume_path), copy_contents(new_extracted_path, new_volume_path)]
|
commands = [ make_directory(new_volume_path), copy_contents(new_extracted_path, new_volume_path) ]
|
||||||
|
|
||||||
if old_version.present?
|
if old_version.present?
|
||||||
commands << copy_contents(new_extracted_path, old_volume_path, continue_on_error: true)
|
commands << copy_contents(new_extracted_path, old_volume_path, continue_on_error: true)
|
||||||
@@ -46,6 +46,6 @@ module Kamal::Commands::App::Assets
|
|||||||
end
|
end
|
||||||
|
|
||||||
def copy_contents(source, destination, continue_on_error: false)
|
def copy_contents(source, destination, continue_on_error: false)
|
||||||
[ :cp, "-rnT", "#{source}", destination, *("|| true" if continue_on_error)]
|
[ :cp, "-rnT", "#{source}", destination, *("|| true" if continue_on_error) ]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ module Kamal::Commands::App::Cord
|
|||||||
def cord(version:)
|
def cord(version:)
|
||||||
pipe \
|
pipe \
|
||||||
docker(:inspect, "-f '{{ range .Mounts }}{{printf \"%s %s\\n\" .Source .Destination}}{{ end }}'", container_name(version)),
|
docker(:inspect, "-f '{{ range .Mounts }}{{printf \"%s %s\\n\" .Source .Destination}}{{ end }}'", container_name(version)),
|
||||||
[:awk, "'$2 == \"#{role.cord_volume.container_path}\" {print $1}'"]
|
[ :awk, "'$2 == \"#{role.cord_volume.container_path}\" {print $1}'" ]
|
||||||
end
|
end
|
||||||
|
|
||||||
def tie_cord(cord)
|
def tie_cord(cord)
|
||||||
@@ -17,6 +17,6 @@ module Kamal::Commands::App::Cord
|
|||||||
def create_empty_file(file)
|
def create_empty_file(file)
|
||||||
chain \
|
chain \
|
||||||
make_directory_for(file),
|
make_directory_for(file),
|
||||||
[:touch, file]
|
[ :touch, file ]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ class Kamal::Commands::Builder::Base < Kamal::Commands::Base
|
|||||||
pipe \
|
pipe \
|
||||||
docker(:inspect, "-f", "'{{ .Config.Labels.service }}'", config.absolute_image),
|
docker(:inspect, "-f", "'{{ .Config.Labels.service }}'", config.absolute_image),
|
||||||
any(
|
any(
|
||||||
[:grep, "-x", config.service],
|
[ :grep, "-x", config.service ],
|
||||||
"(echo \"Image #{config.absolute_image} is missing the 'service' label\" && exit 1)"
|
"(echo \"Image #{config.absolute_image} is missing the 'service' label\" && exit 1)"
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
@@ -38,8 +38,8 @@ class Kamal::Commands::Builder::Base < Kamal::Commands::Base
|
|||||||
|
|
||||||
def build_cache
|
def build_cache
|
||||||
if cache_to && cache_from
|
if cache_to && cache_from
|
||||||
["--cache-to", cache_to,
|
[ "--cache-to", cache_to,
|
||||||
"--cache-from", cache_from]
|
"--cache-from", cache_from ]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
class Kamal::Commands::Healthcheck < Kamal::Commands::Base
|
class Kamal::Commands::Healthcheck < Kamal::Commands::Base
|
||||||
|
|
||||||
def run
|
def run
|
||||||
primary = config.role(config.primary_role)
|
primary = config.role(config.primary_role)
|
||||||
|
|
||||||
|
|||||||
@@ -5,14 +5,14 @@ require "base64"
|
|||||||
class Kamal::Commands::Lock < Kamal::Commands::Base
|
class Kamal::Commands::Lock < Kamal::Commands::Base
|
||||||
def acquire(message, version)
|
def acquire(message, version)
|
||||||
combine \
|
combine \
|
||||||
[:mkdir, lock_dir],
|
[ :mkdir, lock_dir ],
|
||||||
write_lock_details(message, version)
|
write_lock_details(message, version)
|
||||||
end
|
end
|
||||||
|
|
||||||
def release
|
def release
|
||||||
combine \
|
combine \
|
||||||
[:rm, lock_details_file],
|
[ :rm, lock_details_file ],
|
||||||
[:rm, "-r", lock_dir]
|
[ :rm, "-r", lock_dir ]
|
||||||
end
|
end
|
||||||
|
|
||||||
def status
|
def status
|
||||||
@@ -24,19 +24,19 @@ class Kamal::Commands::Lock < Kamal::Commands::Base
|
|||||||
private
|
private
|
||||||
def write_lock_details(message, version)
|
def write_lock_details(message, version)
|
||||||
write \
|
write \
|
||||||
[:echo, "\"#{Base64.encode64(lock_details(message, version))}\""],
|
[ :echo, "\"#{Base64.encode64(lock_details(message, version))}\"" ],
|
||||||
lock_details_file
|
lock_details_file
|
||||||
end
|
end
|
||||||
|
|
||||||
def read_lock_details
|
def read_lock_details
|
||||||
pipe \
|
pipe \
|
||||||
[:cat, lock_details_file],
|
[ :cat, lock_details_file ],
|
||||||
[:base64, "-d"]
|
[ :base64, "-d" ]
|
||||||
end
|
end
|
||||||
|
|
||||||
def stat_lock_dir
|
def stat_lock_dir
|
||||||
write \
|
write \
|
||||||
[:stat, lock_dir],
|
[ :stat, lock_dir ],
|
||||||
"/dev/null"
|
"/dev/null"
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ class Kamal::Commands::Lock < Kamal::Commands::Base
|
|||||||
end
|
end
|
||||||
|
|
||||||
def lock_details_file
|
def lock_details_file
|
||||||
[lock_dir, :details].join("/")
|
[ lock_dir, :details ].join("/")
|
||||||
end
|
end
|
||||||
|
|
||||||
def lock_details(message, version)
|
def lock_details(message, version)
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ class Kamal::Commands::Prune < Kamal::Commands::Base
|
|||||||
|
|
||||||
private
|
private
|
||||||
def stopped_containers_filters
|
def stopped_containers_filters
|
||||||
[ "created", "exited", "dead" ].flat_map { |status| ["--filter", "status=#{status}"] }
|
[ "created", "exited", "dead" ].flat_map { |status| [ "--filter", "status=#{status}" ] }
|
||||||
end
|
end
|
||||||
|
|
||||||
def active_image_list
|
def active_image_list
|
||||||
@@ -43,4 +43,4 @@ class Kamal::Commands::Prune < Kamal::Commands::Base
|
|||||||
def healthcheck_service_filter
|
def healthcheck_service_filter
|
||||||
[ "--filter", "label=service=#{config.healthcheck_service}" ]
|
[ "--filter", "label=service=#{config.healthcheck_service}" ]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
class Kamal::Commands::Server < Kamal::Commands::Base
|
class Kamal::Commands::Server < Kamal::Commands::Base
|
||||||
def ensure_run_directory
|
def ensure_run_directory
|
||||||
[:mkdir, "-p", config.run_directory]
|
[ :mkdir, "-p", config.run_directory ]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ class Kamal::Commands::Traefik < Kamal::Commands::Base
|
|||||||
DEFAULT_IMAGE = "traefik:v2.10"
|
DEFAULT_IMAGE = "traefik:v2.10"
|
||||||
CONTAINER_PORT = 80
|
CONTAINER_PORT = 80
|
||||||
DEFAULT_ARGS = {
|
DEFAULT_ARGS = {
|
||||||
'log.level' => 'DEBUG'
|
"log.level" => "DEBUG"
|
||||||
}
|
}
|
||||||
DEFAULT_LABELS = {
|
DEFAULT_LABELS = {
|
||||||
# These ensure we serve a 502 rather than a 404 if no containers are available
|
# These ensure we serve a 502 rather than a 404 if no containers are available
|
||||||
@@ -84,7 +84,7 @@ class Kamal::Commands::Traefik < Kamal::Commands::Base
|
|||||||
end
|
end
|
||||||
|
|
||||||
def remove_env_file
|
def remove_env_file
|
||||||
[:rm, "-f", host_env_file_path]
|
[ :rm, "-f", host_env_file_path ]
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ class Kamal::Configuration::Accessory
|
|||||||
end
|
end
|
||||||
|
|
||||||
def hosts
|
def hosts
|
||||||
if (specifics.keys & ["host", "hosts", "roles"]).size != 1
|
if (specifics.keys & [ "host", "hosts", "roles" ]).size != 1
|
||||||
raise ArgumentError, "Specify one of `host`, `hosts` or `roles` for accessory `#{name}`"
|
raise ArgumentError, "Specify one of `host`, `hosts` or `roles` for accessory `#{name}`"
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -159,7 +159,7 @@ class Kamal::Configuration::Accessory
|
|||||||
if specifics.key?("host")
|
if specifics.key?("host")
|
||||||
host = specifics["host"]
|
host = specifics["host"]
|
||||||
if host
|
if host
|
||||||
[host]
|
[ host ]
|
||||||
else
|
else
|
||||||
raise ArgumentError, "Missing host for accessory `#{name}`"
|
raise ArgumentError, "Missing host for accessory `#{name}`"
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class Kamal::Configuration::Boot
|
|||||||
limit = @options["limit"]
|
limit = @options["limit"]
|
||||||
|
|
||||||
if limit.to_s.end_with?("%")
|
if limit.to_s.end_with?("%")
|
||||||
[@host_count * limit.to_i / 100, 1].max
|
[ @host_count * limit.to_i / 100, 1 ].max
|
||||||
else
|
else
|
||||||
limit
|
limit
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ class Kamal::Configuration::Builder
|
|||||||
private
|
private
|
||||||
def valid?
|
def valid?
|
||||||
if @options["cache"] && @options["cache"]["type"]
|
if @options["cache"] && @options["cache"]["type"]
|
||||||
raise ArgumentError, "Invalid cache type: #{@options["cache"]["type"]}" unless ["gha", "registry"].include?(@options["cache"]["type"])
|
raise ArgumentError, "Invalid cache type: #{@options["cache"]["type"]}" unless [ "gha", "registry" ].include?(@options["cache"]["type"])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -109,7 +109,7 @@ class Kamal::Configuration::Builder
|
|||||||
end
|
end
|
||||||
|
|
||||||
def cache_to_config_for_gha
|
def cache_to_config_for_gha
|
||||||
[ "type=gha", @options["cache"]&.fetch("options", nil)].compact.join(",")
|
[ "type=gha", @options["cache"]&.fetch("options", nil) ].compact.join(",")
|
||||||
end
|
end
|
||||||
|
|
||||||
def cache_to_config_for_registry
|
def cache_to_config_for_registry
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ class Kamal::Configuration::Role
|
|||||||
end
|
end
|
||||||
|
|
||||||
def host_env_file_path
|
def host_env_file_path
|
||||||
File.join host_env_directory, "#{[config.service, name, config.destination].compact.join("-")}.env"
|
File.join host_env_directory, "#{[ config.service, name, config.destination ].compact.join("-")}.env"
|
||||||
end
|
end
|
||||||
|
|
||||||
def env_args
|
def env_args
|
||||||
@@ -123,13 +123,13 @@ class Kamal::Configuration::Role
|
|||||||
end
|
end
|
||||||
|
|
||||||
def cord_host_directory
|
def cord_host_directory
|
||||||
File.join config.run_directory_as_docker_volume, "cords", [container_prefix, config.run_id].join("-")
|
File.join config.run_directory_as_docker_volume, "cords", [ container_prefix, config.run_id ].join("-")
|
||||||
end
|
end
|
||||||
|
|
||||||
def cord_volume
|
def cord_volume
|
||||||
if (cord = health_check_options["cord"])
|
if (cord = health_check_options["cord"])
|
||||||
@cord_volume ||= Kamal::Configuration::Volume.new \
|
@cord_volume ||= Kamal::Configuration::Volume.new \
|
||||||
host_path: File.join(config.run_directory, "cords", [container_prefix, config.run_id].join("-")),
|
host_path: File.join(config.run_directory, "cords", [ container_prefix, config.run_id ].join("-")),
|
||||||
container_path: cord
|
container_path: cord
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -229,7 +229,7 @@ class Kamal::Configuration::Role
|
|||||||
|
|
||||||
def specializations
|
def specializations
|
||||||
if config.servers.is_a?(Array) || config.servers[name].is_a?(Array)
|
if config.servers.is_a?(Array) || config.servers[name].is_a?(Array)
|
||||||
{ }
|
{}
|
||||||
else
|
else
|
||||||
config.servers[name].except("hosts")
|
config.servers[name].except("hosts")
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ class Kamal::EnvFile
|
|||||||
|
|
||||||
private
|
private
|
||||||
def docker_env_file_line(key, value)
|
def docker_env_file_line(key, value)
|
||||||
"#{key.to_s}=#{escape_docker_env_file_value(value)}\n"
|
"#{key}=#{escape_docker_env_file_value(value)}\n"
|
||||||
end
|
end
|
||||||
|
|
||||||
# Escape a value to make it safe to dump in a docker file.
|
# Escape a value to make it safe to dump in a docker file.
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ module Kamal::Utils
|
|||||||
if value.present?
|
if value.present?
|
||||||
attr = "#{key}=#{escape_shell_value(value)}"
|
attr = "#{key}=#{escape_shell_value(value)}"
|
||||||
attr = self.sensitive(attr, redaction: "#{key}=[REDACTED]") if sensitive
|
attr = self.sensitive(attr, redaction: "#{key}=[REDACTED]") if sensitive
|
||||||
[ argument, attr]
|
[ argument, attr ]
|
||||||
else
|
else
|
||||||
[ argument, key ]
|
[ argument, key ]
|
||||||
end
|
end
|
||||||
@@ -29,7 +29,7 @@ module Kamal::Utils
|
|||||||
|
|
||||||
# Flattens a one-to-many structure into an array of two-element arrays each containing a key-value pair
|
# Flattens a one-to-many structure into an array of two-element arrays each containing a key-value pair
|
||||||
def flatten_args(args)
|
def flatten_args(args)
|
||||||
args.flat_map { |key, value| value.try(:map) { |entry| [key, entry] } || [ [ key, value ] ] }
|
args.flat_map { |key, value| value.try(:map) { |entry| [ key, entry ] } || [ [ key, value ] ] }
|
||||||
end
|
end
|
||||||
|
|
||||||
# Marks sensitive values for redaction in logs and human-visible output.
|
# Marks sensitive values for redaction in logs and human-visible output.
|
||||||
@@ -66,7 +66,7 @@ module Kamal::Utils
|
|||||||
Array(filters).select do |filter|
|
Array(filters).select do |filter|
|
||||||
matches += Array(items).select do |item|
|
matches += Array(items).select do |item|
|
||||||
# Only allow * for a wildcard
|
# Only allow * for a wildcard
|
||||||
pattern = Regexp.escape(filter).gsub('\*', '.*')
|
pattern = Regexp.escape(filter).gsub('\*', ".*")
|
||||||
# items are roles or hosts
|
# items are roles or hosts
|
||||||
(item.respond_to?(:name) ? item.name : item).match(/^#{pattern}$/)
|
(item.respond_to?(:name) ? item.name : item).match(/^#{pattern}$/)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -154,9 +154,9 @@ class CliAccessoryTest < CliTestCase
|
|||||||
|
|
||||||
run_command("boot", "redis", "--hosts", "1.1.1.1").tap do |output|
|
run_command("boot", "redis", "--hosts", "1.1.1.1").tap do |output|
|
||||||
assert_match /docker login.*on 1.1.1.1/, output
|
assert_match /docker login.*on 1.1.1.1/, output
|
||||||
refute_match /docker login.*on 1.1.1.2/, output
|
assert_no_match /docker login.*on 1.1.1.2/, output
|
||||||
assert_match "docker run --name app-redis --detach --restart unless-stopped --log-opt max-size=\"10m\" --publish 6379:6379 --env-file .kamal/env/accessories/app-redis.env --volume $PWD/app-redis/data:/data --label service=\"app-redis\" redis:latest on 1.1.1.1", output
|
assert_match "docker run --name app-redis --detach --restart unless-stopped --log-opt max-size=\"10m\" --publish 6379:6379 --env-file .kamal/env/accessories/app-redis.env --volume $PWD/app-redis/data:/data --label service=\"app-redis\" redis:latest on 1.1.1.1", output
|
||||||
refute_match "docker run --name app-redis --detach --restart unless-stopped --log-opt max-size=\"10m\" --publish 6379:6379 --env-file .kamal/env/accessories/app-redis.env --volume $PWD/app-redis/data:/data --label service=\"app-redis\" redis:latest on 1.1.1.2", output
|
assert_no_match "docker run --name app-redis --detach --restart unless-stopped --log-opt max-size=\"10m\" --publish 6379:6379 --env-file .kamal/env/accessories/app-redis.env --volume $PWD/app-redis/data:/data --label service=\"app-redis\" redis:latest on 1.1.1.2", output
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -166,14 +166,14 @@ class CliAccessoryTest < CliTestCase
|
|||||||
|
|
||||||
run_command("boot", "redis", "--hosts", "1.1.1.1,1.1.1.3").tap do |output|
|
run_command("boot", "redis", "--hosts", "1.1.1.1,1.1.1.3").tap do |output|
|
||||||
assert_match /docker login.*on 1.1.1.1/, output
|
assert_match /docker login.*on 1.1.1.1/, output
|
||||||
refute_match /docker login.*on 1.1.1.3/, output
|
assert_no_match /docker login.*on 1.1.1.3/, output
|
||||||
assert_match "docker run --name app-redis --detach --restart unless-stopped --log-opt max-size=\"10m\" --publish 6379:6379 --env-file .kamal/env/accessories/app-redis.env --volume $PWD/app-redis/data:/data --label service=\"app-redis\" redis:latest on 1.1.1.1", output
|
assert_match "docker run --name app-redis --detach --restart unless-stopped --log-opt max-size=\"10m\" --publish 6379:6379 --env-file .kamal/env/accessories/app-redis.env --volume $PWD/app-redis/data:/data --label service=\"app-redis\" redis:latest on 1.1.1.1", output
|
||||||
refute_match "docker run --name app-redis --detach --restart unless-stopped --log-opt max-size=\"10m\" --publish 6379:6379 --env-file .kamal/env/accessories/app-redis.env --volume $PWD/app-redis/data:/data --label service=\"app-redis\" redis:latest on 1.1.1.3", output
|
assert_no_match "docker run --name app-redis --detach --restart unless-stopped --log-opt max-size=\"10m\" --publish 6379:6379 --env-file .kamal/env/accessories/app-redis.env --volume $PWD/app-redis/data:/data --label service=\"app-redis\" redis:latest on 1.1.1.3", output
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
def run_command(*command)
|
def run_command(*command)
|
||||||
stdouted { Kamal::Cli::Accessory.start([*command, "-c", "test/fixtures/deploy_with_accessories.yml"]) }
|
stdouted { Kamal::Cli::Accessory.start([ *command, "-c", "test/fixtures/deploy_with_accessories.yml" ]) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ class CliAppTest < CliTestCase
|
|||||||
.returns("123") # old version
|
.returns("123") # old version
|
||||||
|
|
||||||
SSHKit::Backend::Abstract.any_instance.expects(:capture_with_info)
|
SSHKit::Backend::Abstract.any_instance.expects(:capture_with_info)
|
||||||
.with(:docker, :inspect, "-f '{{ range .Mounts }}{{printf \"%s %s\\n\" .Source .Destination}}{{ end }}'", "app-web-123", "|", :awk, "'$2 == \"/tmp/kamal-cord\" {print $1}'", :raise_on_non_zero_exit => false)
|
.with(:docker, :inspect, "-f '{{ range .Mounts }}{{printf \"%s %s\\n\" .Source .Destination}}{{ end }}'", "app-web-123", "|", :awk, "'$2 == \"/tmp/kamal-cord\" {print $1}'", raise_on_non_zero_exit: false)
|
||||||
.returns("cordfile") # old version
|
.returns("cordfile") # old version
|
||||||
|
|
||||||
SSHKit::Backend::Abstract.any_instance.expects(:capture_with_info)
|
SSHKit::Backend::Abstract.any_instance.expects(:capture_with_info)
|
||||||
@@ -57,7 +57,7 @@ class CliAppTest < CliTestCase
|
|||||||
test "boot errors leave lock in place" do
|
test "boot errors leave lock in place" do
|
||||||
Kamal::Cli::App.any_instance.expects(:using_version).raises(RuntimeError)
|
Kamal::Cli::App.any_instance.expects(:using_version).raises(RuntimeError)
|
||||||
|
|
||||||
assert !KAMAL.holding_lock?
|
assert_not KAMAL.holding_lock?
|
||||||
assert_raises(RuntimeError) do
|
assert_raises(RuntimeError) do
|
||||||
stderred { run_command("boot") }
|
stderred { run_command("boot") }
|
||||||
end
|
end
|
||||||
@@ -79,7 +79,7 @@ class CliAppTest < CliTestCase
|
|||||||
.returns("123").twice # old version
|
.returns("123").twice # old version
|
||||||
|
|
||||||
SSHKit::Backend::Abstract.any_instance.expects(:capture_with_info)
|
SSHKit::Backend::Abstract.any_instance.expects(:capture_with_info)
|
||||||
.with(:docker, :inspect, "-f '{{ range .Mounts }}{{printf \"%s %s\\n\" .Source .Destination}}{{ end }}'", "app-web-123", "|", :awk, "'$2 == \"/tmp/kamal-cord\" {print $1}'", :raise_on_non_zero_exit => false)
|
.with(:docker, :inspect, "-f '{{ range .Mounts }}{{printf \"%s %s\\n\" .Source .Destination}}{{ end }}'", "app-web-123", "|", :awk, "'$2 == \"/tmp/kamal-cord\" {print $1}'", raise_on_non_zero_exit: false)
|
||||||
.returns("") # old version
|
.returns("") # old version
|
||||||
|
|
||||||
run_command("boot", config: :with_assets).tap do |output|
|
run_command("boot", config: :with_assets).tap do |output|
|
||||||
@@ -223,14 +223,14 @@ class CliAppTest < CliTestCase
|
|||||||
|
|
||||||
|
|
||||||
test "version through main" do
|
test "version through main" do
|
||||||
stdouted { Kamal::Cli::Main.start(["app", "version", "-c", "test/fixtures/deploy_with_accessories.yml", "--hosts", "1.1.1.1"]) }.tap do |output|
|
stdouted { Kamal::Cli::Main.start([ "app", "version", "-c", "test/fixtures/deploy_with_accessories.yml", "--hosts", "1.1.1.1" ]) }.tap do |output|
|
||||||
assert_match "docker ps --filter label=service=app --filter label=role=web --filter status=running --filter status=restarting --latest --format \"{{.Names}}\" | while read line; do echo ${line#app-web-}; done", output
|
assert_match "docker ps --filter label=service=app --filter label=role=web --filter status=running --filter status=restarting --latest --format \"{{.Names}}\" | while read line; do echo ${line#app-web-}; done", output
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
def run_command(*command, config: :with_accessories)
|
def run_command(*command, config: :with_accessories)
|
||||||
stdouted { Kamal::Cli::App.start([*command, "-c", "test/fixtures/deploy_#{config}.yml", "--hosts", "1.1.1.1"]) }
|
stdouted { Kamal::Cli::App.start([ *command, "-c", "test/fixtures/deploy_#{config}.yml", "--hosts", "1.1.1.1" ]) }
|
||||||
end
|
end
|
||||||
|
|
||||||
def stub_running
|
def stub_running
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ class CliBuildTest < CliTestCase
|
|||||||
.with(:docker, "--version", "&&", :docker, :buildx, "version")
|
.with(:docker, "--version", "&&", :docker, :buildx, "version")
|
||||||
|
|
||||||
SSHKit::Backend::Abstract.any_instance.stubs(:execute)
|
SSHKit::Backend::Abstract.any_instance.stubs(:execute)
|
||||||
.with { |*args| args[0..1] == [:docker, :buildx] }
|
.with { |*args| args[0..1] == [ :docker, :buildx ] }
|
||||||
.raises(SSHKit::Command::Failed.new("no builder"))
|
.raises(SSHKit::Command::Failed.new("no builder"))
|
||||||
.then
|
.then
|
||||||
.returns(true)
|
.returns(true)
|
||||||
@@ -50,7 +50,7 @@ class CliBuildTest < CliTestCase
|
|||||||
|
|
||||||
assert_raises(Kamal::Cli::HookError) { run_command("push") }
|
assert_raises(Kamal::Cli::HookError) { run_command("push") }
|
||||||
|
|
||||||
assert @executions.none? { |args| args[0..2] == [:docker, :buildx, :build] }
|
assert @executions.none? { |args| args[0..2] == [ :docker, :buildx, :build ] }
|
||||||
end
|
end
|
||||||
|
|
||||||
test "pull" do
|
test "pull" do
|
||||||
@@ -105,13 +105,13 @@ class CliBuildTest < CliTestCase
|
|||||||
|
|
||||||
private
|
private
|
||||||
def run_command(*command, fixture: :with_accessories)
|
def run_command(*command, fixture: :with_accessories)
|
||||||
stdouted { Kamal::Cli::Build.start([*command, "-c", "test/fixtures/deploy_#{fixture}.yml"]) }
|
stdouted { Kamal::Cli::Build.start([ *command, "-c", "test/fixtures/deploy_#{fixture}.yml" ]) }
|
||||||
end
|
end
|
||||||
|
|
||||||
def stub_dependency_checks
|
def stub_dependency_checks
|
||||||
SSHKit::Backend::Abstract.any_instance.stubs(:execute)
|
SSHKit::Backend::Abstract.any_instance.stubs(:execute)
|
||||||
.with(:docker, "--version", "&&", :docker, :buildx, "version")
|
.with(:docker, "--version", "&&", :docker, :buildx, "version")
|
||||||
SSHKit::Backend::Abstract.any_instance.stubs(:execute)
|
SSHKit::Backend::Abstract.any_instance.stubs(:execute)
|
||||||
.with { |*args| args[0..1] == [:docker, :buildx] }
|
.with { |*args| args[0..1] == [ :docker, :buildx ] }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ class CliTestCase < ActiveSupport::TestCase
|
|||||||
Kamal::Commands::Hook.any_instance.stubs(:hook_exists?).returns(true)
|
Kamal::Commands::Hook.any_instance.stubs(:hook_exists?).returns(true)
|
||||||
|
|
||||||
SSHKit::Backend::Abstract.any_instance.stubs(:execute)
|
SSHKit::Backend::Abstract.any_instance.stubs(:execute)
|
||||||
.with { |*args| @executions << args; args != [".kamal/hooks/#{hook}"] }
|
.with { |*args| @executions << args; args != [ ".kamal/hooks/#{hook}" ] }
|
||||||
SSHKit::Backend::Abstract.any_instance.stubs(:execute)
|
SSHKit::Backend::Abstract.any_instance.stubs(:execute)
|
||||||
.with { |*args| args.first == ".kamal/hooks/#{hook}" }
|
.with { |*args| args.first == ".kamal/hooks/#{hook}" }
|
||||||
.raises(SSHKit::Command::Failed.new("failed"))
|
.raises(SSHKit::Command::Failed.new("failed"))
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ class CliEnvTest < CliTestCase
|
|||||||
assert_match ".kamal/env/roles/app-workers.env", output
|
assert_match ".kamal/env/roles/app-workers.env", output
|
||||||
assert_match ".kamal/env/traefik/traefik.env", output
|
assert_match ".kamal/env/traefik/traefik.env", output
|
||||||
assert_match ".kamal/env/accessories/app-redis.env", output
|
assert_match ".kamal/env/accessories/app-redis.env", output
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -33,6 +32,6 @@ class CliEnvTest < CliTestCase
|
|||||||
|
|
||||||
private
|
private
|
||||||
def run_command(*command)
|
def run_command(*command)
|
||||||
stdouted { Kamal::Cli::Env.start([*command, "-c", "test/fixtures/deploy_with_accessories.yml"]) }
|
stdouted { Kamal::Cli::Env.start([ *command, "-c", "test/fixtures/deploy_with_accessories.yml" ]) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -77,6 +77,6 @@ class CliHealthcheckTest < CliTestCase
|
|||||||
|
|
||||||
private
|
private
|
||||||
def run_command(*command, config_file: "test/fixtures/deploy_with_accessories.yml")
|
def run_command(*command, config_file: "test/fixtures/deploy_with_accessories.yml")
|
||||||
stdouted { Kamal::Cli::Healthcheck.start([*command, "-c", config_file]) }
|
stdouted { Kamal::Cli::Healthcheck.start([ *command, "-c", config_file ]) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -15,6 +15,6 @@ class CliLockTest < CliTestCase
|
|||||||
|
|
||||||
private
|
private
|
||||||
def run_command(*command)
|
def run_command(*command)
|
||||||
stdouted { Kamal::Cli::Lock.start([*command, "-v", "-c", "test/fixtures/deploy_with_accessories.yml"]) }
|
stdouted { Kamal::Cli::Lock.start([ *command, "-v", "-c", "test/fixtures/deploy_with_accessories.yml" ]) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ class CliMainTest < CliTestCase
|
|||||||
.with { |*args| args == [ :mkdir, "-p", ".kamal" ] }
|
.with { |*args| args == [ :mkdir, "-p", ".kamal" ] }
|
||||||
|
|
||||||
SSHKit::Backend::Abstract.any_instance.stubs(:execute)
|
SSHKit::Backend::Abstract.any_instance.stubs(:execute)
|
||||||
.with { |*arg| arg[0..1] == [:mkdir, ".kamal/lock-app"] }
|
.with { |*arg| arg[0..1] == [ :mkdir, ".kamal/lock-app" ] }
|
||||||
.raises(RuntimeError, "mkdir: cannot create directory ‘kamal_lock-app’: File exists")
|
.raises(RuntimeError, "mkdir: cannot create directory ‘kamal_lock-app’: File exists")
|
||||||
|
|
||||||
SSHKit::Backend::Abstract.any_instance.expects(:capture_with_debug)
|
SSHKit::Backend::Abstract.any_instance.expects(:capture_with_debug)
|
||||||
@@ -120,7 +120,7 @@ class CliMainTest < CliTestCase
|
|||||||
.with { |*args| args == [ :mkdir, "-p", ".kamal" ] }
|
.with { |*args| args == [ :mkdir, "-p", ".kamal" ] }
|
||||||
|
|
||||||
SSHKit::Backend::Abstract.any_instance.stubs(:execute)
|
SSHKit::Backend::Abstract.any_instance.stubs(:execute)
|
||||||
.with { |*arg| arg[0..1] == [:mkdir, ".kamal/lock-app"] }
|
.with { |*arg| arg[0..1] == [ :mkdir, ".kamal/lock-app" ] }
|
||||||
.raises(SocketError, "getaddrinfo: nodename nor servname provided, or not known")
|
.raises(SocketError, "getaddrinfo: nodename nor servname provided, or not known")
|
||||||
|
|
||||||
assert_raises(SSHKit::Runner::ExecuteError) do
|
assert_raises(SSHKit::Runner::ExecuteError) do
|
||||||
@@ -135,11 +135,11 @@ class CliMainTest < CliTestCase
|
|||||||
.with("kamal:cli:registry:login", [], invoke_options)
|
.with("kamal:cli:registry:login", [], invoke_options)
|
||||||
.raises(RuntimeError)
|
.raises(RuntimeError)
|
||||||
|
|
||||||
assert !KAMAL.holding_lock?
|
assert_not KAMAL.holding_lock?
|
||||||
assert_raises(RuntimeError) do
|
assert_raises(RuntimeError) do
|
||||||
stderred { run_command("deploy") }
|
stderred { run_command("deploy") }
|
||||||
end
|
end
|
||||||
assert !KAMAL.holding_lock?
|
assert_not KAMAL.holding_lock?
|
||||||
end
|
end
|
||||||
|
|
||||||
test "deploy with skipped hooks" do
|
test "deploy with skipped hooks" do
|
||||||
@@ -154,7 +154,7 @@ class CliMainTest < CliTestCase
|
|||||||
Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:prune:all", [], invoke_options)
|
Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:prune:all", [], invoke_options)
|
||||||
|
|
||||||
run_command("deploy", "--skip_hooks") do
|
run_command("deploy", "--skip_hooks") do
|
||||||
refute_match /Running the post-deploy hook.../, output
|
assert_no_match /Running the post-deploy hook.../, output
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -252,7 +252,7 @@ class CliMainTest < CliTestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
SSHKit::Backend::Abstract.any_instance.expects(:capture_with_info)
|
SSHKit::Backend::Abstract.any_instance.expects(:capture_with_info)
|
||||||
.with(:docker, :inspect, "-f '{{ range .Mounts }}{{printf \"%s %s\\n\" .Source .Destination}}{{ end }}'", "app-web-version-to-rollback", "|", :awk, "'$2 == \"/tmp/kamal-cord\" {print $1}'", :raise_on_non_zero_exit => false)
|
.with(:docker, :inspect, "-f '{{ range .Mounts }}{{printf \"%s %s\\n\" .Source .Destination}}{{ end }}'", "app-web-version-to-rollback", "|", :awk, "'$2 == \"/tmp/kamal-cord\" {print $1}'", raise_on_non_zero_exit: false)
|
||||||
.returns("corddirectory").at_least_once # health check
|
.returns("corddirectory").at_least_once # health check
|
||||||
|
|
||||||
SSHKit::Backend::Abstract.any_instance.expects(:capture_with_info)
|
SSHKit::Backend::Abstract.any_instance.expects(:capture_with_info)
|
||||||
@@ -311,8 +311,8 @@ class CliMainTest < CliTestCase
|
|||||||
run_command("config", config_file: "deploy_simple").tap do |output|
|
run_command("config", config_file: "deploy_simple").tap do |output|
|
||||||
config = YAML.load(output)
|
config = YAML.load(output)
|
||||||
|
|
||||||
assert_equal ["web"], config[:roles]
|
assert_equal [ "web" ], config[:roles]
|
||||||
assert_equal ["1.1.1.1", "1.1.1.2"], config[:hosts]
|
assert_equal [ "1.1.1.1", "1.1.1.2" ], config[:hosts]
|
||||||
assert_equal "999", config[:version]
|
assert_equal "999", config[:version]
|
||||||
assert_equal "dhh/app", config[:repository]
|
assert_equal "dhh/app", config[:repository]
|
||||||
assert_equal "dhh/app:999", config[:absolute_image]
|
assert_equal "dhh/app:999", config[:absolute_image]
|
||||||
@@ -324,8 +324,8 @@ class CliMainTest < CliTestCase
|
|||||||
run_command("config", config_file: "deploy_with_roles").tap do |output|
|
run_command("config", config_file: "deploy_with_roles").tap do |output|
|
||||||
config = YAML.load(output)
|
config = YAML.load(output)
|
||||||
|
|
||||||
assert_equal ["web", "workers"], config[:roles]
|
assert_equal [ "web", "workers" ], config[:roles]
|
||||||
assert_equal ["1.1.1.1", "1.1.1.2", "1.1.1.3", "1.1.1.4"], config[:hosts]
|
assert_equal [ "1.1.1.1", "1.1.1.2", "1.1.1.3", "1.1.1.4" ], config[:hosts]
|
||||||
assert_equal "999", config[:version]
|
assert_equal "999", config[:version]
|
||||||
assert_equal "registry.digitalocean.com/dhh/app", config[:repository]
|
assert_equal "registry.digitalocean.com/dhh/app", config[:repository]
|
||||||
assert_equal "registry.digitalocean.com/dhh/app:999", config[:absolute_image]
|
assert_equal "registry.digitalocean.com/dhh/app:999", config[:absolute_image]
|
||||||
@@ -337,8 +337,8 @@ class CliMainTest < CliTestCase
|
|||||||
run_command("config", config_file: "deploy_primary_web_role_override").tap do |output|
|
run_command("config", config_file: "deploy_primary_web_role_override").tap do |output|
|
||||||
config = YAML.load(output)
|
config = YAML.load(output)
|
||||||
|
|
||||||
assert_equal ["web_chicago", "web_tokyo"], config[:roles]
|
assert_equal [ "web_chicago", "web_tokyo" ], config[:roles]
|
||||||
assert_equal ["1.1.1.1", "1.1.1.2", "1.1.1.3", "1.1.1.4"], config[:hosts]
|
assert_equal [ "1.1.1.1", "1.1.1.2", "1.1.1.3", "1.1.1.4" ], config[:hosts]
|
||||||
assert_equal "1.1.1.3", config[:primary_host]
|
assert_equal "1.1.1.3", config[:primary_host]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -347,8 +347,8 @@ class CliMainTest < CliTestCase
|
|||||||
run_command("config", "-d", "world", config_file: "deploy_for_dest").tap do |output|
|
run_command("config", "-d", "world", config_file: "deploy_for_dest").tap do |output|
|
||||||
config = YAML.load(output)
|
config = YAML.load(output)
|
||||||
|
|
||||||
assert_equal ["web"], config[:roles]
|
assert_equal [ "web" ], config[:roles]
|
||||||
assert_equal ["1.1.1.1", "1.1.1.2"], config[:hosts]
|
assert_equal [ "1.1.1.1", "1.1.1.2" ], config[:hosts]
|
||||||
assert_equal "999", config[:version]
|
assert_equal "999", config[:version]
|
||||||
assert_equal "registry.digitalocean.com/dhh/app", config[:repository]
|
assert_equal "registry.digitalocean.com/dhh/app", config[:repository]
|
||||||
assert_equal "registry.digitalocean.com/dhh/app:999", config[:absolute_image]
|
assert_equal "registry.digitalocean.com/dhh/app:999", config[:absolute_image]
|
||||||
@@ -360,8 +360,8 @@ class CliMainTest < CliTestCase
|
|||||||
run_command("config", config_file: "deploy_with_aliases").tap do |output|
|
run_command("config", config_file: "deploy_with_aliases").tap do |output|
|
||||||
config = YAML.load(output)
|
config = YAML.load(output)
|
||||||
|
|
||||||
assert_equal ["web", "web_tokyo", "workers", "workers_tokyo"], config[:roles]
|
assert_equal [ "web", "web_tokyo", "workers", "workers_tokyo" ], config[:roles]
|
||||||
assert_equal ["1.1.1.1", "1.1.1.2", "1.1.1.3", "1.1.1.4"], config[:hosts]
|
assert_equal [ "1.1.1.1", "1.1.1.2", "1.1.1.3", "1.1.1.4" ], config[:hosts]
|
||||||
assert_equal "999", config[:version]
|
assert_equal "999", config[:version]
|
||||||
assert_equal "registry.digitalocean.com/dhh/app", config[:repository]
|
assert_equal "registry.digitalocean.com/dhh/app", config[:repository]
|
||||||
assert_equal "registry.digitalocean.com/dhh/app:999", config[:absolute_image]
|
assert_equal "registry.digitalocean.com/dhh/app:999", config[:absolute_image]
|
||||||
@@ -487,6 +487,6 @@ class CliMainTest < CliTestCase
|
|||||||
|
|
||||||
private
|
private
|
||||||
def run_command(*command, config_file: "deploy_simple")
|
def run_command(*command, config_file: "deploy_simple")
|
||||||
stdouted { Kamal::Cli::Main.start([*command, "-c", "test/fixtures/#{config_file}.yml"]) }
|
stdouted { Kamal::Cli::Main.start([ *command, "-c", "test/fixtures/#{config_file}.yml" ]) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -33,6 +33,6 @@ class CliPruneTest < CliTestCase
|
|||||||
|
|
||||||
private
|
private
|
||||||
def run_command(*command)
|
def run_command(*command)
|
||||||
stdouted { Kamal::Cli::Prune.start([*command, "-c", "test/fixtures/deploy_with_accessories.yml"]) }
|
stdouted { Kamal::Cli::Prune.start([ *command, "-c", "test/fixtures/deploy_with_accessories.yml" ]) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -16,6 +16,6 @@ class CliRegistryTest < CliTestCase
|
|||||||
|
|
||||||
private
|
private
|
||||||
def run_command(*command)
|
def run_command(*command)
|
||||||
stdouted { Kamal::Cli::Registry.start([*command, "-c", "test/fixtures/deploy_with_accessories.yml"]) }
|
stdouted { Kamal::Cli::Registry.start([ *command, "-c", "test/fixtures/deploy_with_accessories.yml" ]) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -36,6 +36,6 @@ class CliServerTest < CliTestCase
|
|||||||
|
|
||||||
private
|
private
|
||||||
def run_command(*command)
|
def run_command(*command)
|
||||||
stdouted { Kamal::Cli::Server.start([*command, "-c", "test/fixtures/deploy_with_accessories.yml"]) }
|
stdouted { Kamal::Cli::Server.start([ *command, "-c", "test/fixtures/deploy_with_accessories.yml" ]) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -91,6 +91,6 @@ class CliTraefikTest < CliTestCase
|
|||||||
|
|
||||||
private
|
private
|
||||||
def run_command(*command)
|
def run_command(*command)
|
||||||
stdouted { Kamal::Cli::Traefik.start([*command, "-c", "test/fixtures/deploy_with_accessories.yml"]) }
|
stdouted { Kamal::Cli::Traefik.start([ *command, "-c", "test/fixtures/deploy_with_accessories.yml" ]) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -103,14 +103,14 @@ class CommandsAccessoryTest < ActiveSupport::TestCase
|
|||||||
|
|
||||||
test "execute in new container over ssh" do
|
test "execute in new container over ssh" do
|
||||||
new_command(:mysql).stub(:run_over_ssh, ->(cmd) { cmd.join(" ") }) do
|
new_command(:mysql).stub(:run_over_ssh, ->(cmd) { cmd.join(" ") }) do
|
||||||
assert_match %r|docker run -it --rm --env-file .kamal/env/accessories/app-mysql.env private.registry/mysql:8.0 mysql -u root|,
|
assert_match %r{docker run -it --rm --env-file .kamal/env/accessories/app-mysql.env private.registry/mysql:8.0 mysql -u root},
|
||||||
new_command(:mysql).execute_in_new_container_over_ssh("mysql", "-u", "root")
|
new_command(:mysql).execute_in_new_container_over_ssh("mysql", "-u", "root")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
test "execute in existing container over ssh" do
|
test "execute in existing container over ssh" do
|
||||||
new_command(:mysql).stub(:run_over_ssh, ->(cmd) { cmd.join(" ") }) do
|
new_command(:mysql).stub(:run_over_ssh, ->(cmd) { cmd.join(" ") }) do
|
||||||
assert_match %r|docker exec -it app-mysql mysql -u root|,
|
assert_match %r{docker exec -it app-mysql mysql -u root},
|
||||||
new_command(:mysql).execute_in_existing_container_over_ssh("mysql", "-u", "root")
|
new_command(:mysql).execute_in_existing_container_over_ssh("mysql", "-u", "root")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ class CommandsAppTest < ActiveSupport::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
test "run with volumes" do
|
test "run with volumes" do
|
||||||
@config[:volumes] = ["/local/path:/container/path" ]
|
@config[:volumes] = [ "/local/path:/container/path" ]
|
||||||
|
|
||||||
assert_equal \
|
assert_equal \
|
||||||
"docker run --detach --restart unless-stopped --name app-web-999 -e KAMAL_CONTAINER_NAME=\"app-web-999\" -e KAMAL_VERSION=\"999\" --env-file .kamal/env/roles/app-web.env --health-cmd \"(curl -f http://localhost:3000/up || exit 1) && (stat /tmp/kamal-cord/cord > /dev/null || exit 1)\" --health-interval \"1s\" --volume $(pwd)/.kamal/cords/app-web-12345678901234567890123456789012:/tmp/kamal-cord --log-opt max-size=\"10m\" --volume /local/path:/container/path --label service=\"app\" --label role=\"web\" --label traefik.http.services.app-web.loadbalancer.server.scheme=\"http\" --label traefik.http.routers.app-web.rule=\"PathPrefix(\\`/\\`)\" --label traefik.http.routers.app-web.priority=\"2\" --label traefik.http.middlewares.app-web-retry.retry.attempts=\"5\" --label traefik.http.middlewares.app-web-retry.retry.initialinterval=\"500ms\" --label traefik.http.routers.app-web.middlewares=\"app-web-retry@docker\" dhh/app:999",
|
"docker run --detach --restart unless-stopped --name app-web-999 -e KAMAL_CONTAINER_NAME=\"app-web-999\" -e KAMAL_VERSION=\"999\" --env-file .kamal/env/roles/app-web.env --health-cmd \"(curl -f http://localhost:3000/up || exit 1) && (stat /tmp/kamal-cord/cord > /dev/null || exit 1)\" --health-interval \"1s\" --volume $(pwd)/.kamal/cords/app-web-12345678901234567890123456789012:/tmp/kamal-cord --log-opt max-size=\"10m\" --volume /local/path:/container/path --label service=\"app\" --label role=\"web\" --label traefik.http.services.app-web.loadbalancer.server.scheme=\"http\" --label traefik.http.routers.app-web.rule=\"PathPrefix(\\`/\\`)\" --label traefik.http.routers.app-web.priority=\"2\" --label traefik.http.middlewares.app-web-retry.retry.attempts=\"5\" --label traefik.http.middlewares.app-web-retry.retry.initialinterval=\"500ms\" --label traefik.http.routers.app-web.middlewares=\"app-web-retry@docker\" dhh/app:999",
|
||||||
@@ -191,18 +191,18 @@ class CommandsAppTest < ActiveSupport::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
test "execute in new container over ssh" do
|
test "execute in new container over ssh" do
|
||||||
assert_match %r|docker run -it --rm --env-file .kamal/env/roles/app-web.env dhh/app:999 bin/rails c|,
|
assert_match %r{docker run -it --rm --env-file .kamal/env/roles/app-web.env dhh/app:999 bin/rails c},
|
||||||
new_command.execute_in_new_container_over_ssh("bin/rails", "c", host: "app-1")
|
new_command.execute_in_new_container_over_ssh("bin/rails", "c", host: "app-1")
|
||||||
end
|
end
|
||||||
|
|
||||||
test "execute in new container with custom options over ssh" do
|
test "execute in new container with custom options over ssh" do
|
||||||
@config[:servers] = { "web" => { "hosts" => [ "1.1.1.1" ], "options" => { "mount" => "somewhere", "cap-add" => true } } }
|
@config[:servers] = { "web" => { "hosts" => [ "1.1.1.1" ], "options" => { "mount" => "somewhere", "cap-add" => true } } }
|
||||||
assert_match %r|docker run -it --rm --env-file .kamal/env/roles/app-web.env --mount \"somewhere\" --cap-add dhh/app:999 bin/rails c|,
|
assert_match %r{docker run -it --rm --env-file .kamal/env/roles/app-web.env --mount \"somewhere\" --cap-add dhh/app:999 bin/rails c},
|
||||||
new_command.execute_in_new_container_over_ssh("bin/rails", "c", host: "app-1")
|
new_command.execute_in_new_container_over_ssh("bin/rails", "c", host: "app-1")
|
||||||
end
|
end
|
||||||
|
|
||||||
test "execute in existing container over ssh" do
|
test "execute in existing container over ssh" do
|
||||||
assert_match %r|docker exec -it app-web-999 bin/rails c|,
|
assert_match %r{docker exec -it app-web-999 bin/rails c},
|
||||||
new_command.execute_in_existing_container_over_ssh("bin/rails", "c", host: "app-1")
|
new_command.execute_in_existing_container_over_ssh("bin/rails", "c", host: "app-1")
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -387,7 +387,7 @@ class CommandsAppTest < ActiveSupport::TestCase
|
|||||||
:mkdir, "-p", ".kamal/assets/volumes/app-web-999", ";",
|
:mkdir, "-p", ".kamal/assets/volumes/app-web-999", ";",
|
||||||
:cp, "-rnT", ".kamal/assets/extracted/app-web-999", ".kamal/assets/volumes/app-web-999", ";",
|
:cp, "-rnT", ".kamal/assets/extracted/app-web-999", ".kamal/assets/volumes/app-web-999", ";",
|
||||||
:cp, "-rnT", ".kamal/assets/extracted/app-web-999", ".kamal/assets/volumes/app-web-998", "|| true", ";",
|
:cp, "-rnT", ".kamal/assets/extracted/app-web-999", ".kamal/assets/volumes/app-web-998", "|| true", ";",
|
||||||
:cp, "-rnT", ".kamal/assets/extracted/app-web-998", ".kamal/assets/volumes/app-web-999", "|| true",
|
:cp, "-rnT", ".kamal/assets/extracted/app-web-998", ".kamal/assets/volumes/app-web-999", "|| true"
|
||||||
], new_command(asset_path: "/public/assets").sync_asset_volumes(old_version: 998)
|
], new_command(asset_path: "/public/assets").sync_asset_volumes(old_version: 998)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ class CommandsBuilderTest < ActiveSupport::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
test "target multiarch by default" do
|
test "target multiarch by default" do
|
||||||
builder = new_builder_command(builder: { "cache" => { "type" => "gha" }})
|
builder = new_builder_command(builder: { "cache" => { "type" => "gha" } })
|
||||||
assert_equal "multiarch", builder.name
|
assert_equal "multiarch", builder.name
|
||||||
assert_equal \
|
assert_equal \
|
||||||
"docker buildx build --push --platform linux/amd64,linux/arm64 --builder kamal-app-multiarch -t dhh/app:123 -t dhh/app:latest --cache-to type=gha --cache-from type=gha --label service=\"app\" --file Dockerfile .",
|
"docker buildx build --push --platform linux/amd64,linux/arm64 --builder kamal-app-multiarch -t dhh/app:123 -t dhh/app:latest --cache-to type=gha --cache-from type=gha --label service=\"app\" --file Dockerfile .",
|
||||||
@@ -22,7 +22,7 @@ class CommandsBuilderTest < ActiveSupport::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
test "target native cached when multiarch is off and cache is set" do
|
test "target native cached when multiarch is off and cache is set" do
|
||||||
builder = new_builder_command(builder: { "multiarch" => false, "cache" => { "type" => "gha" }})
|
builder = new_builder_command(builder: { "multiarch" => false, "cache" => { "type" => "gha" } })
|
||||||
assert_equal "native/cached", builder.name
|
assert_equal "native/cached", builder.name
|
||||||
assert_equal \
|
assert_equal \
|
||||||
"docker buildx build --push -t dhh/app:123 -t dhh/app:latest --cache-to type=gha --cache-from type=gha --label service=\"app\" --file Dockerfile .",
|
"docker buildx build --push -t dhh/app:123 -t dhh/app:latest --cache-to type=gha --cache-from type=gha --label service=\"app\" --file Dockerfile .",
|
||||||
@@ -30,7 +30,7 @@ class CommandsBuilderTest < ActiveSupport::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
test "target multiarch remote when local and remote is set" do
|
test "target multiarch remote when local and remote is set" do
|
||||||
builder = new_builder_command(builder: { "local" => { }, "remote" => { }, "cache" => { "type" => "gha" } })
|
builder = new_builder_command(builder: { "local" => {}, "remote" => {}, "cache" => { "type" => "gha" } })
|
||||||
assert_equal "multiarch/remote", builder.name
|
assert_equal "multiarch/remote", builder.name
|
||||||
assert_equal \
|
assert_equal \
|
||||||
"docker buildx build --push --platform linux/amd64,linux/arm64 --builder kamal-app-multiarch-remote -t dhh/app:123 -t dhh/app:latest --cache-to type=gha --cache-from type=gha --label service=\"app\" --file Dockerfile .",
|
"docker buildx build --push --platform linux/amd64,linux/arm64 --builder kamal-app-multiarch-remote -t dhh/app:123 -t dhh/app:latest --cache-to type=gha --cache-from type=gha --label service=\"app\" --file Dockerfile .",
|
||||||
@@ -61,7 +61,7 @@ class CommandsBuilderTest < ActiveSupport::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
test "build secrets" do
|
test "build secrets" do
|
||||||
builder = new_builder_command(builder: { "secrets" => ["token_a", "token_b"] })
|
builder = new_builder_command(builder: { "secrets" => [ "token_a", "token_b" ] })
|
||||||
assert_equal \
|
assert_equal \
|
||||||
"-t dhh/app:123 -t dhh/app:latest --label service=\"app\" --secret id=\"token_a\" --secret id=\"token_b\" --file Dockerfile",
|
"-t dhh/app:123 -t dhh/app:latest --label service=\"app\" --secret id=\"token_a\" --secret id=\"token_b\" --file Dockerfile",
|
||||||
builder.target.build_options.join(" ")
|
builder.target.build_options.join(" ")
|
||||||
@@ -112,7 +112,7 @@ class CommandsBuilderTest < ActiveSupport::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
test "build with ssh agent socket" do
|
test "build with ssh agent socket" do
|
||||||
builder = new_builder_command(builder: { "ssh" => 'default=$SSH_AUTH_SOCK' })
|
builder = new_builder_command(builder: { "ssh" => "default=$SSH_AUTH_SOCK" })
|
||||||
|
|
||||||
assert_equal \
|
assert_equal \
|
||||||
"-t dhh/app:123 -t dhh/app:latest --label service=\"app\" --file Dockerfile --ssh default=$SSH_AUTH_SOCK",
|
"-t dhh/app:123 -t dhh/app:latest --label service=\"app\" --file Dockerfile --ssh default=$SSH_AUTH_SOCK",
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ class CommandsTraefikTest < ActiveSupport::TestCase
|
|||||||
"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\" #{@image} --providers.docker --log.level=\"DEBUG\" --accesslog.format=\"json\" --api.insecure --metrics.prometheus.buckets=\"0.1,0.3,1.2,5.0\"",
|
"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\" #{@image} --providers.docker --log.level=\"DEBUG\" --accesslog.format=\"json\" --api.insecure --metrics.prometheus.buckets=\"0.1,0.3,1.2,5.0\"",
|
||||||
new_command.run.join(" ")
|
new_command.run.join(" ")
|
||||||
|
|
||||||
@config[:traefik]["options"] = {"publish" => %w[9000:9000 9001:9001]}
|
@config[:traefik]["options"] = { "publish" => %w[9000:9000 9001:9001] }
|
||||||
assert_equal \
|
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\" --publish \"9000:9000\" --publish \"9001:9001\" #{@image} --providers.docker --log.level=\"DEBUG\" --accesslog.format=\"json\" --api.insecure --metrics.prometheus.buckets=\"0.1,0.3,1.2,5.0\"",
|
"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\" --publish \"9000:9000\" --publish \"9001:9001\" #{@image} --providers.docker --log.level=\"DEBUG\" --accesslog.format=\"json\" --api.insecure --metrics.prometheus.buckets=\"0.1,0.3,1.2,5.0\"",
|
||||||
new_command.run.join(" ")
|
new_command.run.join(" ")
|
||||||
@@ -48,7 +48,7 @@ class CommandsTraefikTest < ActiveSupport::TestCase
|
|||||||
"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\" #{@image} --providers.docker --log.level=\"DEBUG\" --accesslog.format=\"json\" --api.insecure --metrics.prometheus.buckets=\"0.1,0.3,1.2,5.0\"",
|
"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\" #{@image} --providers.docker --log.level=\"DEBUG\" --accesslog.format=\"json\" --api.insecure --metrics.prometheus.buckets=\"0.1,0.3,1.2,5.0\"",
|
||||||
new_command.run.join(" ")
|
new_command.run.join(" ")
|
||||||
|
|
||||||
@config[:traefik]["options"] = {"volume" => %w[./letsencrypt/acme.json:/letsencrypt/acme.json] }
|
@config[:traefik]["options"] = { "volume" => %w[./letsencrypt/acme.json:/letsencrypt/acme.json] }
|
||||||
assert_equal \
|
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\" --volume \"./letsencrypt/acme.json:/letsencrypt/acme.json\" #{@image} --providers.docker --log.level=\"DEBUG\" --accesslog.format=\"json\" --api.insecure --metrics.prometheus.buckets=\"0.1,0.3,1.2,5.0\"",
|
"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\" --volume \"./letsencrypt/acme.json:/letsencrypt/acme.json\" #{@image} --providers.docker --log.level=\"DEBUG\" --accesslog.format=\"json\" --api.insecure --metrics.prometheus.buckets=\"0.1,0.3,1.2,5.0\"",
|
||||||
new_command.run.join(" ")
|
new_command.run.join(" ")
|
||||||
@@ -59,7 +59,7 @@ class CommandsTraefikTest < ActiveSupport::TestCase
|
|||||||
"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\" #{@image} --providers.docker --log.level=\"DEBUG\" --accesslog.format=\"json\" --api.insecure --metrics.prometheus.buckets=\"0.1,0.3,1.2,5.0\"",
|
"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\" #{@image} --providers.docker --log.level=\"DEBUG\" --accesslog.format=\"json\" --api.insecure --metrics.prometheus.buckets=\"0.1,0.3,1.2,5.0\"",
|
||||||
new_command.run.join(" ")
|
new_command.run.join(" ")
|
||||||
|
|
||||||
@config[:traefik]["options"] = {"volume" => %w[./letsencrypt/acme.json:/letsencrypt/acme.json], "publish" => %w[8080:8080], "memory" => "512m"}
|
@config[:traefik]["options"] = { "volume" => %w[./letsencrypt/acme.json:/letsencrypt/acme.json], "publish" => %w[8080:8080], "memory" => "512m" }
|
||||||
assert_equal \
|
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\" --volume \"./letsencrypt/acme.json:/letsencrypt/acme.json\" --publish \"8080:8080\" --memory \"512m\" #{@image} --providers.docker --log.level=\"DEBUG\" --accesslog.format=\"json\" --api.insecure --metrics.prometheus.buckets=\"0.1,0.3,1.2,5.0\"",
|
"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\" --volume \"./letsencrypt/acme.json:/letsencrypt/acme.json\" --publish \"8080:8080\" --memory \"512m\" #{@image} --providers.docker --log.level=\"DEBUG\" --accesslog.format=\"json\" --api.insecure --metrics.prometheus.buckets=\"0.1,0.3,1.2,5.0\"",
|
||||||
new_command.run.join(" ")
|
new_command.run.join(" ")
|
||||||
@@ -138,7 +138,7 @@ class CommandsTraefikTest < ActiveSupport::TestCase
|
|||||||
test "traefik logs since 2h" do
|
test "traefik logs since 2h" do
|
||||||
assert_equal \
|
assert_equal \
|
||||||
"docker logs traefik --since 2h --timestamps 2>&1",
|
"docker logs traefik --since 2h --timestamps 2>&1",
|
||||||
new_command.logs(since: '2h').join(" ")
|
new_command.logs(since: "2h").join(" ")
|
||||||
end
|
end
|
||||||
|
|
||||||
test "traefik logs last 10 lines" do
|
test "traefik logs last 10 lines" do
|
||||||
@@ -150,7 +150,7 @@ class CommandsTraefikTest < ActiveSupport::TestCase
|
|||||||
test "traefik logs with grep hello!" do
|
test "traefik logs with grep hello!" do
|
||||||
assert_equal \
|
assert_equal \
|
||||||
"docker logs traefik --timestamps 2>&1 | grep 'hello!'",
|
"docker logs traefik --timestamps 2>&1 | grep 'hello!'",
|
||||||
new_command.logs(grep: 'hello!').join(" ")
|
new_command.logs(grep: "hello!").join(" ")
|
||||||
end
|
end
|
||||||
|
|
||||||
test "traefik remove container" do
|
test "traefik remove container" do
|
||||||
@@ -174,7 +174,7 @@ class CommandsTraefikTest < ActiveSupport::TestCase
|
|||||||
test "traefik follow logs with grep hello!" do
|
test "traefik follow logs with grep hello!" do
|
||||||
assert_equal \
|
assert_equal \
|
||||||
"ssh -t root@1.1.1.1 -p 22 'docker logs traefik --timestamps --tail 10 --follow 2>&1 | grep \"hello!\"'",
|
"ssh -t root@1.1.1.1 -p 22 'docker logs traefik --timestamps --tail 10 --follow 2>&1 | grep \"hello!\"'",
|
||||||
new_command.follow_logs(host: @config[:servers].first, grep: 'hello!')
|
new_command.follow_logs(host: @config[:servers].first, grep: "hello!")
|
||||||
end
|
end
|
||||||
|
|
||||||
test "env_file" do
|
test "env_file" do
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ class ConfigurationAccessoryTest < ActiveSupport::TestCase
|
|||||||
},
|
},
|
||||||
"secret" => [
|
"secret" => [
|
||||||
"MYSQL_ROOT_PASSWORD"
|
"MYSQL_ROOT_PASSWORD"
|
||||||
],
|
]
|
||||||
},
|
},
|
||||||
"files" => [
|
"files" => [
|
||||||
"config/mysql/my.cnf:/etc/mysql/my.cnf",
|
"config/mysql/my.cnf:/etc/mysql/my.cnf",
|
||||||
@@ -82,9 +82,9 @@ class ConfigurationAccessoryTest < ActiveSupport::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
test "host" do
|
test "host" do
|
||||||
assert_equal ["1.1.1.5"], @config.accessory(:mysql).hosts
|
assert_equal [ "1.1.1.5" ], @config.accessory(:mysql).hosts
|
||||||
assert_equal ["1.1.1.6", "1.1.1.7"], @config.accessory(:redis).hosts
|
assert_equal [ "1.1.1.6", "1.1.1.7" ], @config.accessory(:redis).hosts
|
||||||
assert_equal ["1.1.1.1", "1.1.1.2"], @config.accessory(:monitoring).hosts
|
assert_equal [ "1.1.1.1", "1.1.1.2" ], @config.accessory(:monitoring).hosts
|
||||||
end
|
end
|
||||||
|
|
||||||
test "missing host" do
|
test "missing host" do
|
||||||
@@ -108,13 +108,13 @@ class ConfigurationAccessoryTest < ActiveSupport::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
test "label args" do
|
test "label args" do
|
||||||
assert_equal ["--label", "service=\"app-mysql\""], @config.accessory(:mysql).label_args
|
assert_equal [ "--label", "service=\"app-mysql\"" ], @config.accessory(:mysql).label_args
|
||||||
assert_equal ["--label", "service=\"app-redis\"", "--label", "cache=\"true\""], @config.accessory(:redis).label_args
|
assert_equal [ "--label", "service=\"app-redis\"", "--label", "cache=\"true\"" ], @config.accessory(:redis).label_args
|
||||||
end
|
end
|
||||||
|
|
||||||
test "env args" do
|
test "env args" do
|
||||||
assert_equal ["--env-file", ".kamal/env/accessories/app-mysql.env"], @config.accessory(:mysql).env_args
|
assert_equal [ "--env-file", ".kamal/env/accessories/app-mysql.env" ], @config.accessory(:mysql).env_args
|
||||||
assert_equal ["--env-file", ".kamal/env/accessories/app-redis.env"], @config.accessory(:redis).env_args
|
assert_equal [ "--env-file", ".kamal/env/accessories/app-redis.env" ], @config.accessory(:redis).env_args
|
||||||
end
|
end
|
||||||
|
|
||||||
test "env file with secret" do
|
test "env file with secret" do
|
||||||
@@ -139,8 +139,8 @@ class ConfigurationAccessoryTest < ActiveSupport::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
test "volume args" do
|
test "volume args" do
|
||||||
assert_equal ["--volume", "$PWD/app-mysql/etc/mysql/my.cnf:/etc/mysql/my.cnf", "--volume", "$PWD/app-mysql/docker-entrypoint-initdb.d/structure.sql:/docker-entrypoint-initdb.d/structure.sql", "--volume", "$PWD/app-mysql/data:/var/lib/mysql"], @config.accessory(:mysql).volume_args
|
assert_equal [ "--volume", "$PWD/app-mysql/etc/mysql/my.cnf:/etc/mysql/my.cnf", "--volume", "$PWD/app-mysql/docker-entrypoint-initdb.d/structure.sql:/docker-entrypoint-initdb.d/structure.sql", "--volume", "$PWD/app-mysql/data:/var/lib/mysql" ], @config.accessory(:mysql).volume_args
|
||||||
assert_equal ["--volume", "/var/lib/redis:/data"], @config.accessory(:redis).volume_args
|
assert_equal [ "--volume", "/var/lib/redis:/data" ], @config.accessory(:redis).volume_args
|
||||||
end
|
end
|
||||||
|
|
||||||
test "dynamic file expansion" do
|
test "dynamic file expansion" do
|
||||||
@@ -153,15 +153,15 @@ class ConfigurationAccessoryTest < ActiveSupport::TestCase
|
|||||||
|
|
||||||
test "directory with a relative path" do
|
test "directory with a relative path" do
|
||||||
@deploy[:accessories]["mysql"]["directories"] = [ "data:/var/lib/mysql" ]
|
@deploy[:accessories]["mysql"]["directories"] = [ "data:/var/lib/mysql" ]
|
||||||
assert_equal({"$PWD/app-mysql/data"=>"/var/lib/mysql"}, @config.accessory(:mysql).directories)
|
assert_equal({ "$PWD/app-mysql/data"=>"/var/lib/mysql" }, @config.accessory(:mysql).directories)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "directory with an absolute path" do
|
test "directory with an absolute path" do
|
||||||
@deploy[:accessories]["mysql"]["directories"] = [ "/var/data/mysql:/var/lib/mysql" ]
|
@deploy[:accessories]["mysql"]["directories"] = [ "/var/data/mysql:/var/lib/mysql" ]
|
||||||
assert_equal({"/var/data/mysql"=>"/var/lib/mysql"}, @config.accessory(:mysql).directories)
|
assert_equal({ "/var/data/mysql"=>"/var/lib/mysql" }, @config.accessory(:mysql).directories)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "options" do
|
test "options" do
|
||||||
assert_equal ["--cpus", "\"4\"", "--memory", "\"2GB\""], @config.accessory(:redis).option_args
|
assert_equal [ "--cpus", "\"4\"", "--memory", "\"2GB\"" ], @config.accessory(:redis).option_args
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -124,9 +124,9 @@ class ConfigurationBuilderTest < ActiveSupport::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
test "setting secrets" do
|
test "setting secrets" do
|
||||||
@deploy_with_builder_option[:builder] = { "secrets" => ["GITHUB_TOKEN"] }
|
@deploy_with_builder_option[:builder] = { "secrets" => [ "GITHUB_TOKEN" ] }
|
||||||
|
|
||||||
assert_equal ["GITHUB_TOKEN"], @config_with_builder_option.builder.secrets
|
assert_equal [ "GITHUB_TOKEN" ], @config_with_builder_option.builder.secrets
|
||||||
end
|
end
|
||||||
|
|
||||||
test "dockerfile" do
|
test "dockerfile" do
|
||||||
@@ -154,8 +154,8 @@ class ConfigurationBuilderTest < ActiveSupport::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
test "setting ssh params" do
|
test "setting ssh params" do
|
||||||
@deploy_with_builder_option[:builder] = { "ssh" => 'default=$SSH_AUTH_SOCK' }
|
@deploy_with_builder_option[:builder] = { "ssh" => "default=$SSH_AUTH_SOCK" }
|
||||||
|
|
||||||
assert_equal 'default=$SSH_AUTH_SOCK', @config_with_builder_option.builder.ssh
|
assert_equal "default=$SSH_AUTH_SOCK", @config_with_builder_option.builder.ssh
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ class ConfigurationRoleTest < ActiveSupport::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
test "env args" do
|
test "env args" do
|
||||||
assert_equal ["--env-file", ".kamal/env/roles/app-workers.env"], @config_with_roles.role(:workers).env_args
|
assert_equal [ "--env-file", ".kamal/env/roles/app-workers.env" ], @config_with_roles.role(:workers).env_args
|
||||||
end
|
end
|
||||||
|
|
||||||
test "env secret overwritten by role" do
|
test "env secret overwritten by role" do
|
||||||
@@ -188,8 +188,8 @@ class ConfigurationRoleTest < ActiveSupport::TestCase
|
|||||||
|
|
||||||
@deploy_with_roles[:servers]["workers"]["env"] = {
|
@deploy_with_roles[:servers]["workers"]["env"] = {
|
||||||
"clear" => {
|
"clear" => {
|
||||||
"REDIS_URL" => "redis://c/d",
|
"REDIS_URL" => "redis://c/d"
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ENV["REDIS_PASSWORD"] = "secret456"
|
ENV["REDIS_PASSWORD"] = "secret456"
|
||||||
@@ -214,7 +214,7 @@ class ConfigurationRoleTest < ActiveSupport::TestCase
|
|||||||
|
|
||||||
test "uses cord" do
|
test "uses cord" do
|
||||||
assert @config_with_roles.role(:web).uses_cord?
|
assert @config_with_roles.role(:web).uses_cord?
|
||||||
assert !@config_with_roles.role(:workers).uses_cord?
|
assert_not @config_with_roles.role(:workers).uses_cord?
|
||||||
end
|
end
|
||||||
|
|
||||||
test "cord host file" do
|
test "cord host file" do
|
||||||
@@ -238,28 +238,28 @@ class ConfigurationRoleTest < ActiveSupport::TestCase
|
|||||||
assert_nil @config_with_roles.role(:workers).asset_volume_args
|
assert_nil @config_with_roles.role(:workers).asset_volume_args
|
||||||
assert_nil @config_with_roles.role(:web).asset_path
|
assert_nil @config_with_roles.role(:web).asset_path
|
||||||
assert_nil @config_with_roles.role(:workers).asset_path
|
assert_nil @config_with_roles.role(:workers).asset_path
|
||||||
assert !@config_with_roles.role(:web).assets?
|
assert_not @config_with_roles.role(:web).assets?
|
||||||
assert !@config_with_roles.role(:workers).assets?
|
assert_not @config_with_roles.role(:workers).assets?
|
||||||
|
|
||||||
config_with_assets = Kamal::Configuration.new(@deploy_with_roles.dup.tap { |c|
|
config_with_assets = Kamal::Configuration.new(@deploy_with_roles.dup.tap { |c|
|
||||||
c[:asset_path] = "foo"
|
c[:asset_path] = "foo"
|
||||||
})
|
})
|
||||||
assert_equal "foo", config_with_assets.role(:web).asset_path
|
assert_equal "foo", config_with_assets.role(:web).asset_path
|
||||||
assert_equal "foo", config_with_assets.role(:workers).asset_path
|
assert_equal "foo", config_with_assets.role(:workers).asset_path
|
||||||
assert_equal ["--volume", "$(pwd)/.kamal/assets/volumes/app-web-12345:foo"], config_with_assets.role(:web).asset_volume_args
|
assert_equal [ "--volume", "$(pwd)/.kamal/assets/volumes/app-web-12345:foo" ], config_with_assets.role(:web).asset_volume_args
|
||||||
assert_nil config_with_assets.role(:workers).asset_volume_args
|
assert_nil config_with_assets.role(:workers).asset_volume_args
|
||||||
assert config_with_assets.role(:web).assets?
|
assert config_with_assets.role(:web).assets?
|
||||||
assert !config_with_assets.role(:workers).assets?
|
assert_not config_with_assets.role(:workers).assets?
|
||||||
|
|
||||||
config_with_assets = Kamal::Configuration.new(@deploy_with_roles.dup.tap { |c|
|
config_with_assets = Kamal::Configuration.new(@deploy_with_roles.dup.tap { |c|
|
||||||
c[:servers]["web"] = { "hosts" => [ "1.1.1.1", "1.1.1.2" ], "asset_path" => "bar" }
|
c[:servers]["web"] = { "hosts" => [ "1.1.1.1", "1.1.1.2" ], "asset_path" => "bar" }
|
||||||
})
|
})
|
||||||
assert_equal "bar", config_with_assets.role(:web).asset_path
|
assert_equal "bar", config_with_assets.role(:web).asset_path
|
||||||
assert_nil config_with_assets.role(:workers).asset_path
|
assert_nil config_with_assets.role(:workers).asset_path
|
||||||
assert_equal ["--volume", "$(pwd)/.kamal/assets/volumes/app-web-12345:bar"], config_with_assets.role(:web).asset_volume_args
|
assert_equal [ "--volume", "$(pwd)/.kamal/assets/volumes/app-web-12345:bar" ], config_with_assets.role(:web).asset_volume_args
|
||||||
assert_nil config_with_assets.role(:workers).asset_volume_args
|
assert_nil config_with_assets.role(:workers).asset_volume_args
|
||||||
assert config_with_assets.role(:web).assets?
|
assert config_with_assets.role(:web).assets?
|
||||||
assert !config_with_assets.role(:workers).assets?
|
assert_not config_with_assets.role(:workers).assets?
|
||||||
|
|
||||||
ensure
|
ensure
|
||||||
ENV.delete("VERSION")
|
ENV.delete("VERSION")
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ class ConfigurationSshTest < ActiveSupport::TestCase
|
|||||||
registry: { "username" => "dhh", "password" => "secret" },
|
registry: { "username" => "dhh", "password" => "secret" },
|
||||||
env: { "REDIS_URL" => "redis://x/y" },
|
env: { "REDIS_URL" => "redis://x/y" },
|
||||||
servers: [ "1.1.1.1", "1.1.1.2" ],
|
servers: [ "1.1.1.1", "1.1.1.2" ],
|
||||||
volumes: ["/local/path:/container/path"]
|
volumes: [ "/local/path:/container/path" ]
|
||||||
}
|
}
|
||||||
|
|
||||||
@config = Kamal::Configuration.new(@deploy)
|
@config = Kamal::Configuration.new(@deploy)
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ class ConfigurationSshkitTest < ActiveSupport::TestCase
|
|||||||
registry: { "username" => "dhh", "password" => "secret" },
|
registry: { "username" => "dhh", "password" => "secret" },
|
||||||
env: { "REDIS_URL" => "redis://x/y" },
|
env: { "REDIS_URL" => "redis://x/y" },
|
||||||
servers: [ "1.1.1.1", "1.1.1.2" ],
|
servers: [ "1.1.1.1", "1.1.1.2" ],
|
||||||
volumes: ["/local/path:/container/path"]
|
volumes: [ "/local/path:/container/path" ]
|
||||||
}
|
}
|
||||||
|
|
||||||
@config = Kamal::Configuration.new(@deploy)
|
@config = Kamal::Configuration.new(@deploy)
|
||||||
|
|||||||
@@ -3,11 +3,11 @@ require "test_helper"
|
|||||||
class ConfigurationVolumeTest < ActiveSupport::TestCase
|
class ConfigurationVolumeTest < ActiveSupport::TestCase
|
||||||
test "docker args absolute" do
|
test "docker args absolute" do
|
||||||
volume = Kamal::Configuration::Volume.new(host_path: "/root/foo/bar", container_path: "/assets")
|
volume = Kamal::Configuration::Volume.new(host_path: "/root/foo/bar", container_path: "/assets")
|
||||||
assert_equal ["--volume", "/root/foo/bar:/assets"], volume.docker_args
|
assert_equal [ "--volume", "/root/foo/bar:/assets" ], volume.docker_args
|
||||||
end
|
end
|
||||||
|
|
||||||
test "docker args relative" do
|
test "docker args relative" do
|
||||||
volume = Kamal::Configuration::Volume.new(host_path: "foo/bar", container_path: "/assets")
|
volume = Kamal::Configuration::Volume.new(host_path: "foo/bar", container_path: "/assets")
|
||||||
assert_equal ["--volume", "$(pwd)/foo/bar:/assets"], volume.docker_args
|
assert_equal [ "--volume", "$(pwd)/foo/bar:/assets" ], volume.docker_args
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ class ConfigurationTest < ActiveSupport::TestCase
|
|||||||
registry: { "username" => "dhh", "password" => "secret" },
|
registry: { "username" => "dhh", "password" => "secret" },
|
||||||
env: { "REDIS_URL" => "redis://x/y" },
|
env: { "REDIS_URL" => "redis://x/y" },
|
||||||
servers: [ "1.1.1.1", "1.1.1.2" ],
|
servers: [ "1.1.1.1", "1.1.1.2" ],
|
||||||
volumes: ["/local/path:/container/path"]
|
volumes: [ "/local/path:/container/path" ]
|
||||||
}
|
}
|
||||||
|
|
||||||
@config = Kamal::Configuration.new(@deploy)
|
@config = Kamal::Configuration.new(@deploy)
|
||||||
@@ -64,7 +64,7 @@ class ConfigurationTest < ActiveSupport::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
test "all hosts" do
|
test "all hosts" do
|
||||||
assert_equal [ "1.1.1.1", "1.1.1.2"], @config.all_hosts
|
assert_equal [ "1.1.1.1", "1.1.1.2" ], @config.all_hosts
|
||||||
assert_equal [ "1.1.1.1", "1.1.1.2", "1.1.1.3" ], @config_with_roles.all_hosts
|
assert_equal [ "1.1.1.1", "1.1.1.2", "1.1.1.3" ], @config_with_roles.all_hosts
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -86,7 +86,7 @@ class ConfigurationTest < ActiveSupport::TestCase
|
|||||||
ENV.delete("VERSION")
|
ENV.delete("VERSION")
|
||||||
|
|
||||||
Kamal::Git.expects(:used?).returns(nil)
|
Kamal::Git.expects(:used?).returns(nil)
|
||||||
error = assert_raises(RuntimeError) { @config.version}
|
error = assert_raises(RuntimeError) { @config.version }
|
||||||
assert_match /no git repository found/, error.message
|
assert_match /no git repository found/, error.message
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -186,21 +186,21 @@ class ConfigurationTest < ActiveSupport::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
test "volume_args" do
|
test "volume_args" do
|
||||||
assert_equal ["--volume", "/local/path:/container/path"], @config.volume_args
|
assert_equal [ "--volume", "/local/path:/container/path" ], @config.volume_args
|
||||||
end
|
end
|
||||||
|
|
||||||
test "logging args default" do
|
test "logging args default" do
|
||||||
assert_equal ["--log-opt", "max-size=\"10m\""], @config.logging_args
|
assert_equal [ "--log-opt", "max-size=\"10m\"" ], @config.logging_args
|
||||||
end
|
end
|
||||||
|
|
||||||
test "logging args with configured options" do
|
test "logging args with configured options" do
|
||||||
config = Kamal::Configuration.new(@deploy.tap { |c| c.merge!(logging: { "options" => { "max-size" => "100m", "max-file" => 5 } }) })
|
config = Kamal::Configuration.new(@deploy.tap { |c| c.merge!(logging: { "options" => { "max-size" => "100m", "max-file" => 5 } }) })
|
||||||
assert_equal ["--log-opt", "max-size=\"100m\"", "--log-opt", "max-file=\"5\""], @config.logging_args
|
assert_equal [ "--log-opt", "max-size=\"100m\"", "--log-opt", "max-file=\"5\"" ], @config.logging_args
|
||||||
end
|
end
|
||||||
|
|
||||||
test "logging args with configured driver and options" do
|
test "logging args with configured driver and options" do
|
||||||
config = Kamal::Configuration.new(@deploy.tap { |c| c.merge!(logging: { "driver" => "local", "options" => { "max-size" => "100m", "max-file" => 5 } }) })
|
config = Kamal::Configuration.new(@deploy.tap { |c| c.merge!(logging: { "driver" => "local", "options" => { "max-size" => "100m", "max-file" => 5 } }) })
|
||||||
assert_equal ["--log-driver", "\"local\"", "--log-opt", "max-size=\"100m\"", "--log-opt", "max-file=\"5\""], @config.logging_args
|
assert_equal [ "--log-driver", "\"local\"", "--log-opt", "max-size=\"100m\"", "--log-opt", "max-file=\"5\"" ], @config.logging_args
|
||||||
end
|
end
|
||||||
|
|
||||||
test "erb evaluation of yml config" do
|
test "erb evaluation of yml config" do
|
||||||
@@ -240,19 +240,19 @@ class ConfigurationTest < ActiveSupport::TestCase
|
|||||||
|
|
||||||
test "to_h" do
|
test "to_h" do
|
||||||
expected_config = \
|
expected_config = \
|
||||||
{ :roles=>["web"],
|
{ roles: [ "web" ],
|
||||||
:hosts=>["1.1.1.1", "1.1.1.2"],
|
hosts: [ "1.1.1.1", "1.1.1.2" ],
|
||||||
:primary_host=>"1.1.1.1",
|
primary_host: "1.1.1.1",
|
||||||
:version=>"missing",
|
version: "missing",
|
||||||
:repository=>"dhh/app",
|
repository: "dhh/app",
|
||||||
:absolute_image=>"dhh/app:missing",
|
absolute_image: "dhh/app:missing",
|
||||||
:service_with_version=>"app-missing",
|
service_with_version: "app-missing",
|
||||||
:ssh_options=>{ :user=>"root", port: 22, log_level: :fatal, keepalive: true, keepalive_interval: 30 },
|
ssh_options: { user: "root", port: 22, log_level: :fatal, keepalive: true, keepalive_interval: 30 },
|
||||||
:sshkit=>{},
|
sshkit: {},
|
||||||
:volume_args=>["--volume", "/local/path:/container/path"],
|
volume_args: [ "--volume", "/local/path:/container/path" ],
|
||||||
:builder=>{},
|
builder: {},
|
||||||
:logging=>["--log-opt", "max-size=\"10m\""],
|
logging: [ "--log-opt", "max-size=\"10m\"" ],
|
||||||
:healthcheck=>{ "path"=>"/up", "port"=>3000, "max_attempts" => 7, "exposed_port" => 3999, "cord" => "/tmp/kamal-cord", "log_lines" => 50 }}
|
healthcheck: { "path"=>"/up", "port"=>3000, "max_attempts" => 7, "exposed_port" => 3999, "cord" => "/tmp/kamal-cord", "log_lines" => 50 } }
|
||||||
|
|
||||||
assert_equal expected_config, @config.to_h
|
assert_equal expected_config, @config.to_h
|
||||||
end
|
end
|
||||||
@@ -304,7 +304,7 @@ class ConfigurationTest < ActiveSupport::TestCase
|
|||||||
|
|
||||||
config = Kamal::Configuration.new(@deploy_with_roles.deep_merge({
|
config = Kamal::Configuration.new(@deploy_with_roles.deep_merge({
|
||||||
servers: { "alternate_web" => { "hosts" => [ "1.1.1.4", "1.1.1.5" ] } },
|
servers: { "alternate_web" => { "hosts" => [ "1.1.1.4", "1.1.1.5" ] } },
|
||||||
primary_role: "alternate_web" } ))
|
primary_role: "alternate_web" }))
|
||||||
|
|
||||||
|
|
||||||
assert_equal "alternate_web", config.primary_role.name
|
assert_equal "alternate_web", config.primary_role.name
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ class AccessoryTest < IntegrationTest
|
|||||||
end
|
end
|
||||||
|
|
||||||
def assert_accessory_not_running(name)
|
def assert_accessory_not_running(name)
|
||||||
refute_match /registry:4443\/busybox:1.36.0 "sh -c 'echo \\"Start/, accessory_details(name)
|
assert_no_match /registry:4443\/busybox:1.36.0 "sh -c 'echo \\"Start/, accessory_details(name)
|
||||||
end
|
end
|
||||||
|
|
||||||
def accessory_details(name)
|
def accessory_details(name)
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ class IntegrationTest < ActiveSupport::TestCase
|
|||||||
|
|
||||||
teardown do
|
teardown do
|
||||||
unless passed?
|
unless passed?
|
||||||
[:deployer, :vm1, :vm2, :shared, :load_balancer, :registry].each do |container|
|
[ :deployer, :vm1, :vm2, :shared, :load_balancer, :registry ].each do |container|
|
||||||
puts
|
puts
|
||||||
puts "Logs for #{container}:"
|
puts "Logs for #{container}:"
|
||||||
docker_compose :logs, container
|
docker_compose :logs, container
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ class TraefikTest < IntegrationTest
|
|||||||
end
|
end
|
||||||
|
|
||||||
def assert_traefik_not_running
|
def assert_traefik_not_running
|
||||||
refute_match /traefik:v2.10 "\/entrypoint.sh/, traefik_details
|
assert_no_match /traefik:v2.10 "\/entrypoint.sh/, traefik_details
|
||||||
end
|
end
|
||||||
|
|
||||||
def traefik_details
|
def traefik_details
|
||||||
|
|||||||
Reference in New Issue
Block a user