Skip to content

Commit cec1a71

Browse files
committed
Make config/runtime.exs deep merge, closes #10365
1 parent 53d1b98 commit cec1a71

File tree

7 files changed

+40
-25
lines changed

7 files changed

+40
-25
lines changed

lib/mix/lib/mix/cli.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ defmodule Mix.CLI do
146146
path = Path.join(Mix.Utils.mix_config(), "config.exs")
147147

148148
if File.regular?(path) do
149-
Mix.Tasks.Loadconfig.load_imports(path)
149+
Mix.Tasks.Loadconfig.load_compile(path)
150150
end
151151
end
152152

lib/mix/lib/mix/tasks/app.config.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ defmodule Mix.Tasks.App.Config do
3434
runtime = config[:config_path] |> Path.dirname() |> Path.join("runtime.exs")
3535

3636
if File.exists?(runtime) do
37-
Mix.Tasks.Loadconfig.load_file(runtime)
37+
Mix.Tasks.Loadconfig.load_runtime(runtime)
3838
end
3939

4040
if opts[:preload_modules] do

lib/mix/lib/mix/tasks/loadconfig.ex

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,34 +29,42 @@ defmodule Mix.Tasks.Loadconfig do
2929

3030
case args do
3131
[] -> load_default()
32-
[file] -> load_imports(file)
32+
[file] -> load_compile(file)
3333
end
3434
end
3535

3636
defp load_default do
3737
config = Mix.Project.config()
3838

3939
if File.regular?(config[:config_path]) or config[:config_path] != "config/config.exs" do
40-
load_imports(config[:config_path])
40+
load_compile(config[:config_path])
4141
else
4242
[]
4343
end
4444
end
4545

4646
@doc false
47-
def load_imports(file) do
47+
# Loads compile-time configuration, they support imports, and are not deep merged.
48+
def load_compile(file) do
4849
{config, files} = Config.Reader.read_imports!(file, env: Mix.env(), target: Mix.target())
4950
Mix.ProjectStack.loaded_config(persist_apps(config, file), files)
5051
config
5152
end
5253

5354
@doc false
54-
def load_file(file) do
55+
# Loads runtime configuration, they do not support imports, and are deep merged.
56+
def load_runtime(file) do
5557
config = Config.Reader.read!(file, env: Mix.env(), target: Mix.target(), imports: :disabled)
56-
Mix.ProjectStack.loaded_config(persist_apps(config, file), [])
58+
Mix.ProjectStack.loaded_config(persist_apps(hydrate_apps(config), file), [])
5759
config
5860
end
5961

62+
defp hydrate_apps(config) do
63+
for {app, pairs} <- config do
64+
hd(Config.Reader.merge([{app, Application.get_all_env(app)}], [{app, pairs}]))
65+
end
66+
end
67+
6068
defp persist_apps(config, file) do
6169
Application.put_all_env(config, persistent: true)
6270
apps = Keyword.keys(config)

lib/mix/lib/mix/tasks/run.ex

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,13 @@ defmodule Mix.Tasks.Run do
154154

155155
defp process_config(opts) do
156156
for {:config, value} <- opts do
157-
Mix.Tasks.Loadconfig.load_imports(value)
157+
# TODO: Remove on v2.0.
158+
IO.warn(
159+
"the --config flag is deprecated. If you need to handle multiple configurations, " <>
160+
"it is preferable to dynamically import them in your config files"
161+
)
162+
163+
Mix.Tasks.Loadconfig.load_compile(value)
158164
end
159165

160166
:ok

lib/mix/test/mix/tasks/app.config_test.exs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,13 @@ defmodule Mix.Tasks.App.ConfigTest do
1717
File.write!("config/config.exs", """
1818
import Config
1919
config :sample, from_compile: :compile, from_runtime: :compile
20+
config :sample, :nested, from_compile: :compile, from_runtime: :compile
2021
""")
2122

2223
File.write!("config/runtime.exs", """
2324
import Config
2425
config :sample, from_runtime: :runtime
26+
config :sample, :nested, from_compile: :compile, from_runtime: :compile
2527
""")
2628

2729
Mix.Task.run("loadconfig")
@@ -30,10 +32,12 @@ defmodule Mix.Tasks.App.ConfigTest do
3032
assert Application.get_all_env(:sample) |> Enum.sort() == [
3133
from_compile: :compile,
3234
from_env: :env,
33-
from_runtime: :runtime
35+
from_runtime: :runtime,
36+
nested: [from_compile: :compile, from_runtime: :compile]
3437
]
3538
end)
3639
after
40+
Application.delete_env(:sample, :nested, persistent: true)
3741
Application.delete_env(:sample, :from_env, persistent: true)
3842
Application.delete_env(:sample, :from_compile, persistent: true)
3943
Application.delete_env(:sample, :from_runtime, persistent: true)

lib/mix/test/mix/tasks/release_test.exs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -359,14 +359,23 @@ defmodule Mix.Tasks.ReleaseTest do
359359
config = [releases: [runtime_config: [reboot_system_after_config: true]]]
360360

361361
Mix.Project.in_project(:release_test, ".", config, fn _ ->
362+
File.write!("config/config.exs", """
363+
#{File.read!("config/config.exs")}
364+
config :release_test, :runtime, keep: :static, override: :static
365+
""")
366+
362367
File.write!("config/runtime.exs", """
363368
import Config
364369
365370
if System.get_env("RELEASE_MODE") == nil do
366371
raise "file should not be loaded while assembling release"
367372
end
368373
369-
config :release_test, :runtime, {:was_set, config_env(), config_target()}
374+
config :release_test, :runtime,
375+
override: :runtime,
376+
config_env: config_env(),
377+
config_target: config_target()
378+
370379
config :release_test, :encoding, {:runtime, :time_μs, :"£", "£", '£'}
371380
""")
372381

@@ -401,7 +410,9 @@ defmodule Mix.Tasks.ReleaseTest do
401410
release_mode: "embedded",
402411
release_node: "runtime_config",
403412
release_vsn: "0.1.0",
404-
runtime_config: {:ok, {:was_set, :dev, :host}},
413+
runtime_config:
414+
{:ok,
415+
[keep: :static, override: :runtime, config_env: :dev, config_target: :host]},
405416
static_config: {:ok, :was_set},
406417
sys_config_env: sys_config_env,
407418
sys_config_init: sys_config_init

lib/mix/test/mix/tasks/run_test.exs

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,10 @@ Code.require_file("../../test_helper.exs", __DIR__)
33
defmodule Mix.Tasks.RunTest do
44
use MixTest.Case
55

6-
import ExUnit.CaptureIO
7-
86
setup do
97
Mix.Project.push(MixTest.Case.Sample)
108
end
119

12-
test "loads configuration", context do
13-
in_tmp(context.test, fn ->
14-
config = fixture_path("configs/good_config.exs")
15-
expr = "IO.puts(Application.get_env(:my_app, :key))"
16-
17-
assert capture_io(fn -> Mix.Task.run("run", ["--config", config, "--eval", expr]) end) ==
18-
"value\n"
19-
end)
20-
after
21-
Application.delete_env(:my_app, :key)
22-
end
23-
2410
test "run requires files before evaling commands", context do
2511
git_repo = fixture_path("git_repo/lib/git_repo.ex")
2612

0 commit comments

Comments
 (0)