Skip to content

Commit d9823e0

Browse files
jmschneiderclaude
andcommitted
config_generator: deep-merge sibling deploy.yml into destination file
When the consumer points base-deploy-file at a destination override (e.g. config/deploy.staging.yml) and the shared config (deploy.yml) defines `env: { secret: [RAILS_MASTER_KEY, ...] }` while the destination defines `env: { clear: { RAILS_ENV: staging } }`, the previous shallow merge replaced the entire env block with the destination's version — dropping env.secret entirely. That left the per-PR deploy file with no secrets list, so Kamal didn't surface RAILS_MASTER_KEY into .kamal/apps/.../env/roles/web.env, and Rails booted with no secret_key_base. Deep-merge instead: hashes recurse, arrays/scalars override wins. Matches Kamal's own merge behavior at deploy time. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent a05d0fc commit d9823e0

1 file changed

Lines changed: 15 additions & 2 deletions

File tree

lib/kamal_previews/config_generator.rb

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -239,14 +239,27 @@ def load_base_yaml
239239
shared = parse_yaml(sibling)
240240
if shared.is_a?(Hash)
241241
# Destination values win where they're set; the shared file fills
242-
# in everything else.
243-
data = shared.merge(data) { |_key, _shared_v, dest_v| dest_v }
242+
# in everything else. Deep-merge so `env: { clear: {...}, secret: [...] }`
243+
# in deploy.yml and `env: { clear: { RAILS_ENV: staging } }` in the
244+
# destination file combine instead of clobbering — Kamal does this
245+
# at deploy time, and our generator must match.
246+
data = deep_merge(shared, data)
244247
end
245248
end
246249

247250
data
248251
end
249252

253+
def deep_merge(base, override)
254+
base.merge(override) do |_key, base_v, over_v|
255+
if base_v.is_a?(Hash) && over_v.is_a?(Hash)
256+
deep_merge(base_v, over_v)
257+
else
258+
over_v
259+
end
260+
end
261+
end
262+
250263
def parse_yaml(path)
251264
raw = File.read(path)
252265
YAML.safe_load(raw, permitted_classes: [Date, Time], aliases: true)

0 commit comments

Comments
 (0)