From 0098f2124377220c99e2d64a894a4ff4edc8489b Mon Sep 17 00:00:00 2001 From: Deniz Adrian Date: Sat, 25 Jan 2020 15:43:44 +0100 Subject: [PATCH] Ensure ERTS is not copied into release (#9752) The default behaviour when starting a new mix project is to `include_erts: true`. If at some point you choose to `include_erts: false`, but have the ERTS artifact hanging around from previous builds, it gets included in future builds, therefore rendering `include_erts: false` broken when running on systems that have built with `include_erts: true` for the same environment. `make_tar/1` currently always tries to include the ERTS artifact into the archive, regardless of our `include_erts` configuration. this fails in 1.9.4 if no previous artifact is present, and seems to be worked around in the current implementation by simply ignoring source directories that don't exist. This adds a regression test for the behaviour by "simulating" an ERTS leftover from a previous build. This also adds logic to not try to include ERTS into archives in the first place when our release is configured with `include_erts: false`. --- lib/mix/lib/mix/tasks/release.ex | 10 +++++++-- lib/mix/test/mix/tasks/release_test.exs | 28 +++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/lib/mix/lib/mix/tasks/release.ex b/lib/mix/lib/mix/tasks/release.ex index 043e1a1b17..ade494e5a7 100644 --- a/lib/mix/lib/mix/tasks/release.ex +++ b/lib/mix/lib/mix/tasks/release.ex @@ -1075,14 +1075,20 @@ defmodule Mix.Tasks.Release do [Path.join("lib", "#{name}-#{vsn}") | acc] end) + erts_dir = + case release.erts_source do + nil -> [] + _ -> ["erts-#{release.erts_version}"] + end + release_files = for basename <- File.ls!(Path.join(release.path, "releases")), not File.dir?(Path.join([release.path, "releases", basename])), do: Path.join("releases", basename) dirs = - ["bin", Path.join("releases", release.version), "erts-#{release.erts_version}"] ++ - lib_dirs ++ release_files + ["bin", Path.join("releases", release.version)] ++ + erts_dir ++ lib_dirs ++ release_files files = dirs diff --git a/lib/mix/test/mix/tasks/release_test.exs b/lib/mix/test/mix/tasks/release_test.exs index 712ed97ada..a5abc19e5c 100644 --- a/lib/mix/test/mix/tasks/release_test.exs +++ b/lib/mix/test/mix/tasks/release_test.exs @@ -208,6 +208,34 @@ defmodule Mix.Tasks.ReleaseTest do end) end) end + + test "without ERTS when a previous build included ERTS" do + in_fixture("release_test", fn -> + config = [releases: [demo: [include_erts: false, steps: [:assemble, :tar]]]] + + Mix.Project.in_project(:release_test, ".", config, fn _ -> + root = Path.absname("_build/#{Mix.env()}/rel/demo") + + erts_dir_from_previous_build = + Path.absname("_build/#{Mix.env()}/rel/demo/erts-#{@erts_version}") + + File.mkdir_p!(erts_dir_from_previous_build) + + Mix.Task.run("release") + tar_path = Path.expand(Path.join([root, "..", "..", "demo-0.1.0.tar.gz"])) + message = "* building #{tar_path}" + assert_received {:mix_shell, :info, [^message]} + assert File.exists?(tar_path) + + {:ok, files} = String.to_charlist(tar_path) |> :erl_tar.table([:compressed]) + files = Enum.map(files, &to_string/1) + + assert "bin/demo" in files + refute Enum.any?(files, &(&1 =~ "erts")) + refute Enum.any?(files, &(&1 =~ "stdlib")) + end) + end) + end end test "assembles a bootable release with ERTS" do