Merge pull request #865 from basecamp/clean-envify-env

Ensure envify templates aren't polluted by existing env
This commit is contained in:
Donal McBreen
2024-07-15 13:41:03 +01:00
committed by GitHub
3 changed files with 48 additions and 12 deletions

View File

@@ -25,12 +25,17 @@ module Kamal::Cli
def initialize(*) def initialize(*)
super super
@original_env = ENV.to_h.dup @original_env = ENV.to_h.dup
load_envs load_env
initialize_commander(options_with_subcommand_class_options) initialize_commander(options_with_subcommand_class_options)
end end
private private
def load_envs def reload_env
reset_env
load_env
end
def load_env
if destination = options[:destination] if destination = options[:destination]
Dotenv.load(".env.#{destination}", ".env") Dotenv.load(".env.#{destination}", ".env")
else else
@@ -38,10 +43,27 @@ module Kamal::Cli
end end
end end
def reload_envs def reset_env
replace_env @original_env
end
def replace_env(env)
ENV.clear ENV.clear
ENV.update(@original_env) ENV.update(env)
load_envs 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 end
def options_with_subcommand_class_options def options_with_subcommand_class_options

View File

@@ -191,10 +191,12 @@ class Kamal::Cli::Main < Kamal::Cli::Base
end end
if Pathname.new(File.expand_path(env_template_path)).exist? if Pathname.new(File.expand_path(env_template_path)).exist?
File.write(env_path, ERB.new(File.read(env_template_path), trim_mode: "-").result, perm: 0600) # 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] unless options[:skip_push]
reload_envs reload_env
invoke "kamal:cli:env:push", options invoke "kamal:cli:env:push", options
end end
else else

View File

@@ -1,6 +1,9 @@
require_relative "cli_test_case" require_relative "cli_test_case"
class CliMainTest < CliTestCase class CliMainTest < CliTestCase
setup { @original_env = ENV.to_h.dup }
teardown { ENV.clear; ENV.update @original_env }
test "setup" do test "setup" do
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 }
@@ -444,7 +447,7 @@ class CliMainTest < CliTestCase
end end
test "envify" do test "envify" do
with_test_dot_env_erb(contents: "HELLO=<%= 'world' %>") do with_test_dotenv(".env.erb": "HELLO=<%= 'world' %>") do
run_command("envify") run_command("envify")
assert_equal("HELLO=world", File.read(".env")) assert_equal("HELLO=world", File.read(".env"))
end end
@@ -458,14 +461,14 @@ class CliMainTest < CliTestCase
<% end -%> <% end -%>
EOF EOF
with_test_dot_env_erb(contents: file) do with_test_dotenv(".env.erb": file) do
run_command("envify") run_command("envify")
assert_equal("HELLO=world\nKEY=value\n", File.read(".env")) assert_equal("HELLO=world\nKEY=value\n", File.read(".env"))
end end
end end
test "envify with destination" do test "envify with destination" do
with_test_dot_env_erb(contents: "HELLO=<%= 'world' %>", file: ".env.world.erb") do with_test_dotenv(".env.world.erb": "HELLO=<%= 'world' %>") do
run_command("envify", "-d", "world", config_file: "deploy_for_dest") run_command("envify", "-d", "world", config_file: "deploy_for_dest")
assert_equal "HELLO=world", File.read(".env.world") assert_equal "HELLO=world", File.read(".env.world")
end end
@@ -480,6 +483,13 @@ class CliMainTest < CliTestCase
run_command("envify", "--skip-push") run_command("envify", "--skip-push")
end 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
@@ -532,14 +542,16 @@ class CliMainTest < CliTestCase
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
def with_test_dot_env_erb(contents:, file: ".env.erb") def with_test_dotenv(**files)
Dir.mktmpdir do |dir| Dir.mktmpdir do |dir|
fixtures_dup = File.join(dir, "test") fixtures_dup = File.join(dir, "test")
FileUtils.mkdir_p(fixtures_dup) FileUtils.mkdir_p(fixtures_dup)
FileUtils.cp_r("test/fixtures/", fixtures_dup) FileUtils.cp_r("test/fixtures/", fixtures_dup)
Dir.chdir(dir) do Dir.chdir(dir) do
File.write(file, contents) files.each do |filename, contents|
File.binwrite(filename.to_s, contents)
end
yield yield
end end
end end