Skip to content

[Feature] Preserve kamal default options #1427

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions lib/kamal/cli/base.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
require "thor"
require "kamal/sshkit_with_ext"
require "active_support/core_ext/hash/keys"

module Kamal::Cli
class Base < Thor
Expand All @@ -17,7 +18,7 @@ def self.dynamic_command_class() Kamal::Cli::Alias::Command end
class_option :hosts, aliases: "-h", desc: "Run commands on these hosts instead of all (separate by comma, supports wildcards with *)"
class_option :roles, aliases: "-r", desc: "Run commands on these roles instead of all (separate by comma, supports wildcards with *)"

class_option :config_file, aliases: "-c", default: "config/deploy.yml", desc: "Path to config file"
class_option :config_file, aliases: "-c", desc: "Path to config file. Default set in .kamal/options.yml. Fallback to config/deploy.yml"
class_option :destination, aliases: "-d", desc: "Specify destination to be used for config file (staging -> deploy.staging.yml)"

class_option :skip_hooks, aliases: "-H", type: :boolean, default: false, desc: "Don't run hooks"
Expand Down Expand Up @@ -51,7 +52,7 @@ def initialize_commander
end

commander.configure \
config_file: Pathname.new(File.expand_path(options[:config_file])),
config_file: Pathname.new(File.expand_path(option_with_default_from_file(:config_file) || "config/deploy.yml")),
destination: options[:destination],
version: options[:version]

Expand All @@ -61,6 +62,17 @@ def initialize_commander
end
end

def option_with_default_from_file(key)
options[key] || options_file_defaults[key]
end

def options_file_defaults
@options_file_defaults ||= begin
options_file = Pathname.new(File.expand_path(".kamal/options.yml"))
options_file.exist? ? YAML.load(File.read(options_file)).symbolize_keys : {}
end
end

def print_runtime
started_at = Time.now
yield
Expand Down
20 changes: 15 additions & 5 deletions lib/kamal/cli/main.rb
Original file line number Diff line number Diff line change
Expand Up @@ -136,17 +136,27 @@ def docs(section = nil)
puts "No documentation found for #{section}"
end

desc "init", "Create config stub in config/deploy.yml and secrets stub in .kamal"
desc "init", "Create config stub (default config/deploy.yml) and secrets stub in .kamal"
option :bundle, type: :boolean, default: false, desc: "Add Kamal to the Gemfile and create a bin/kamal binstub"
def init
require "fileutils"

if (deploy_file = Pathname.new(File.expand_path("config/deploy.yml"))).exist?
puts "Config file already exists in config/deploy.yml (remove first to create a new one)"
config_file = options[:config_file] || "config/deploy.yml"
if (deploy_file = Pathname.new(File.expand_path(config_file))).exist?
puts "Config file #{config_file} already exists (remove first to create a new one)"
else
FileUtils.mkdir_p deploy_file.dirname
FileUtils.cp_r Pathname.new(File.expand_path("templates/deploy.yml", __dir__)), deploy_file
puts "Created configuration file in config/deploy.yml"
FileUtils.cp Pathname.new(File.expand_path("templates/deploy.yml", __dir__)), deploy_file
puts "Created config file #{config_file}"
end

unless (options_file = Pathname.new(File.expand_path(".kamal/options.yml"))).exist?
FileUtils.mkdir_p options_file.dirname
FileUtils.cp Pathname.new(File.expand_path("templates/options.yml", __dir__)), options_file
File.open(options_file, "a") do |file|
file.write("config_file: \"#{config_file}\"\n")
end
puts "Created .kamal/options.yml file"
end

unless (secrets_file = Pathname.new(File.expand_path(".kamal/secrets"))).exist?
Expand Down
1 change: 1 addition & 0 deletions lib/kamal/cli/templates/options.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Default options to apply on execution of kamal commands.
90 changes: 66 additions & 24 deletions test/cli/main_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -348,33 +348,72 @@ class CliMainTest < CliTestCase
end
end

test "config and alias commands with defaults from .kamal/options.yml" do
Dir.mktmpdir do |tmpdir|
relative_deploy_file_path = ".kamal/deploy.yml"

Dir.chdir(tmpdir) do
run_init("-c", relative_deploy_file_path)
end

config_file = File.join(tmpdir, relative_deploy_file_path)
FileUtils.cp "test/fixtures/deploy_with_aliases.yml", config_file

Dir.chdir(tmpdir) do
run_main_command("config").tap do |output|
config = YAML.load(output)
assert_equal [ "console", "web", "workers" ], config[:roles]
end

run_main_command("console", "-r", "workers").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
end
end

test "init" do
in_dummy_git_repo do
run_command("init").tap do |output|
assert_match "Created configuration file in config/deploy.yml", output
run_init.tap do |output|
assert_match "Created config file config/deploy.yml", output
assert_match "Created .kamal/options.yml file", output
assert_match "Created .kamal/secrets file", output
end

assert_file "config/deploy.yml", "service: my-app"
assert_file ".kamal/options.yml", "config_file: \"config/deploy.yml\""
assert_file ".kamal/secrets", "KAMAL_REGISTRY_PASSWORD=$KAMAL_REGISTRY_PASSWORD"
end
end

test "init with config file option" do
in_dummy_git_repo do
run_init("-c", ".kamal/deploy.yml").tap do |output|
assert_match "Created config file .kamal/deploy.yml", output
assert_match "Created .kamal/options.yml file", output
end

assert_file ".kamal/deploy.yml", "service: my-app"
assert_file ".kamal/options.yml", "config_file: \".kamal/deploy.yml\""
end
end

test "init with existing config" do
in_dummy_git_repo do
run_command("init")
run_init

run_command("init").tap do |output|
assert_match /Config file already exists in config\/deploy.yml \(remove first to create a new one\)/, output
run_init.tap do |output|
assert_match /Config file config\/deploy.yml already exists \(remove first to create a new one\)/, output
assert_no_match /Added .kamal\/secrets/, output
end
end
end

test "init with bundle option" do
in_dummy_git_repo do
run_command("init", "--bundle").tap do |output|
assert_match "Created configuration file in config/deploy.yml", output
run_init("--bundle").tap do |output|
assert_match "Created config file config/deploy.yml", output
assert_match "Created .kamal/secrets file", output
assert_match /Adding Kamal to Gemfile and bundle/, output
assert_match /bundle add kamal/, output
Expand All @@ -385,15 +424,14 @@ class CliMainTest < CliTestCase
end

test "init with bundle option and existing binstub" do
Pathname.any_instance.expects(:exist?).returns(true).times(4)
Pathname.any_instance.stubs(:mkpath)
FileUtils.stubs(:mkdir_p)
FileUtils.stubs(:cp_r)
FileUtils.stubs(:cp)
in_dummy_git_repo do
binstub = Pathname.new(File.expand_path("bin/kamal"))
FileUtils.mkdir_p binstub.dirname
FileUtils.touch binstub

run_command("init", "--bundle").tap do |output|
assert_match /Config file already exists in config\/deploy.yml \(remove first to create a new one\)/, output
assert_match /Binstub already exists in bin\/kamal \(remove first to create a new one\)/, output
run_init("--bundle").tap do |output|
assert_match /Binstub already exists in bin\/kamal \(remove first to create a new one\)/, output
end
end
end

Expand Down Expand Up @@ -484,20 +522,16 @@ class CliMainTest < CliTestCase

test "switch config file with an alias" do
with_config_files do
with_argv([ "other_config" ]) do
stdouted { Kamal::Cli::Main.start }.tap do |output|
assert_match ":service_with_version: app2-999", output
end
run_main_command("other_config").tap do |output|
assert_match ":service_with_version: app2-999", output
end
end
end

test "switch destination with an alias" do
with_config_files do
with_argv([ "other_destination_config" ]) do
stdouted { Kamal::Cli::Main.start }.tap do |output|
assert_match ":service_with_version: app3-999", output
end
run_main_command("other_destination_config").tap do |output|
assert_match ":service_with_version: app3-999", output
end
end
end
Expand Down Expand Up @@ -539,7 +573,15 @@ class CliMainTest < CliTestCase

private
def run_command(*command, config_file: "deploy_simple")
with_argv([ *command, "-c", "test/fixtures/#{config_file}.yml" ]) do
run_main_command(*command, "-c", "test/fixtures/#{config_file}.yml")
end

def run_init(*options)
run_main_command("init", *options)
end

def run_main_command(*command)
with_argv([ *command ]) do
stdouted { Kamal::Cli::Main.start }
end
end
Expand Down
Loading