From 2ff46a6dbbe7546f830fd6132411b5088f911dd9 Mon Sep 17 00:00:00 2001 From: Thales Macedo Garitezi Date: Tue, 21 Dec 2021 17:28:39 -0300 Subject: [PATCH] chore(mix): create a few more required files during release Since Mix does not support hot upgrades out of the box, it does not create a `RELEASES` file by default. Here, we introduce functionality similar to what `relx` does in order for that file to be generated. https://github.com/erlware/relx/blob/fdc8d7237ef757162cbf198a56c761065e54b49e/src/rlx_assemble.erl#L928-L948 The `RELEASES` file, in its turn, is required for `nodetool` to work properly, and `nodetool` is required for us to generate several required config files using `hocon`. Since the `start{_clean}.boot` file used by the files generated by Elixir must be explicitly defined in the `RELEASE_LIB` `boot_var`, we apply a small patch in the existing `nodetool` in order to inject that required parameter when calling the escript. --- mix.exs | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 76 insertions(+), 4 deletions(-) diff --git a/mix.exs b/mix.exs index 29278cf40..7525df5a1 100644 --- a/mix.exs +++ b/mix.exs @@ -118,17 +118,89 @@ defmodule EMQXUmbrella.MixProject do :emqx_prometheus, :emqx_plugins ], - steps: [:assemble, ©_files/1] + steps: [ + :assemble, + &create_RELEASES/1, + ©_files/1, + ©_nodetool/1, + ] ] ] end def copy_files(release) do + overwrite? = Keyword.get(release.options, :overwrite, false) + + bin = Path.join(release.path, "bin") etc = Path.join(release.path, "etc") - # FIXME: Remove?? - File.mkdir_p!(etc) - File.cp!("apps/emqx_authz/etc/acl.conf", Path.join(etc, "acl.conf")) + Mix.Generator.create_directory(bin) + Mix.Generator.create_directory(etc) + + Mix.Generator.copy_file( + "apps/emqx_authz/etc/acl.conf", + Path.join(etc, "acl.conf"), + force: overwrite? + ) + + # FIXME: check if cloud/edge!! + Mix.Generator.copy_file( + "apps/emqx/etc/emqx_cloud/vm.args", + Path.join(etc, "vm.args"), + force: overwrite? + ) + Mix.Generator.copy_file( + "apps/emqx/etc/emqx_cloud/vm.args", + Path.join(release.version_path, "vm.args"), + force: overwrite? + ) + + + release + end + + # needed by nodetool and by release_handler + def create_RELEASES(release) do + apps = Enum.map(release.applications, fn {app_name, app_props} -> + app_vsn = Keyword.fetch!(app_props, :vsn) + app_path = + "./lib" + |> Path.join("#{app_name}-#{app_vsn}") + |> to_charlist() + {app_name, app_vsn, app_path} + end) + release_entry = + [{ + :release, + to_charlist(release.name), + to_charlist(release.version), + release.erts_version, + apps, + :permanent + }] + + release.path + |> Path.join("releases") + |> Path.join("RELEASES") + |> File.open!([:write, :utf8], fn handle -> + IO.puts(handle, "%% coding: utf-8") + :io.format(handle, '~tp.~n', [release_entry]) + end) + + release + end + + def copy_nodetool(release) do + [shebang, rest] = + "bin/nodetool" + |> File.read!() + |> String.split("\n", parts: 2) + + path = Path.join([release.path, "bin", "nodetool"]) + # the elixir version of escript + start.boot required the boot_var + # RELEASE_LIB to be defined. + boot_var = "%%!-boot_var RELEASE_LIB $RUNNER_ROOT_DIR/lib" + File.write!(path, [shebang, "\n", boot_var, "\n", rest]) release end