feat(emqx_release): add new APIs to parse/compare release versions

This commit is contained in:
Zaiming (Stone) Shi 2023-05-31 00:13:15 +02:00
parent a3a6480f00
commit 39d6f612ca
3 changed files with 110 additions and 3 deletions

View File

@ -31,11 +31,11 @@
%% NOTE: ALso make sure to follow the instructions in end of
%% `apps/emqx/src/bpapi/README.md'
%% Community edition
%% Opensource edition
-define(EMQX_RELEASE_CE, "5.1.0-alpha.1").
%% Enterprise edition
-define(EMQX_RELEASE_EE, "5.1.0-alpha.1").
%% the HTTP API version
%% The HTTP API version
-define(EMQX_API_VERSION, "5.0").

View File

@ -21,7 +21,10 @@
edition_vsn_prefix/0,
edition_longstr/0,
description/0,
version/0
version/0,
version_with_prefix/0,
vsn_compare/1,
vsn_compare/2
]).
-include("emqx_release.hrl").
@ -68,6 +71,10 @@ edition_vsn_prefix() ->
edition_longstr() ->
maps:get(edition(), ?EMQX_REL_NAME).
%% @doc Return the release version with prefix.
version_with_prefix() ->
edition_vsn_prefix() ++ version().
%% @doc Return the release version.
version() ->
case lists:keyfind(emqx_vsn, 1, ?MODULE:module_info(compile)) of
@ -92,3 +99,47 @@ version() ->
build_vsn() ->
maps:get(edition(), ?EMQX_REL_VSNS).
%% @doc Compare the given version with the current running version,
%% return 'newer' 'older' or 'same'.
vsn_compare("v" ++ Vsn) ->
vsn_compare(?EMQX_RELEASE_CE, Vsn);
vsn_compare("e" ++ Vsn) ->
vsn_compare(?EMQX_RELEASE_EE, Vsn).
%% @priv Compare the second argument with the first argument, return
%% 'newer' 'older' or 'same' semver comparison result.
vsn_compare(Vsn1, Vsn2) ->
ParsedVsn1 = parse_vsn(Vsn1),
ParsedVsn2 = parse_vsn(Vsn2),
case ParsedVsn1 =:= ParsedVsn2 of
true ->
same;
false when ParsedVsn1 < ParsedVsn2 ->
newer;
false ->
older
end.
%% @priv Parse the version string to a tuple.
%% Return {{Major, Minor, Patch}, Suffix}.
%% Where Suffix is either an empty string or a tuple like {"rc", 1}.
%% NOTE: taking the nature ordering of the suffix:
%% {"alpha", _} < {"beta", _} < {"rc", _} < ""
parse_vsn(Vsn) ->
try
[V1, V2, V3 | Suffix0] = string:tokens(Vsn, ".-"),
Suffix =
case Suffix0 of
"" ->
%% For the case like "5.1.0"
"";
[ReleaseStage, Number] ->
%% For the case like "5.1.0-rc.1"
{ReleaseStage, list_to_integer(Number)}
end,
{{list_to_integer(V1), list_to_integer(V2), list_to_integer(V3)}, Suffix}
catch
_:_ ->
erlang:error({invalid_version_string, Vsn})
end.

View File

@ -0,0 +1,56 @@
%%--------------------------------------------------------------------
%% Copyright (c) 2023 EMQ Technologies Co., Ltd. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
%% You may obtain a copy of the License at
%%
%% http://www.apache.org/licenses/LICENSE-2.0
%%
%% Unless required by applicable law or agreed to in writing, software
%% distributed under the License is distributed on an "AS IS" BASIS,
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%% See the License for the specific language governing permissions and
%% limitations under the License.
%%--------------------------------------------------------------------
-module(emqx_release_tests).
-include_lib("eunit/include/eunit.hrl").
vsn_compre_test_() ->
CurrentVersion = emqx_release:version_with_prefix(),
[
{"must be 'same' when comparing with current version", fun() ->
?assertEqual(same, emqx_release:vsn_compare(CurrentVersion))
end},
{"must be 'same' when comparing same version strings", fun() ->
?assertEqual(same, emqx_release:vsn_compare("1.1.1", "1.1.1"))
end},
{"1.1.1 is older than 1.1.2", fun() ->
?assertEqual(older, emqx_release:vsn_compare("1.1.2", "1.1.1")),
?assertEqual(newer, emqx_release:vsn_compare("1.1.1", "1.1.2"))
end},
{"1.1.9 is older than 1.1.10", fun() ->
?assertEqual(older, emqx_release:vsn_compare("1.1.10", "1.1.9")),
?assertEqual(newer, emqx_release:vsn_compare("1.1.9", "1.1.10"))
end},
{"alpha is older than beta", fun() ->
?assertEqual(older, emqx_release:vsn_compare("1.1.1-beta.1", "1.1.1-alpha.2")),
?assertEqual(newer, emqx_release:vsn_compare("1.1.1-alpha.2", "1.1.1-beta.1"))
end},
{"beta is older than rc", fun() ->
?assertEqual(older, emqx_release:vsn_compare("1.1.1-rc.1", "1.1.1-beta.2")),
?assertEqual(newer, emqx_release:vsn_compare("1.1.1-beta.2", "1.1.1-rc.1"))
end},
{"rc is older than official cut", fun() ->
?assertEqual(older, emqx_release:vsn_compare("1.1.1", "1.1.1-rc.1")),
?assertEqual(newer, emqx_release:vsn_compare("1.1.1-rc.1", "1.1.1"))
end},
{"invalid version string will crash", fun() ->
?assertError({invalid_version_string, "1.1.a"}, emqx_release:vsn_compare("v1.1.a")),
?assertError(
{invalid_version_string, "1.1.1-alpha"}, emqx_release:vsn_compare("e1.1.1-alpha")
)
end}
].