Compare commits
5 Commits
revert-905
...
no-envify
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
90212129d5 | ||
|
|
a13adbf0dd | ||
|
|
d2f57b1889 | ||
|
|
cbb4c87035 | ||
|
|
a8837d453c |
@@ -1,7 +1,7 @@
|
|||||||
PATH
|
PATH
|
||||||
remote: .
|
remote: .
|
||||||
specs:
|
specs:
|
||||||
kamal (2.0.0.alpha)
|
kamal (1.8.1)
|
||||||
activesupport (>= 7.0)
|
activesupport (>= 7.0)
|
||||||
base64 (~> 0.2)
|
base64 (~> 0.2)
|
||||||
bcrypt_pbkdf (~> 1.0)
|
bcrypt_pbkdf (~> 1.0)
|
||||||
@@ -10,7 +10,7 @@ PATH
|
|||||||
ed25519 (~> 1.2)
|
ed25519 (~> 1.2)
|
||||||
net-ssh (~> 7.0)
|
net-ssh (~> 7.0)
|
||||||
sshkit (>= 1.23.0, < 2.0)
|
sshkit (>= 1.23.0, < 2.0)
|
||||||
thor (~> 1.3)
|
thor (~> 1.2)
|
||||||
zeitwerk (~> 2.5)
|
zeitwerk (~> 2.5)
|
||||||
|
|
||||||
GEM
|
GEM
|
||||||
|
|||||||
20
bin/docs
20
bin/docs
@@ -17,7 +17,6 @@ end
|
|||||||
|
|
||||||
DOCS = {
|
DOCS = {
|
||||||
"accessory" => "Accessories",
|
"accessory" => "Accessories",
|
||||||
"alias" => "Aliases",
|
|
||||||
"boot" => "Booting",
|
"boot" => "Booting",
|
||||||
"builder" => "Builders",
|
"builder" => "Builders",
|
||||||
"configuration" => "Configuration overview",
|
"configuration" => "Configuration overview",
|
||||||
@@ -68,27 +67,26 @@ class DocWriter
|
|||||||
output.puts
|
output.puts
|
||||||
place = :new_section
|
place = :new_section
|
||||||
elsif line =~ /^ *#/
|
elsif line =~ /^ *#/
|
||||||
generate_line(line, heading: place == :new_section)
|
generate_line(line, place: place)
|
||||||
place = :in_section
|
place = :in_section
|
||||||
else
|
else
|
||||||
output.puts "```yaml"
|
output.puts "```yaml"
|
||||||
output.puts line
|
output.print line
|
||||||
place = :in_yaml
|
place = :in_yaml
|
||||||
end
|
end
|
||||||
when :in_yaml, :in_empty_line_yaml
|
when :in_yaml
|
||||||
if line =~ /^ *#/
|
if line =~ /^ *#/
|
||||||
output.puts "```"
|
output.puts "```"
|
||||||
generate_line(line, heading: place == :in_empty_line_yaml)
|
generate_line(line, place: :new_section)
|
||||||
place = :in_section
|
place = :in_section
|
||||||
elsif line.empty?
|
|
||||||
place = :in_empty_line_yaml
|
|
||||||
else
|
else
|
||||||
output.puts line
|
output.puts
|
||||||
|
output.print line
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
output.puts "```" if place == :in_yaml
|
output.puts "\n```" if place == :in_yaml
|
||||||
end
|
end
|
||||||
|
|
||||||
def generate_header
|
def generate_header
|
||||||
@@ -100,7 +98,7 @@ class DocWriter
|
|||||||
output.puts
|
output.puts
|
||||||
end
|
end
|
||||||
|
|
||||||
def generate_line(line, heading: false)
|
def generate_line(line, place: :in_section)
|
||||||
line = line.gsub(/^ *#\s?/, "")
|
line = line.gsub(/^ *#\s?/, "")
|
||||||
|
|
||||||
if line =~ /(.*)kamal docs ([a-z]*)(.*)/
|
if line =~ /(.*)kamal docs ([a-z]*)(.*)/
|
||||||
@@ -111,7 +109,7 @@ class DocWriter
|
|||||||
line = "#{$1}[#{titlify($2.split("/").last)}](#{$2})#{$3}"
|
line = "#{$1}[#{titlify($2.split("/").last)}](#{$2})#{$3}"
|
||||||
end
|
end
|
||||||
|
|
||||||
if heading
|
if place == :new_section
|
||||||
output.puts "## [#{line}](##{linkify(line)})"
|
output.puts "## [#{line}](##{linkify(line)})"
|
||||||
else
|
else
|
||||||
output.puts line
|
output.puts line
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ Gem::Specification.new do |spec|
|
|||||||
spec.add_dependency "activesupport", ">= 7.0"
|
spec.add_dependency "activesupport", ">= 7.0"
|
||||||
spec.add_dependency "sshkit", ">= 1.23.0", "< 2.0"
|
spec.add_dependency "sshkit", ">= 1.23.0", "< 2.0"
|
||||||
spec.add_dependency "net-ssh", "~> 7.0"
|
spec.add_dependency "net-ssh", "~> 7.0"
|
||||||
spec.add_dependency "thor", "~> 1.3"
|
spec.add_dependency "thor", "~> 1.2"
|
||||||
spec.add_dependency "dotenv", "~> 2.8"
|
spec.add_dependency "dotenv", "~> 2.8"
|
||||||
spec.add_dependency "zeitwerk", "~> 2.5"
|
spec.add_dependency "zeitwerk", "~> 2.5"
|
||||||
spec.add_dependency "ed25519", "~> 1.2"
|
spec.add_dependency "ed25519", "~> 1.2"
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
class Kamal::Cli::Alias::Command < Thor::DynamicCommand
|
|
||||||
def run(instance, args = [])
|
|
||||||
if (_alias = KAMAL.config.aliases[name])
|
|
||||||
Kamal::Cli::Main.start(Shellwords.split(_alias.command) + ARGV[1..-1])
|
|
||||||
else
|
|
||||||
super
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -71,12 +71,11 @@ class Kamal::Cli::App < Kamal::Cli::Base
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
desc "exec [CMD...]", "Execute a custom command on servers within the app container (use --help to show options)"
|
desc "exec [CMD]", "Execute a custom command on servers within the app container (use --help to show options)"
|
||||||
option :interactive, aliases: "-i", type: :boolean, default: false, desc: "Execute command over ssh for an interactive shell (use for console/bash)"
|
option :interactive, aliases: "-i", type: :boolean, default: false, desc: "Execute command over ssh for an interactive shell (use for console/bash)"
|
||||||
option :reuse, type: :boolean, default: false, desc: "Reuse currently running container instead of starting a new one"
|
option :reuse, type: :boolean, default: false, desc: "Reuse currently running container instead of starting a new one"
|
||||||
option :env, aliases: "-e", type: :hash, desc: "Set environment variables for the command"
|
option :env, aliases: "-e", type: :hash, desc: "Set environment variables for the command"
|
||||||
def exec(*cmd)
|
def exec(cmd)
|
||||||
cmd = Kamal::Utils.join_commands(cmd)
|
|
||||||
env = options[:env]
|
env = options[:env]
|
||||||
case
|
case
|
||||||
when options[:interactive] && options[:reuse]
|
when options[:interactive] && options[:reuse]
|
||||||
|
|||||||
@@ -6,8 +6,7 @@ module Kamal::Cli
|
|||||||
class Base < Thor
|
class Base < Thor
|
||||||
include SSHKit::DSL
|
include SSHKit::DSL
|
||||||
|
|
||||||
def self.exit_on_failure?() false end
|
def self.exit_on_failure?() true end
|
||||||
def self.dynamic_command_class() Kamal::Cli::Alias::Command end
|
|
||||||
|
|
||||||
class_option :verbose, type: :boolean, aliases: "-v", desc: "Detailed logging"
|
class_option :verbose, type: :boolean, aliases: "-v", desc: "Detailed logging"
|
||||||
class_option :quiet, type: :boolean, aliases: "-q", desc: "Minimal logging"
|
class_option :quiet, type: :boolean, aliases: "-q", desc: "Minimal logging"
|
||||||
@@ -23,56 +22,48 @@ module Kamal::Cli
|
|||||||
|
|
||||||
class_option :skip_hooks, aliases: "-H", type: :boolean, default: false, desc: "Don't run hooks"
|
class_option :skip_hooks, aliases: "-H", type: :boolean, default: false, desc: "Don't run hooks"
|
||||||
|
|
||||||
def initialize(args = [], local_options = {}, config = {})
|
@@ran_pre_init_hook = false
|
||||||
if config[:current_command].is_a?(Kamal::Cli::Alias::Command)
|
class << self
|
||||||
# When Thor generates a dynamic command, it doesn't attempt to parse the arguments.
|
def ran_pre_init_hook
|
||||||
# For our purposes, it means the arguments are passed in args rather than local_options.
|
@@ran_pre_init_hook
|
||||||
super([], args, config)
|
|
||||||
else
|
|
||||||
super
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def ran_pre_init_hook=(value)
|
||||||
|
@@ran_pre_init_hook = value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def initialize(*)
|
||||||
|
super
|
||||||
@original_env = ENV.to_h.dup
|
@original_env = ENV.to_h.dup
|
||||||
|
run_pre_init_hook
|
||||||
load_env
|
load_env
|
||||||
initialize_commander(options_with_subcommand_class_options)
|
initialize_commander(options_with_subcommand_class_options)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
def reload_env
|
|
||||||
reset_env
|
|
||||||
load_env
|
|
||||||
end
|
|
||||||
|
|
||||||
def load_env
|
def load_env
|
||||||
if destination = options[:destination]
|
if destination = options[:destination]
|
||||||
Dotenv.load(".env.#{destination}", ".env")
|
if File.exist?(".kamal/.env.#{destination}") || File.exist?(".kamal/.env")
|
||||||
|
Dotenv.load(".kamal/.env.#{destination}", ".kamal/.env")
|
||||||
|
else
|
||||||
|
loading_files = [ (".env" if File.exist?(".env")), (".env.#{destination}" if File.exist?(".env.#{destination}")) ].compact
|
||||||
|
if loading_files.any?
|
||||||
|
warn "Loading #{loading_files.join(" and ")} from the project root, in future they will be loaded from .kamal/"
|
||||||
|
Dotenv.load(".env.#{destination}", ".env")
|
||||||
|
end
|
||||||
|
end
|
||||||
else
|
else
|
||||||
Dotenv.load(".env")
|
if File.exist?(".kamal/.env")
|
||||||
|
Dotenv.load(".kamal/.env")
|
||||||
|
elsif File.exist?(".env")
|
||||||
|
$stderr.puts caller
|
||||||
|
warn "Loading .env from the project root, in future it will be loaded then from .kamal/.env"
|
||||||
|
Dotenv.load(".env")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def reset_env
|
|
||||||
replace_env @original_env
|
|
||||||
end
|
|
||||||
|
|
||||||
def replace_env(env)
|
|
||||||
ENV.clear
|
|
||||||
ENV.update(env)
|
|
||||||
end
|
|
||||||
|
|
||||||
def with_original_env
|
|
||||||
keeping_current_env do
|
|
||||||
reset_env
|
|
||||||
yield
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def keeping_current_env
|
|
||||||
current_env = ENV.to_h.dup
|
|
||||||
yield
|
|
||||||
ensure
|
|
||||||
replace_env(current_env)
|
|
||||||
end
|
|
||||||
|
|
||||||
def options_with_subcommand_class_options
|
def options_with_subcommand_class_options
|
||||||
options.merge(@_initializer.last[:class_options] || {})
|
options.merge(@_initializer.last[:class_options] || {})
|
||||||
end
|
end
|
||||||
@@ -169,8 +160,23 @@ module Kamal::Cli
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def run_pre_init_hook
|
||||||
|
unless self.class.ran_pre_init_hook
|
||||||
|
hook = "pre-init"
|
||||||
|
if run_hook?(hook)
|
||||||
|
say "Running the #{hook} hook...", :magenta
|
||||||
|
run_locally do
|
||||||
|
execute *Kamal::Hooks.file(hook), verbosity: :debug
|
||||||
|
rescue SSHKit::Command::Failed => e
|
||||||
|
raise HookError.new("Hook `#{hook}` failed:\n#{e.message}")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
self.class.ran_pre_init_hook = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def run_hook(hook, **extra_details)
|
def run_hook(hook, **extra_details)
|
||||||
if !options[:skip_hooks] && KAMAL.hook.hook_exists?(hook)
|
if run_hook?(hook)
|
||||||
details = { hosts: KAMAL.hosts.join(","), command: command, subcommand: subcommand }
|
details = { hosts: KAMAL.hosts.join(","), command: command, subcommand: subcommand }
|
||||||
|
|
||||||
say "Running the #{hook} hook...", :magenta
|
say "Running the #{hook} hook...", :magenta
|
||||||
@@ -182,6 +188,10 @@ module Kamal::Cli
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def run_hook?(hook)
|
||||||
|
!options[:skip_hooks] && Kamal::Hooks.exists?(hook)
|
||||||
|
end
|
||||||
|
|
||||||
def on(*args, &block)
|
def on(*args, &block)
|
||||||
if !KAMAL.connected?
|
if !KAMAL.connected?
|
||||||
run_hook "pre-connect"
|
run_hook "pre-connect"
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ class Kamal::Cli::Main < Kamal::Cli::Base
|
|||||||
invoke "kamal:cli:server:bootstrap", [], invoke_options
|
invoke "kamal:cli:server:bootstrap", [], invoke_options
|
||||||
|
|
||||||
say "Evaluate and push env files...", :magenta
|
say "Evaluate and push env files...", :magenta
|
||||||
invoke "kamal:cli:main:envify", [], invoke_options
|
|
||||||
invoke "kamal:cli:env:push", [], invoke_options
|
invoke "kamal:cli:env:push", [], invoke_options
|
||||||
|
|
||||||
invoke "kamal:cli:accessory:boot", [ "all" ], invoke_options
|
invoke "kamal:cli:accessory:boot", [ "all" ], invoke_options
|
||||||
@@ -179,31 +178,6 @@ class Kamal::Cli::Main < Kamal::Cli::Base
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
desc "envify", "Create .env by evaluating .env.erb (or .env.staging.erb -> .env.staging when using -d staging)"
|
|
||||||
option :skip_push, aliases: "-P", type: :boolean, default: false, desc: "Skip .env file push"
|
|
||||||
def envify
|
|
||||||
if destination = options[:destination]
|
|
||||||
env_template_path = ".env.#{destination}.erb"
|
|
||||||
env_path = ".env.#{destination}"
|
|
||||||
else
|
|
||||||
env_template_path = ".env.erb"
|
|
||||||
env_path = ".env"
|
|
||||||
end
|
|
||||||
|
|
||||||
if Pathname.new(File.expand_path(env_template_path)).exist?
|
|
||||||
# Ensure existing env doesn't pollute template evaluation
|
|
||||||
content = with_original_env { ERB.new(File.read(env_template_path), trim_mode: "-").result }
|
|
||||||
File.write(env_path, content, perm: 0600)
|
|
||||||
|
|
||||||
unless options[:skip_push]
|
|
||||||
reload_env
|
|
||||||
invoke "kamal:cli:env:push", options
|
|
||||||
end
|
|
||||||
else
|
|
||||||
puts "Skipping envify (no #{env_template_path} exist)"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
desc "remove", "Remove Traefik, app, accessories, and registry session from servers"
|
desc "remove", "Remove Traefik, app, accessories, and registry session from servers"
|
||||||
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
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
class Kamal::Cli::Server < Kamal::Cli::Base
|
class Kamal::Cli::Server < Kamal::Cli::Base
|
||||||
desc "exec", "Run a custom command on the server (use --help to show options)"
|
desc "exec", "Run a custom command on the server (use --help to show options)"
|
||||||
option :interactive, type: :boolean, aliases: "-i", default: false, desc: "Run the command interactively (use for console/bash)"
|
option :interactive, type: :boolean, aliases: "-i", default: false, desc: "Run the command interactively (use for console/bash)"
|
||||||
def exec(*cmd)
|
def exec(cmd)
|
||||||
cmd = Kamal::Utils.join_commands(cmd)
|
|
||||||
hosts = KAMAL.hosts | KAMAL.accessory_hosts
|
hosts = KAMAL.hosts | KAMAL.accessory_hosts
|
||||||
|
|
||||||
case
|
case
|
||||||
|
|||||||
@@ -27,11 +27,7 @@ class Kamal::Commander
|
|||||||
|
|
||||||
def specific_primary!
|
def specific_primary!
|
||||||
@specifics = nil
|
@specifics = nil
|
||||||
if specific_roles.present?
|
self.specific_hosts = [ config.primary_host ]
|
||||||
self.specific_hosts = [ specific_roles.first.primary_host ]
|
|
||||||
else
|
|
||||||
self.specific_hosts = [ config.primary_host ]
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def specific_roles=(role_names)
|
def specific_roles=(role_names)
|
||||||
@@ -117,10 +113,6 @@ class Kamal::Commander
|
|||||||
@traefik ||= Kamal::Commands::Traefik.new(config)
|
@traefik ||= Kamal::Commands::Traefik.new(config)
|
||||||
end
|
end
|
||||||
|
|
||||||
def alias(name)
|
|
||||||
config.aliases[name]
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
def with_verbosity(level)
|
def with_verbosity(level)
|
||||||
old_level = self.verbosity
|
old_level = self.verbosity
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ module Kamal::Commands::Builder::Clone
|
|||||||
end
|
end
|
||||||
|
|
||||||
def clone
|
def clone
|
||||||
git :clone, Kamal::Git.root, "--recurse-submodules", path: clone_directory
|
git :clone, Kamal::Git.root, path: clone_directory
|
||||||
end
|
end
|
||||||
|
|
||||||
def clone_reset_steps
|
def clone_reset_steps
|
||||||
@@ -14,8 +14,7 @@ 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
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,5 @@
|
|||||||
class Kamal::Commands::Hook < Kamal::Commands::Base
|
class Kamal::Commands::Hook < Kamal::Commands::Base
|
||||||
def run(hook, **details)
|
def run(hook, **details)
|
||||||
[ hook_file(hook), env: tags(**details).env ]
|
[ Kamal::Hooks.file(hook), env: tags(**details).env ]
|
||||||
end
|
end
|
||||||
|
|
||||||
def hook_exists?(hook)
|
|
||||||
Pathname.new(hook_file(hook)).exist?
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
def hook_file(hook)
|
|
||||||
File.join(config.hooks_path, hook)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ require "erb"
|
|||||||
require "net/ssh/proxy/jump"
|
require "net/ssh/proxy/jump"
|
||||||
|
|
||||||
class Kamal::Configuration
|
class Kamal::Configuration
|
||||||
delegate :service, :image, :labels, :stop_wait_time, :hooks_path, to: :raw_config, allow_nil: true
|
delegate :service, :image, :labels, :stop_wait_time, to: :raw_config, allow_nil: true
|
||||||
delegate :argumentize, :optionize, to: Kamal::Utils
|
delegate :argumentize, :optionize, to: Kamal::Utils
|
||||||
|
|
||||||
attr_reader :destination, :raw_config
|
attr_reader :destination, :raw_config
|
||||||
attr_reader :accessories, :aliases, :boot, :builder, :env, :healthcheck, :logging, :traefik, :servers, :ssh, :sshkit, :registry
|
attr_reader :accessories, :boot, :builder, :env, :healthcheck, :logging, :traefik, :servers, :ssh, :sshkit, :registry
|
||||||
|
|
||||||
include Validation
|
include Validation
|
||||||
|
|
||||||
@@ -54,7 +54,6 @@ class Kamal::Configuration
|
|||||||
@registry = Registry.new(config: self)
|
@registry = Registry.new(config: self)
|
||||||
|
|
||||||
@accessories = @raw_config.accessories&.keys&.collect { |name| Accessory.new(name, config: self) } || []
|
@accessories = @raw_config.accessories&.keys&.collect { |name| Accessory.new(name, config: self) } || []
|
||||||
@aliases = @raw_config.aliases&.keys&.to_h { |name| [ name, Alias.new(name, config: self) ] } || {}
|
|
||||||
@boot = Boot.new(config: self)
|
@boot = Boot.new(config: self)
|
||||||
@builder = Builder.new(config: self)
|
@builder = Builder.new(config: self)
|
||||||
@env = Env.new(config: @raw_config.env || {})
|
@env = Env.new(config: @raw_config.env || {})
|
||||||
@@ -209,10 +208,6 @@ class Kamal::Configuration
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def hooks_path
|
|
||||||
raw_config.hooks_path || ".kamal/hooks"
|
|
||||||
end
|
|
||||||
|
|
||||||
def asset_path
|
def asset_path
|
||||||
raw_config.asset_path
|
raw_config.asset_path
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
class Kamal::Configuration::Alias
|
|
||||||
include Kamal::Configuration::Validation
|
|
||||||
|
|
||||||
attr_reader :name, :command
|
|
||||||
|
|
||||||
def initialize(name, config:)
|
|
||||||
@name, @command = name.inquiry, config.raw_config["aliases"][name]
|
|
||||||
|
|
||||||
validate! \
|
|
||||||
command,
|
|
||||||
example: validation_yml["aliases"]["uname"],
|
|
||||||
context: "aliases/#{name}",
|
|
||||||
with: Kamal::Configuration::Validator::Alias
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
# Aliases
|
|
||||||
#
|
|
||||||
# Aliases are shortcuts for Kamal commands.
|
|
||||||
#
|
|
||||||
# For example, for a Rails app, you might open a console with:
|
|
||||||
#
|
|
||||||
# ```shell
|
|
||||||
# kamal app exec -i -r console "rails console"
|
|
||||||
# ```
|
|
||||||
#
|
|
||||||
# By defining an alias, like this:
|
|
||||||
aliases:
|
|
||||||
console: app exec -r console -i "rails console"
|
|
||||||
# You can now open the console with:
|
|
||||||
# ```shell
|
|
||||||
# kamal console
|
|
||||||
# ```
|
|
||||||
|
|
||||||
# Configuring aliases
|
|
||||||
#
|
|
||||||
# Aliases are defined in the root config under the alias key
|
|
||||||
#
|
|
||||||
# Each alias is named and can only contain lowercase letters, numbers, dashes and underscores.
|
|
||||||
|
|
||||||
aliases:
|
|
||||||
uname: app exec -p -q -r web "uname -a"
|
|
||||||
@@ -74,10 +74,6 @@ env:
|
|||||||
# To configure this, set the path to the assets:
|
# To configure this, set the path to the assets:
|
||||||
asset_path: /path/to/assets
|
asset_path: /path/to/assets
|
||||||
|
|
||||||
# Path to hooks, defaults to `.kamal/hooks`
|
|
||||||
# See https://kamal-deploy.org/docs/hooks for more information
|
|
||||||
hooks_path: /user_home/kamal/hooks
|
|
||||||
|
|
||||||
# Require destinations
|
# Require destinations
|
||||||
#
|
#
|
||||||
# Whether deployments require a destination to be specified, defaults to `false`
|
# Whether deployments require a destination to be specified, defaults to `false`
|
||||||
@@ -166,9 +162,3 @@ healthcheck:
|
|||||||
# Docker logging configuration, see kamal docs logging
|
# Docker logging configuration, see kamal docs logging
|
||||||
logging:
|
logging:
|
||||||
...
|
...
|
||||||
|
|
||||||
# Aliases
|
|
||||||
#
|
|
||||||
# Alias configuration, see kamal docs alias
|
|
||||||
aliases:
|
|
||||||
...
|
|
||||||
|
|||||||
@@ -24,14 +24,14 @@ env:
|
|||||||
# KAMAL_REGISTRY_PASSWORD=pw
|
# KAMAL_REGISTRY_PASSWORD=pw
|
||||||
# DB_PASSWORD=secret123
|
# DB_PASSWORD=secret123
|
||||||
# ```
|
# ```
|
||||||
# See https://kamal-deploy.org/docs/commands/envify/ for how to use generated .env files.
|
# See https://kamal-deploy.org/docs/commands/env/ for how to use generated .env files.
|
||||||
#
|
#
|
||||||
# To pass the secrets you should list them under the `secret` key. When you do this the
|
# To pass the secrets you should list them under the `secret` key. When you do this the
|
||||||
# other variables need to be moved under the `clear` key.
|
# other variables need to be moved under the `clear` key.
|
||||||
#
|
#
|
||||||
# Unlike clear values, secrets are not passed directly to the container,
|
# Unlike clear values, secrets are not passed directly to the container,
|
||||||
# but are stored in an env file on the host
|
# but are stored in an env file on the host
|
||||||
# The file is not updated when deploying, only when running `kamal envify` or `kamal env push`.
|
# The file is not updated when deploying, only when running `kamal env push`.
|
||||||
env:
|
env:
|
||||||
clear:
|
clear:
|
||||||
DB_USER: app
|
DB_USER: app
|
||||||
|
|||||||
@@ -13,34 +13,32 @@ class Kamal::Configuration::Validator
|
|||||||
|
|
||||||
private
|
private
|
||||||
def validate_against_example!(validation_config, example)
|
def validate_against_example!(validation_config, example)
|
||||||
validate_type! validation_config, example.class
|
validate_type! validation_config, Hash
|
||||||
|
|
||||||
if example.class == Hash
|
check_unknown_keys! validation_config, example
|
||||||
check_unknown_keys! validation_config, example
|
|
||||||
|
|
||||||
validation_config.each do |key, value|
|
validation_config.each do |key, value|
|
||||||
next if extension?(key)
|
next if extension?(key)
|
||||||
with_context(key) do
|
with_context(key) do
|
||||||
example_value = example[key]
|
example_value = example[key]
|
||||||
|
|
||||||
if example_value == "..."
|
if example_value == "..."
|
||||||
validate_type! value, *(Array if key == :servers), Hash
|
validate_type! value, *(Array if key == :servers), Hash
|
||||||
elsif key == "hosts"
|
elsif key == "hosts"
|
||||||
validate_servers! value
|
validate_servers! value
|
||||||
elsif example_value.is_a?(Array)
|
elsif example_value.is_a?(Array)
|
||||||
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", "args"
|
when "options", "args"
|
||||||
validate_type! value, Hash
|
validate_type! value, Hash
|
||||||
when "labels"
|
when "labels"
|
||||||
validate_hash_of! value, example_value.first[1].class
|
validate_hash_of! value, example_value.first[1].class
|
||||||
else
|
|
||||||
validate_against_example! value, example_value
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
validate_type! value, example_value.class
|
validate_against_example! value, example_value
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
validate_type! value, example_value.class
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
class Kamal::Configuration::Validator::Alias < Kamal::Configuration::Validator
|
|
||||||
def validate!
|
|
||||||
super
|
|
||||||
|
|
||||||
name = context.delete_prefix("aliases/")
|
|
||||||
|
|
||||||
if name !~ /\A[a-z0-9_-]+\z/
|
|
||||||
error "Invalid alias name: '#{name}'. Must only contain lowercase letters, alphanumeric, hyphens and underscores."
|
|
||||||
end
|
|
||||||
|
|
||||||
if Kamal::Cli::Main.commands.include?(name)
|
|
||||||
error "Alias '#{name}' conflicts with a built-in command."
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -77,8 +77,4 @@ module Kamal::Utils
|
|||||||
def stable_sort!(elements, &block)
|
def stable_sort!(elements, &block)
|
||||||
elements.sort_by!.with_index { |element, index| [ block.call(element), index ] }
|
elements.sort_by!.with_index { |element, index| [ block.call(element), index ] }
|
||||||
end
|
end
|
||||||
|
|
||||||
def join_commands(commands)
|
|
||||||
commands.map(&:strip).join(" ")
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
module Kamal
|
module Kamal
|
||||||
VERSION = "2.0.0.alpha"
|
VERSION = "1.8.1"
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -247,12 +247,6 @@ class CliAppTest < CliTestCase
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
test "exec separate arguments" do
|
|
||||||
run_command("exec", "ruby", " -v").tap do |output|
|
|
||||||
assert_match "docker run --rm --env-file .kamal/env/roles/app-web.env dhh/app:latest ruby -v", output
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
test "exec with reuse" do
|
test "exec with reuse" do
|
||||||
run_command("exec", "--reuse", "ruby -v").tap do |output|
|
run_command("exec", "--reuse", "ruby -v").tap do |output|
|
||||||
assert_match "sh -c 'docker ps --latest --format '\\''{{.Names}}'\\'' --filter label=service=app --filter label=role=web --filter status=running --filter status=restarting --filter ancestor=$(docker image ls --filter reference=dhh/app:latest --format '\\''{{.ID}}'\\'') ; docker ps --latest --format '\\''{{.Names}}'\\'' --filter label=service=app --filter label=role=web --filter status=running --filter status=restarting' | head -1 | while read line; do echo ${line#app-web-}; done", output # Get current version
|
assert_match "sh -c 'docker ps --latest --format '\\''{{.Names}}'\\'' --filter label=service=app --filter label=role=web --filter status=running --filter status=restarting --filter ancestor=$(docker image ls --filter reference=dhh/app:latest --format '\\''{{.ID}}'\\'') ; docker ps --latest --format '\\''{{.Names}}'\\'' --filter label=service=app --filter label=role=web --filter status=running --filter status=restarting' | head -1 | while read line; do echo ${line#app-web-}; done", output # Get current version
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ class CliBuildTest < CliTestCase
|
|||||||
|
|
||||||
test "push" do
|
test "push" do
|
||||||
with_build_directory do |build_directory|
|
with_build_directory do |build_directory|
|
||||||
Kamal::Commands::Hook.any_instance.stubs(:hook_exists?).returns(true)
|
Kamal::Hooks.stubs(:exists?).returns(true)
|
||||||
hook_variables = { version: 999, service_version: "app@999", hosts: "1.1.1.1,1.1.1.2,1.1.1.3,1.1.1.4", command: "build", subcommand: "push" }
|
hook_variables = { version: 999, service_version: "app@999", hosts: "1.1.1.1,1.1.1.2,1.1.1.3,1.1.1.4", command: "build", subcommand: "push" }
|
||||||
|
|
||||||
SSHKit::Backend::Abstract.any_instance.expects(:capture_with_info)
|
SSHKit::Backend::Abstract.any_instance.expects(:capture_with_info)
|
||||||
@@ -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, "--recurse-submodules")
|
.with(:git, "-C", "#{Dir.tmpdir}/kamal-clones/app-#{pwd_sha}", :clone, Dir.pwd)
|
||||||
.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,7 +50,6 @@ 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", ".")
|
||||||
@@ -71,7 +70,7 @@ class CliBuildTest < CliTestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
test "push without clone" do
|
test "push without clone" do
|
||||||
Kamal::Commands::Hook.any_instance.stubs(:hook_exists?).returns(true)
|
Kamal::Hooks.stubs(:exists?).returns(true)
|
||||||
hook_variables = { version: 999, service_version: "app@999", hosts: "1.1.1.1,1.1.1.2,1.1.1.3,1.1.1.4", command: "build", subcommand: "push" }
|
hook_variables = { version: 999, service_version: "app@999", hosts: "1.1.1.1,1.1.1.2,1.1.1.3,1.1.1.4", command: "build", subcommand: "push" }
|
||||||
|
|
||||||
run_command("push", "--verbose", fixture: :without_clone).tap do |output|
|
run_command("push", "--verbose", fixture: :without_clone).tap do |output|
|
||||||
@@ -89,7 +88,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, "--recurse-submodules")
|
.with(:git, "-C", "#{Dir.tmpdir}/kamal-clones/app-#{pwd_sha}", :clone, Dir.pwd)
|
||||||
.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)
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ class CliTestCase < ActiveSupport::TestCase
|
|||||||
private
|
private
|
||||||
def fail_hook(hook)
|
def fail_hook(hook)
|
||||||
@executions = []
|
@executions = []
|
||||||
Kamal::Commands::Hook.any_instance.stubs(:hook_exists?).returns(true)
|
Kamal::Hooks.stubs(: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}" ] }
|
||||||
@@ -63,12 +63,4 @@ class CliTestCase < ActiveSupport::TestCase
|
|||||||
|
|
||||||
assert_match expected, output
|
assert_match expected, output
|
||||||
end
|
end
|
||||||
|
|
||||||
def with_argv(*argv)
|
|
||||||
old_argv = ARGV
|
|
||||||
ARGV.replace(*argv)
|
|
||||||
yield
|
|
||||||
ensure
|
|
||||||
ARGV.replace(old_argv)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ class CliMainTest < CliTestCase
|
|||||||
invoke_options = { "config_file" => "test/fixtures/deploy_simple.yml", "version" => "999", "skip_hooks" => false }
|
invoke_options = { "config_file" => "test/fixtures/deploy_simple.yml", "version" => "999", "skip_hooks" => false }
|
||||||
|
|
||||||
Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:server:bootstrap", [], invoke_options)
|
Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:server:bootstrap", [], invoke_options)
|
||||||
Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:main:envify", [], invoke_options)
|
|
||||||
Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:env:push", [], invoke_options)
|
Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:env:push", [], invoke_options)
|
||||||
Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:accessory:boot", [ "all" ], invoke_options)
|
Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:accessory:boot", [ "all" ], invoke_options)
|
||||||
Kamal::Cli::Main.any_instance.expects(:deploy)
|
Kamal::Cli::Main.any_instance.expects(:deploy)
|
||||||
@@ -24,7 +23,6 @@ class CliMainTest < CliTestCase
|
|||||||
|
|
||||||
Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:server:bootstrap", [], invoke_options)
|
Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:server:bootstrap", [], invoke_options)
|
||||||
Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:env:push", [], invoke_options)
|
Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:env:push", [], invoke_options)
|
||||||
Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:main:envify", [], invoke_options)
|
|
||||||
Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:accessory:boot", [ "all" ], invoke_options)
|
Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:accessory:boot", [ "all" ], invoke_options)
|
||||||
# deploy
|
# deploy
|
||||||
Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:registry:login", [], invoke_options.merge(skip_local: true))
|
Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:registry:login", [], invoke_options.merge(skip_local: true))
|
||||||
@@ -58,10 +56,11 @@ class CliMainTest < CliTestCase
|
|||||||
Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:app:boot", [], invoke_options)
|
Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:app:boot", [], invoke_options)
|
||||||
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)
|
||||||
|
|
||||||
Kamal::Commands::Hook.any_instance.stubs(:hook_exists?).returns(true)
|
Kamal::Hooks.stubs(:exists?).returns(true)
|
||||||
hook_variables = { version: 999, service_version: "app@999", hosts: "1.1.1.1,1.1.1.2", command: "deploy" }
|
hook_variables = { version: 999, service_version: "app@999", hosts: "1.1.1.1,1.1.1.2", command: "deploy" }
|
||||||
|
|
||||||
run_command("deploy", "--verbose").tap do |output|
|
run_command("deploy", "--verbose").tap do |output|
|
||||||
|
assert_match "Running the pre-init hook...", output
|
||||||
assert_hook_ran "pre-connect", output, **hook_variables
|
assert_hook_ran "pre-connect", output, **hook_variables
|
||||||
assert_match /Log into image registry/, output
|
assert_match /Log into image registry/, output
|
||||||
assert_match /Build and push app image/, output
|
assert_match /Build and push app image/, output
|
||||||
@@ -237,7 +236,7 @@ class CliMainTest < CliTestCase
|
|||||||
Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:app:stale_containers", [], invoke_options.merge(stop: true))
|
Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:app:stale_containers", [], invoke_options.merge(stop: true))
|
||||||
Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:app:boot", [], invoke_options)
|
Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:app:boot", [], invoke_options)
|
||||||
|
|
||||||
Kamal::Commands::Hook.any_instance.stubs(:hook_exists?).returns(true)
|
Kamal::Hooks.stubs(:exists?).returns(true)
|
||||||
|
|
||||||
hook_variables = { version: 999, service_version: "app@999", hosts: "1.1.1.1,1.1.1.2", command: "redeploy" }
|
hook_variables = { version: 999, service_version: "app@999", hosts: "1.1.1.1,1.1.1.2", command: "redeploy" }
|
||||||
|
|
||||||
@@ -298,7 +297,7 @@ class CliMainTest < CliTestCase
|
|||||||
.with(:docker, :container, :ls, "--all", "--filter", "name=^app-web-version-to-rollback$", "--quiet", "|", :xargs, :docker, :inspect, "--format", "'{{if .State.Health}}{{.State.Health.Status}}{{else}}{{.State.Status}}{{end}}'")
|
.with(:docker, :container, :ls, "--all", "--filter", "name=^app-web-version-to-rollback$", "--quiet", "|", :xargs, :docker, :inspect, "--format", "'{{if .State.Health}}{{.State.Health.Status}}{{else}}{{.State.Status}}{{end}}'")
|
||||||
.returns("unhealthy").at_least_once # health check
|
.returns("unhealthy").at_least_once # health check
|
||||||
|
|
||||||
Kamal::Commands::Hook.any_instance.stubs(:hook_exists?).returns(true)
|
Kamal::Hooks.stubs(:exists?).returns(true)
|
||||||
hook_variables = { version: 123, service_version: "app@123", hosts: "1.1.1.1,1.1.1.2,1.1.1.3,1.1.1.4", command: "rollback" }
|
hook_variables = { version: 123, service_version: "app@123", hosts: "1.1.1.1,1.1.1.2,1.1.1.3,1.1.1.4", command: "rollback" }
|
||||||
|
|
||||||
run_command("rollback", "--verbose", "123", config_file: "deploy_with_accessories").tap do |output|
|
run_command("rollback", "--verbose", "123", config_file: "deploy_with_accessories").tap do |output|
|
||||||
@@ -396,7 +395,7 @@ class CliMainTest < CliTestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
test "init" do
|
test "init" do
|
||||||
Pathname.any_instance.expects(:exist?).returns(false).times(3)
|
Pathname.any_instance.expects(:exist?).returns(false).times(4)
|
||||||
Pathname.any_instance.stubs(:mkpath)
|
Pathname.any_instance.stubs(:mkpath)
|
||||||
FileUtils.stubs(:mkdir_p)
|
FileUtils.stubs(:mkdir_p)
|
||||||
FileUtils.stubs(:cp_r)
|
FileUtils.stubs(:cp_r)
|
||||||
@@ -409,7 +408,7 @@ class CliMainTest < CliTestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
test "init with existing config" do
|
test "init with existing config" do
|
||||||
Pathname.any_instance.expects(:exist?).returns(true).times(3)
|
Pathname.any_instance.expects(:exist?).returns(true).times(4)
|
||||||
|
|
||||||
run_command("init").tap do |output|
|
run_command("init").tap do |output|
|
||||||
assert_match /Config file already exists in config\/deploy.yml \(remove first to create a new one\)/, output
|
assert_match /Config file already exists in config\/deploy.yml \(remove first to create a new one\)/, output
|
||||||
@@ -417,7 +416,7 @@ class CliMainTest < CliTestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
test "init with bundle option" do
|
test "init with bundle option" do
|
||||||
Pathname.any_instance.expects(:exist?).returns(false).times(4)
|
Pathname.any_instance.expects(:exist?).returns(false).times(5)
|
||||||
Pathname.any_instance.stubs(:mkpath)
|
Pathname.any_instance.stubs(:mkpath)
|
||||||
FileUtils.stubs(:mkdir_p)
|
FileUtils.stubs(:mkdir_p)
|
||||||
FileUtils.stubs(:cp_r)
|
FileUtils.stubs(:cp_r)
|
||||||
@@ -434,7 +433,7 @@ class CliMainTest < CliTestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
test "init with bundle option and existing binstub" do
|
test "init with bundle option and existing binstub" do
|
||||||
Pathname.any_instance.expects(:exist?).returns(true).times(4)
|
Pathname.any_instance.expects(:exist?).returns(true).times(5)
|
||||||
Pathname.any_instance.stubs(:mkpath)
|
Pathname.any_instance.stubs(:mkpath)
|
||||||
FileUtils.stubs(:mkdir_p)
|
FileUtils.stubs(:mkdir_p)
|
||||||
FileUtils.stubs(:cp_r)
|
FileUtils.stubs(:cp_r)
|
||||||
@@ -446,50 +445,6 @@ class CliMainTest < CliTestCase
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
test "envify" do
|
|
||||||
with_test_dotenv(".env.erb": "HELLO=<%= 'world' %>") do
|
|
||||||
run_command("envify")
|
|
||||||
assert_equal("HELLO=world", File.read(".env"))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
test "envify with blank line trimming" do
|
|
||||||
file = <<~EOF
|
|
||||||
HELLO=<%= 'world' %>
|
|
||||||
<% if true -%>
|
|
||||||
KEY=value
|
|
||||||
<% end -%>
|
|
||||||
EOF
|
|
||||||
|
|
||||||
with_test_dotenv(".env.erb": file) do
|
|
||||||
run_command("envify")
|
|
||||||
assert_equal("HELLO=world\nKEY=value\n", File.read(".env"))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
test "envify with destination" do
|
|
||||||
with_test_dotenv(".env.world.erb": "HELLO=<%= 'world' %>") do
|
|
||||||
run_command("envify", "-d", "world", config_file: "deploy_for_dest")
|
|
||||||
assert_equal "HELLO=world", File.read(".env.world")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
test "envify with skip_push" do
|
|
||||||
Pathname.any_instance.expects(:exist?).returns(true).times(1)
|
|
||||||
File.expects(:read).with(".env.erb").returns("HELLO=<%= 'world' %>")
|
|
||||||
File.expects(:write).with(".env", "HELLO=world", perm: 0600)
|
|
||||||
|
|
||||||
Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:env:push").never
|
|
||||||
run_command("envify", "--skip-push")
|
|
||||||
end
|
|
||||||
|
|
||||||
test "envify with clean env" do
|
|
||||||
with_test_dotenv(".env": "HELLO=already", ".env.erb": "HELLO=<%= ENV.fetch 'HELLO', 'never' %>") do
|
|
||||||
run_command("envify", "--skip-push")
|
|
||||||
assert_equal "HELLO=never", File.read(".env")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
test "remove with confirmation" do
|
test "remove with confirmation" do
|
||||||
run_command("remove", "-y", config_file: "deploy_with_accessories").tap do |output|
|
run_command("remove", "-y", config_file: "deploy_with_accessories").tap do |output|
|
||||||
assert_match /docker container stop traefik/, output
|
assert_match /docker container stop traefik/, output
|
||||||
@@ -537,47 +492,9 @@ class CliMainTest < CliTestCase
|
|||||||
assert_equal Kamal::VERSION, version
|
assert_equal Kamal::VERSION, version
|
||||||
end
|
end
|
||||||
|
|
||||||
test "run an alias for details" do
|
|
||||||
Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:traefik:details")
|
|
||||||
Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:app:details")
|
|
||||||
Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:accessory:details", [ "all" ])
|
|
||||||
|
|
||||||
run_command("info", config_file: "deploy_with_aliases")
|
|
||||||
end
|
|
||||||
|
|
||||||
test "run an alias for a console" do
|
|
||||||
run_command("console", config_file: "deploy_with_aliases").tap do |output|
|
|
||||||
assert_match "docker exec app-console-999 bin/console on 1.1.1.5", output
|
|
||||||
assert_match "App Host: 1.1.1.5", output
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
test "run an alias for a console overriding role" do
|
|
||||||
run_command("console", "-r", "workers", config_file: "deploy_with_aliases").tap do |output|
|
|
||||||
assert_match "docker exec app-workers-999 bin/console on 1.1.1.3", output
|
|
||||||
assert_match "App Host: 1.1.1.3", output
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
test "run an alias for a console passing command" do
|
|
||||||
run_command("exec", "bin/job", config_file: "deploy_with_aliases").tap do |output|
|
|
||||||
assert_match "docker exec app-console-999 bin/job on 1.1.1.5", output
|
|
||||||
assert_match "App Host: 1.1.1.5", output
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
test "append to command with an alias" do
|
|
||||||
run_command("rails", "db:migrate:status", config_file: "deploy_with_aliases").tap do |output|
|
|
||||||
assert_match "docker exec app-console-999 rails db:migrate:status on 1.1.1.5", output
|
|
||||||
assert_match "App Host: 1.1.1.5", output
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
private
|
||||||
def run_command(*command, config_file: "deploy_simple")
|
def run_command(*command, config_file: "deploy_simple")
|
||||||
with_argv([ *command, "-c", "test/fixtures/#{config_file}.yml" ]) do
|
stdouted { Kamal::Cli::Main.start([ *command, "-c", "test/fixtures/#{config_file}.yml" ]) }
|
||||||
stdouted { Kamal::Cli::Main.start }
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def with_test_dotenv(**files)
|
def with_test_dotenv(**files)
|
||||||
@@ -587,8 +504,11 @@ class CliMainTest < CliTestCase
|
|||||||
FileUtils.cp_r("test/fixtures/", fixtures_dup)
|
FileUtils.cp_r("test/fixtures/", fixtures_dup)
|
||||||
|
|
||||||
Dir.chdir(dir) do
|
Dir.chdir(dir) do
|
||||||
files.each do |filename, contents|
|
FileUtils.mkdir_p(".kamal")
|
||||||
File.binwrite(filename.to_s, contents)
|
Dir.chdir(".kamal") do
|
||||||
|
files.each do |filename, contents|
|
||||||
|
File.binwrite(filename.to_s, contents)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
yield
|
yield
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ require_relative "cli_test_case"
|
|||||||
class CliServerTest < CliTestCase
|
class CliServerTest < CliTestCase
|
||||||
test "running a command with exec" do
|
test "running a command with exec" do
|
||||||
SSHKit::Backend::Abstract.any_instance.stubs(:capture)
|
SSHKit::Backend::Abstract.any_instance.stubs(:capture)
|
||||||
.with("date", verbosity: 1)
|
.with("date", verbosity: 1)
|
||||||
.returns("Today")
|
.returns("Today")
|
||||||
|
|
||||||
hosts = "1.1.1.1".."1.1.1.4"
|
hosts = "1.1.1.1".."1.1.1.4"
|
||||||
run_command("exec", "date").tap do |output|
|
run_command("exec", "date").tap do |output|
|
||||||
@@ -15,20 +15,6 @@ class CliServerTest < CliTestCase
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
test "running a command with exec multiple arguments" do
|
|
||||||
SSHKit::Backend::Abstract.any_instance.stubs(:capture)
|
|
||||||
.with("date -j", verbosity: 1)
|
|
||||||
.returns("Today")
|
|
||||||
|
|
||||||
hosts = "1.1.1.1".."1.1.1.4"
|
|
||||||
run_command("exec", "date", "-j").tap do |output|
|
|
||||||
hosts.map do |host|
|
|
||||||
assert_match "Running 'date -j' on #{hosts.to_a.join(', ')}...", output
|
|
||||||
assert_match "App Host: #{host}\nToday", output
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
test "bootstrap already installed" do
|
test "bootstrap already installed" do
|
||||||
stub_setup
|
stub_setup
|
||||||
SSHKit::Backend::Abstract.any_instance.expects(:execute).with(:docker, "-v", raise_on_non_zero_exit: false).returns(true).at_least_once
|
SSHKit::Backend::Abstract.any_instance.expects(:execute).with(:docker, "-v", raise_on_non_zero_exit: false).returns(true).at_least_once
|
||||||
@@ -54,7 +40,8 @@ class CliServerTest < CliTestCase
|
|||||||
SSHKit::Backend::Abstract.any_instance.expects(:execute).with('[ "${EUID:-$(id -u)}" -eq 0 ] || command -v sudo >/dev/null || command -v su >/dev/null', raise_on_non_zero_exit: false).returns(true).at_least_once
|
SSHKit::Backend::Abstract.any_instance.expects(:execute).with('[ "${EUID:-$(id -u)}" -eq 0 ] || command -v sudo >/dev/null || command -v su >/dev/null', raise_on_non_zero_exit: false).returns(true).at_least_once
|
||||||
SSHKit::Backend::Abstract.any_instance.expects(:execute).with(:sh, "-c", "'curl -fsSL https://get.docker.com || wget -O - https://get.docker.com || echo \"exit 1\"'", "|", :sh).at_least_once
|
SSHKit::Backend::Abstract.any_instance.expects(:execute).with(:sh, "-c", "'curl -fsSL https://get.docker.com || wget -O - https://get.docker.com || echo \"exit 1\"'", "|", :sh).at_least_once
|
||||||
SSHKit::Backend::Abstract.any_instance.expects(:execute).with(:mkdir, "-p", ".kamal").returns("").at_least_once
|
SSHKit::Backend::Abstract.any_instance.expects(:execute).with(:mkdir, "-p", ".kamal").returns("").at_least_once
|
||||||
Kamal::Commands::Hook.any_instance.stubs(:hook_exists?).returns(true)
|
Kamal::Hooks.stubs(:exists?).returns(true)
|
||||||
|
SSHKit::Backend::Abstract.any_instance.expects(:execute).with(".kamal/hooks/pre-init", anything).at_least_once
|
||||||
SSHKit::Backend::Abstract.any_instance.expects(:execute).with(".kamal/hooks/pre-connect", anything).at_least_once
|
SSHKit::Backend::Abstract.any_instance.expects(:execute).with(".kamal/hooks/pre-connect", anything).at_least_once
|
||||||
SSHKit::Backend::Abstract.any_instance.expects(:execute).with(".kamal/hooks/docker-setup", anything).at_least_once
|
SSHKit::Backend::Abstract.any_instance.expects(:execute).with(".kamal/hooks/docker-setup", anything).at_least_once
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ class CommandsHookTest < ActiveSupport::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
test "run with custom hooks_path" do
|
test "run with custom hooks_path" do
|
||||||
|
ENV["KAMAL_HOOKS_PATH"] = "custom/hooks/path"
|
||||||
assert_equal [
|
assert_equal [
|
||||||
"custom/hooks/path/foo",
|
"custom/hooks/path/foo",
|
||||||
{ env: {
|
{ env: {
|
||||||
@@ -36,7 +37,9 @@ class CommandsHookTest < ActiveSupport::TestCase
|
|||||||
"KAMAL_VERSION" => "123",
|
"KAMAL_VERSION" => "123",
|
||||||
"KAMAL_SERVICE_VERSION" => "app@123",
|
"KAMAL_SERVICE_VERSION" => "app@123",
|
||||||
"KAMAL_SERVICE" => "app" } }
|
"KAMAL_SERVICE" => "app" } }
|
||||||
], new_command(hooks_path: "custom/hooks/path").run("foo")
|
], new_command.run("foo")
|
||||||
|
ensure
|
||||||
|
ENV.delete("KAMAL_HOOKS_PATH")
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ class ConfigurationValidationTest < ActiveSupport::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
test "wrong root types" do
|
test "wrong root types" do
|
||||||
[ :service, :image, :asset_path, :hooks_path, :primary_role, :minimum_version, :run_directory ].each do |key|
|
[ :service, :image, :asset_path, :primary_role, :minimum_version, :run_directory ].each do |key|
|
||||||
assert_error "#{key}: should be a string", **{ key => [] }
|
assert_error "#{key}: should be a string", **{ key => [] }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
21
test/fixtures/deploy_with_aliases.yml
vendored
21
test/fixtures/deploy_with_aliases.yml
vendored
@@ -1,21 +0,0 @@
|
|||||||
service: app
|
|
||||||
image: dhh/app
|
|
||||||
servers:
|
|
||||||
web:
|
|
||||||
- 1.1.1.1
|
|
||||||
- 1.1.1.2
|
|
||||||
workers:
|
|
||||||
hosts:
|
|
||||||
- 1.1.1.3
|
|
||||||
- 1.1.1.4
|
|
||||||
console:
|
|
||||||
hosts:
|
|
||||||
- 1.1.1.5
|
|
||||||
registry:
|
|
||||||
username: user
|
|
||||||
password: pw
|
|
||||||
aliases:
|
|
||||||
info: details
|
|
||||||
console: app exec --reuse -p -r console "bin/console"
|
|
||||||
exec: app exec --reuse -p -r console
|
|
||||||
rails: app exec --reuse -p -r console rails
|
|
||||||
@@ -2,8 +2,6 @@ require_relative "integration_test"
|
|||||||
|
|
||||||
class AccessoryTest < IntegrationTest
|
class AccessoryTest < IntegrationTest
|
||||||
test "boot, stop, start, restart, logs, remove" do
|
test "boot, stop, start, restart, logs, remove" do
|
||||||
kamal :envify
|
|
||||||
|
|
||||||
kamal :accessory, :boot, :busybox
|
kamal :accessory, :boot, :busybox
|
||||||
assert_accessory_running :busybox
|
assert_accessory_running :busybox
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,6 @@ require_relative "integration_test"
|
|||||||
|
|
||||||
class AppTest < IntegrationTest
|
class AppTest < IntegrationTest
|
||||||
test "stop, start, boot, logs, images, containers, exec, remove" do
|
test "stop, start, boot, logs, images, containers, exec, remove" do
|
||||||
kamal :envify
|
|
||||||
|
|
||||||
kamal :deploy
|
kamal :deploy
|
||||||
|
|
||||||
assert_app_is_up
|
assert_app_is_up
|
||||||
|
|||||||
@@ -4,8 +4,6 @@ class BrokenDeployTest < IntegrationTest
|
|||||||
test "deploying a bad image" do
|
test "deploying a bad image" do
|
||||||
@app = "app_with_roles"
|
@app = "app_with_roles"
|
||||||
|
|
||||||
kamal :envify
|
|
||||||
|
|
||||||
first_version = latest_app_version
|
first_version = latest_app_version
|
||||||
|
|
||||||
kamal :deploy
|
kamal :deploy
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ services:
|
|||||||
context: docker/registry
|
context: docker/registry
|
||||||
environment:
|
environment:
|
||||||
- REGISTRY_HTTP_ADDR=0.0.0.0:4443
|
- REGISTRY_HTTP_ADDR=0.0.0.0:4443
|
||||||
|
- REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt
|
||||||
|
- REGISTRY_HTTP_TLS_KEY=/certs/domain.key
|
||||||
volumes:
|
volumes:
|
||||||
- shared:/shared
|
- shared:/shared
|
||||||
- registry:/var/lib/registry/
|
- registry:/var/lib/registry/
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ COPY app_with_roles/ app_with_roles/
|
|||||||
|
|
||||||
RUN rm -rf /root/.ssh
|
RUN rm -rf /root/.ssh
|
||||||
RUN ln -s /shared/ssh /root/.ssh
|
RUN ln -s /shared/ssh /root/.ssh
|
||||||
|
RUN mkdir -p /etc/docker/certs.d/registry:4443 && ln -s /shared/certs/domain.crt /etc/docker/certs.d/registry:4443/ca.crt
|
||||||
|
|
||||||
RUN git config --global user.email "deployer@example.com"
|
RUN git config --global user.email "deployer@example.com"
|
||||||
RUN git config --global user.name "Deployer"
|
RUN git config --global user.name "Deployer"
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
SECRET_TOKEN='1234 with "中文"'
|
|
||||||
SECRET_TAG='TAGME'
|
|
||||||
@@ -1,4 +1,8 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
echo "About to lock..."
|
echo "About to lock..."
|
||||||
|
if [ "$KAMAL_HOSTS" != "vm1,vm2" ]; then
|
||||||
|
echo "Expected hosts to be 'vm1,vm2', got $KAMAL_HOSTS"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
mkdir -p /tmp/${TEST_ID} && touch /tmp/${TEST_ID}/pre-connect
|
mkdir -p /tmp/${TEST_ID} && touch /tmp/${TEST_ID}/pre-connect
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
SECRET_TOKEN='1234 with "中文"'
|
|
||||||
@@ -1,4 +1,8 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
echo "About to lock..."
|
echo "About to lock..."
|
||||||
|
if [ "$KAMAL_HOSTS" != "vm1,vm2,vm3" ]; then
|
||||||
|
echo "Expected hosts to be 'vm1,vm2,vm3', got $KAMAL_HOSTS"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
mkdir -p /tmp/${TEST_ID} && touch /tmp/${TEST_ID}/pre-connect
|
mkdir -p /tmp/${TEST_ID} && touch /tmp/${TEST_ID}/pre-connect
|
||||||
|
|||||||
@@ -37,7 +37,3 @@ accessories:
|
|||||||
- web
|
- web
|
||||||
stop_wait_time: 1
|
stop_wait_time: 1
|
||||||
readiness_delay: 0
|
readiness_delay: 0
|
||||||
aliases:
|
|
||||||
whome: version
|
|
||||||
worker_hostname: app exec -r workers -q --reuse hostname
|
|
||||||
uname: server exec -q -p uname
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
dockerd --max-concurrent-downloads 1 --insecure-registry registry:4443 &
|
dockerd --max-concurrent-downloads 1 &
|
||||||
|
|
||||||
exec sleep infinity
|
exec sleep infinity
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
|
while [ ! -f /certs/domain.crt ]; do sleep 1; done
|
||||||
|
|
||||||
exec /entrypoint.sh /etc/docker/registry/config.yml
|
exec /entrypoint.sh /etc/docker/registry/config.yml
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ RUN mkdir ssh && \
|
|||||||
COPY registry-dns.conf .
|
COPY registry-dns.conf .
|
||||||
COPY boot.sh .
|
COPY boot.sh .
|
||||||
|
|
||||||
|
RUN mkdir certs && openssl req -newkey rsa:4096 -nodes -sha256 -keyout certs/domain.key -x509 -days 365 -out certs/domain.crt -subj '/CN=registry' -extensions EXT -config registry-dns.conf
|
||||||
|
|
||||||
HEALTHCHECK --interval=1s CMD pgrep sleep
|
HEALTHCHECK --interval=1s CMD pgrep sleep
|
||||||
|
|
||||||
CMD ["./boot.sh"]
|
CMD ["./boot.sh"]
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ WORKDIR /work
|
|||||||
RUN apt-get update --fix-missing && apt-get -y install openssh-client openssh-server docker.io
|
RUN apt-get update --fix-missing && apt-get -y install openssh-client openssh-server docker.io
|
||||||
|
|
||||||
RUN mkdir /root/.ssh && ln -s /shared/ssh/id_rsa.pub /root/.ssh/authorized_keys
|
RUN mkdir /root/.ssh && ln -s /shared/ssh/id_rsa.pub /root/.ssh/authorized_keys
|
||||||
|
RUN mkdir -p /etc/docker/certs.d/registry:4443 && ln -s /shared/certs/domain.crt /etc/docker/certs.d/registry:4443/ca.crt
|
||||||
|
|
||||||
RUN echo "HOST_TOKEN=abcd" >> /etc/environment
|
RUN echo "HOST_TOKEN=abcd" >> /etc/environment
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,6 @@ while [ ! -f /root/.ssh/authorized_keys ]; do echo "Waiting for ssh keys"; sleep
|
|||||||
|
|
||||||
service ssh restart
|
service ssh restart
|
||||||
|
|
||||||
dockerd --max-concurrent-downloads 1 --insecure-registry registry:4443 &
|
dockerd --max-concurrent-downloads 1 &
|
||||||
|
|
||||||
exec sleep infinity
|
exec sleep infinity
|
||||||
|
|||||||
@@ -2,8 +2,6 @@ require_relative "integration_test"
|
|||||||
|
|
||||||
class LockTest < IntegrationTest
|
class LockTest < IntegrationTest
|
||||||
test "acquire, release, status" do
|
test "acquire, release, status" do
|
||||||
kamal :envify
|
|
||||||
|
|
||||||
kamal :lock, :acquire, "-m 'Integration Tests'"
|
kamal :lock, :acquire, "-m 'Integration Tests'"
|
||||||
|
|
||||||
status = kamal :lock, :status, capture: true
|
status = kamal :lock, :status, capture: true
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
require_relative "integration_test"
|
require_relative "integration_test"
|
||||||
|
|
||||||
class MainTest < IntegrationTest
|
class MainTest < IntegrationTest
|
||||||
test "envify, deploy, redeploy, rollback, details and audit" do
|
test "env push, deploy, redeploy, rollback, details and audit" do
|
||||||
kamal :envify
|
kamal :env, :push
|
||||||
assert_env_files
|
assert_env_files
|
||||||
remove_local_env_file
|
remove_local_env_file
|
||||||
|
|
||||||
@@ -12,19 +12,19 @@ class MainTest < IntegrationTest
|
|||||||
|
|
||||||
kamal :deploy
|
kamal :deploy
|
||||||
assert_app_is_up version: first_version
|
assert_app_is_up version: first_version
|
||||||
assert_hooks_ran "pre-connect", "pre-build", "pre-deploy", "post-deploy"
|
assert_hooks_ran "pre-init", "pre-connect", "pre-build", "pre-deploy", "post-deploy"
|
||||||
assert_envs version: first_version
|
assert_envs version: first_version
|
||||||
|
|
||||||
second_version = update_app_rev
|
second_version = update_app_rev
|
||||||
|
|
||||||
kamal :redeploy
|
kamal :redeploy
|
||||||
assert_app_is_up version: second_version
|
assert_app_is_up version: second_version
|
||||||
assert_hooks_ran "pre-connect", "pre-build", "pre-deploy", "post-deploy"
|
assert_hooks_ran "pre-init", "pre-connect", "pre-build", "pre-deploy", "post-deploy"
|
||||||
|
|
||||||
assert_accumulated_assets first_version, second_version
|
assert_accumulated_assets first_version, second_version
|
||||||
|
|
||||||
kamal :rollback, first_version
|
kamal :rollback, first_version
|
||||||
assert_hooks_ran "pre-connect", "pre-deploy", "post-deploy"
|
assert_hooks_ran "pre-init", "pre-connect", "pre-deploy", "post-deploy"
|
||||||
assert_app_is_up version: first_version
|
assert_app_is_up version: first_version
|
||||||
|
|
||||||
details = kamal :details, capture: true
|
details = kamal :details, capture: true
|
||||||
@@ -45,7 +45,7 @@ class MainTest < IntegrationTest
|
|||||||
test "app with roles" do
|
test "app with roles" do
|
||||||
@app = "app_with_roles"
|
@app = "app_with_roles"
|
||||||
|
|
||||||
kamal :envify
|
kamal :env, :push
|
||||||
|
|
||||||
version = latest_app_version
|
version = latest_app_version
|
||||||
|
|
||||||
@@ -54,7 +54,7 @@ class MainTest < IntegrationTest
|
|||||||
kamal :deploy
|
kamal :deploy
|
||||||
|
|
||||||
assert_app_is_up version: version
|
assert_app_is_up version: version
|
||||||
assert_hooks_ran "pre-connect", "pre-build", "pre-deploy", "post-deploy"
|
assert_hooks_ran "pre-init", "pre-connect", "pre-build", "pre-deploy", "post-deploy"
|
||||||
assert_container_running host: :vm3, name: "app-workers-#{version}"
|
assert_container_running host: :vm3, name: "app-workers-#{version}"
|
||||||
|
|
||||||
second_version = update_app_rev
|
second_version = update_app_rev
|
||||||
@@ -82,28 +82,12 @@ class MainTest < IntegrationTest
|
|||||||
assert_equal({ "cmd"=>"wget -qO- http://localhost > /dev/null || exit 1", "interval"=>"1s", "max_attempts"=>3, "port"=>3000, "path"=>"/up", "cord"=>"/tmp/kamal-cord", "log_lines"=>50 }, config[:healthcheck])
|
assert_equal({ "cmd"=>"wget -qO- http://localhost > /dev/null || exit 1", "interval"=>"1s", "max_attempts"=>3, "port"=>3000, "path"=>"/up", "cord"=>"/tmp/kamal-cord", "log_lines"=>50 }, config[:healthcheck])
|
||||||
end
|
end
|
||||||
|
|
||||||
test "aliases" do
|
|
||||||
@app = "app_with_roles"
|
|
||||||
|
|
||||||
kamal :envify
|
|
||||||
kamal :deploy
|
|
||||||
|
|
||||||
output = kamal :whome, capture: true
|
|
||||||
assert_equal Kamal::VERSION, output
|
|
||||||
|
|
||||||
output = kamal :worker_hostname, capture: true
|
|
||||||
assert_match /App Host: vm3\nvm3-[0-9a-f]{12}$/, output
|
|
||||||
|
|
||||||
output = kamal :uname, "-o", capture: true
|
|
||||||
assert_match "App Host: vm1\nGNU/Linux", output
|
|
||||||
end
|
|
||||||
|
|
||||||
test "setup and remove" do
|
test "setup and remove" do
|
||||||
# Check remove completes when nothing has been setup yet
|
# Check remove completes when nothing has been setup yet
|
||||||
kamal :remove, "-y"
|
kamal :remove, "-y"
|
||||||
assert_no_images_or_containers
|
assert_no_images_or_containers
|
||||||
|
|
||||||
kamal :envify
|
kamal :env, :push
|
||||||
kamal :setup
|
kamal :setup
|
||||||
assert_images_and_containers
|
assert_images_and_containers
|
||||||
|
|
||||||
@@ -113,7 +97,7 @@ class MainTest < IntegrationTest
|
|||||||
|
|
||||||
private
|
private
|
||||||
def assert_local_env_file(contents)
|
def assert_local_env_file(contents)
|
||||||
assert_equal contents, deployer_exec("cat .env", capture: true)
|
assert_equal contents, deployer_exec("cat .kamal/.env", capture: true)
|
||||||
end
|
end
|
||||||
|
|
||||||
def assert_envs(version:)
|
def assert_envs(version:)
|
||||||
@@ -143,7 +127,7 @@ class MainTest < IntegrationTest
|
|||||||
end
|
end
|
||||||
|
|
||||||
def remove_local_env_file
|
def remove_local_env_file
|
||||||
deployer_exec("rm .env")
|
deployer_exec("rm .kamal/.env")
|
||||||
end
|
end
|
||||||
|
|
||||||
def assert_remote_env_file(contents, vm:)
|
def assert_remote_env_file(contents, vm:)
|
||||||
|
|||||||
@@ -2,8 +2,6 @@ require_relative "integration_test"
|
|||||||
|
|
||||||
class TraefikTest < IntegrationTest
|
class TraefikTest < IntegrationTest
|
||||||
test "boot, reboot, stop, start, restart, logs, remove" do
|
test "boot, reboot, stop, start, restart, logs, remove" do
|
||||||
kamal :envify
|
|
||||||
|
|
||||||
kamal :traefik, :boot
|
kamal :traefik, :boot
|
||||||
assert_traefik_running
|
assert_traefik_running
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,10 @@ end
|
|||||||
class ActiveSupport::TestCase
|
class ActiveSupport::TestCase
|
||||||
include ActiveSupport::Testing::Stream
|
include ActiveSupport::Testing::Stream
|
||||||
|
|
||||||
|
setup do
|
||||||
|
Kamal::Cli::Base.ran_pre_init_hook = false
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
def stdouted
|
def stdouted
|
||||||
capture(:stdout) { yield }.strip
|
capture(:stdout) { yield }.strip
|
||||||
|
|||||||
Reference in New Issue
Block a user