From 9a81dfd35bf24ec0a60ff51ecb147b339385dfe7 Mon Sep 17 00:00:00 2001 From: Tristan Sloughter Date: Sat, 23 May 2020 11:17:53 -0600 Subject: [PATCH 1/2] add --all option for release building in parallel --- rebar.lock | 2 +- src/rebar_relx.erl | 98 +++++++++++++++++++++++++++++++++++++--------- 2 files changed, 81 insertions(+), 19 deletions(-) diff --git a/rebar.lock b/rebar.lock index 56ad0b0f..2359669d 100644 --- a/rebar.lock +++ b/rebar.lock @@ -10,7 +10,7 @@ {<<"providers">>,{pkg,<<"providers">>,<<"1.8.1">>},0}, {<<"relx">>, {git,"https://github.com/erlware/relx.git", - {ref,"aa6c81d265986f223fa347cacf3b9691e7b56f2f"}}, + {ref,"0182d6aeca73c99c4fffaf7a94c8d21b2be3aa74"}}, 0}, {<<"ssl_verify_fun">>,{pkg,<<"ssl_verify_fun">>,<<"1.1.5">>},0}]}. [ diff --git a/src/rebar_relx.erl b/src/rebar_relx.erl index ae29c0d1..0dc93b03 100644 --- a/src/rebar_relx.erl +++ b/src/rebar_relx.erl @@ -21,18 +21,6 @@ -spec do(atom(), rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}. do(Provider, State) -> {Opts, _} = rebar_state:command_parsed_args(State), - Release = case proplists:get_value(relname, Opts, undefined) of - undefined -> - undefined; - R -> - case proplists:get_value(relvsn, Opts, undefined) of - undefined -> - list_to_atom(R); - RelVsn -> - {list_to_atom(R), RelVsn} - end - end, - %% TODO: read in ./relx.config if it exists or --config value RelxConfig = rebar_state:get(State, relx, []), @@ -57,15 +45,16 @@ do(Provider, State) -> Cwd = rebar_state:dir(State), rebar_hooks:run_project_and_app_hooks(Cwd, pre, Provider, Providers, State), + Releases = releases_to_build(Provider, Opts, RelxState), + case Provider of - release -> - relx:build_release(Release, all_apps(State), RelxState); - tar -> - relx:build_tar(Release, all_apps(State), RelxState); relup -> ToVsn = proplists:get_value(relvsn, Opts, undefined), UpFromVsn = proplists:get_value(upfrom, Opts, undefined), - relx:build_relup(Release, ToVsn, UpFromVsn, RelxState) + %% hd/1 can't fail because --all is not a valid option to relup + relx:build_relup(hd(Releases), ToVsn, UpFromVsn, RelxState); + _ -> + parallel_run(Provider, Releases, all_apps(State), RelxState) end, rebar_hooks:run_project_and_app_hooks(Cwd, post, Provider, Providers, State), @@ -73,9 +62,80 @@ do(Provider, State) -> {ok, State}. -spec format_error(any()) -> iolist(). +format_error(all_relup) -> + "Option --all can not be applied to `relup` command"; format_error(Error) -> io_lib:format("~p", [Error]). +%% + +parallel_run(release, [Release], AllApps, RelxState) -> + relx:build_release(Release, AllApps, RelxState); +parallel_run(tar, [Release], AllApps, RelxState) -> + relx:build_tar(Release, AllApps, RelxState); +parallel_run(Provider, Releases, AllApps, RelxState) -> + rebar_parallel:queue(Releases, fun rel_worker/2, [Provider, AllApps, RelxState], fun rel_handler/2, []). + +rel_worker(Release, [Provider, Apps, RelxState]) -> + try + case Provider of + release -> + relx:build_release(Release, Apps, RelxState); + tar -> + relx:build_tar(Release, Apps, RelxState) + end + catch + error:Error -> + {Release, Error} + end. + +rel_handler({{Name, Vsn}, {error, {Module, Reason}}}, _Args) -> + ?ERROR("Error building release ~ts-~ts:~n~ts~ts", [Name, Vsn, rebar_utils:indent(1), + Module:format_error(Reason)]), + ok; +rel_handler(_, _Args) -> + ok. + +releases_to_build(Provider, Opts, RelxState)-> + case proplists:get_value(all, Opts, undefined) of + undefined -> + case proplists:get_value(relname, Opts, undefined) of + undefined -> + [undefined]; + R -> + case proplists:get_value(relvsn, Opts, undefined) of + undefined -> + [list_to_atom(R)]; + RelVsn -> + [{list_to_atom(R), RelVsn}] + end + end; + true when Provider =:= relup -> + erlang:error(?PRV_ERROR(all_relup)); + true -> + highest_unique_releases(rlx_state:configured_releases(RelxState)) + end. + +%% takes a map of relx configured releases and returns a list of the highest +%% version for each unique release name +-spec highest_unique_releases(rlx_state:releases()) -> [{atom(), string() | undefined}]. +highest_unique_releases(Releases) -> + Unique = maps:fold(fun({Name, Vsn}, _, Acc) -> + update_map_if_higher(Name, Vsn, Acc) + end, #{}, Releases), + maps:to_list(Unique). + +update_map_if_higher(Name, Vsn, Acc) -> + maps:update_with(Name, fun(Vsn1) -> + case rlx_util:parsed_vsn_lte(rlx_util:parse_vsn(Vsn1), + rlx_util:parse_vsn(Vsn)) of + true -> + Vsn; + false -> + Vsn1 + end + end, Vsn, Acc). + %% Don't override output_dir if the user passed one on the command line output_dir(DefaultOutputDir, Options) -> {output_dir, proplists:get_value(output_dir, Options, DefaultOutputDir)}. @@ -104,7 +164,9 @@ all_apps(State) -> -spec opt_spec_list() -> [getopt:option_spec()]. opt_spec_list() -> - [{relname, $n, "relname", string, + [{all, undefined, "all", boolean, + "If true runs the command against all configured releases"}, + {relname, $n, "relname", string, "Specify the name for the release that will be generated"}, {relvsn, $v, "relvsn", string, "Specify the version for the release"}, {upfrom, $u, "upfrom", string, From d99f2d84424e70d267b1b2ff81000bc1b9b6a561 Mon Sep 17 00:00:00 2001 From: Tristan Sloughter Date: Mon, 25 May 2020 15:03:48 -0600 Subject: [PATCH 2/2] switch relx to master branch which is now the 4.x branch --- rebar.config | 2 +- rebar.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rebar.config b/rebar.config index a42a398f..fac09e63 100644 --- a/rebar.config +++ b/rebar.config @@ -9,7 +9,7 @@ {getopt, "1.0.1"}, {bbmustache, "1.8.0"}, %% {relx, "3.33.0"}, - {relx, {git, "https://github.com/erlware/relx.git", {branch, "4.0.0"}}}, + {relx, {git, "https://github.com/erlware/relx.git", {branch, "master"}}}, {cf, "0.2.2"}, {cth_readable, "1.4.8"}, {eunit_formatters, "0.5.0"}]}. diff --git a/rebar.lock b/rebar.lock index 2359669d..fd008d21 100644 --- a/rebar.lock +++ b/rebar.lock @@ -10,7 +10,7 @@ {<<"providers">>,{pkg,<<"providers">>,<<"1.8.1">>},0}, {<<"relx">>, {git,"https://github.com/erlware/relx.git", - {ref,"0182d6aeca73c99c4fffaf7a94c8d21b2be3aa74"}}, + {ref,"0d9d6255a53af63927f826c0b827b3741a8ed458"}}, 0}, {<<"ssl_verify_fun">>,{pkg,<<"ssl_verify_fun">>,<<"1.1.5">>},0}]}. [