Ensure envify templates aren't polluted by existing env

Setting `GITHUB_TOKEN` as in the docs results in reusing the existing
`GITHUB_TOKEN` since `gh` returns that env var if it's set:
```bash
GITHUB_TOKEN=junk gh config get -h github.com oauth_token
junk
```

Using the original env ensures that the templates will be evaluated the
same way regardless of whether envify had been previously invoked.
This commit is contained in:
Jeremy Daer
2024-06-25 10:48:31 -07:00
parent 9a1379be6c
commit 13409ada5a
3 changed files with 48 additions and 12 deletions

View File

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

View File

@@ -191,10 +191,12 @@ class Kamal::Cli::Main < Kamal::Cli::Base
end
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]
reload_envs
reload_env
invoke "kamal:cli:env:push", options
end
else

View File

@@ -1,6 +1,9 @@
require_relative "cli_test_case"
class CliMainTest < CliTestCase
setup { @original_env = ENV.to_h.dup }
teardown { ENV.clear; ENV.update @original_env }
test "setup" do
invoke_options = { "config_file" => "test/fixtures/deploy_simple.yml", "version" => "999", "skip_hooks" => false }
@@ -434,7 +437,7 @@ class CliMainTest < CliTestCase
end
test "envify" do
with_test_dot_env_erb(contents: "HELLO=<%= 'world' %>") do
with_test_dotenv(".env.erb": "HELLO=<%= 'world' %>") do
run_command("envify")
assert_equal("HELLO=world", File.read(".env"))
end
@@ -448,14 +451,14 @@ class CliMainTest < CliTestCase
<% end -%>
EOF
with_test_dot_env_erb(contents: file) do
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_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")
assert_equal "HELLO=world", File.read(".env.world")
end
@@ -470,6 +473,13 @@ class CliMainTest < CliTestCase
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
run_command("remove", "-y", config_file: "deploy_with_accessories").tap do |output|
assert_match /docker container stop traefik/, output
@@ -522,14 +532,16 @@ class CliMainTest < CliTestCase
stdouted { Kamal::Cli::Main.start([ *command, "-c", "test/fixtures/#{config_file}.yml" ]) }
end
def with_test_dot_env_erb(contents:, file: ".env.erb")
def with_test_dotenv(**files)
Dir.mktmpdir do |dir|
fixtures_dup = File.join(dir, "test")
FileUtils.mkdir_p(fixtures_dup)
FileUtils.cp_r("test/fixtures/", fixtures_dup)
Dir.chdir(dir) do
File.write(file, contents)
files.each do |filename, contents|
File.binwrite(filename.to_s, contents)
end
yield
end
end