emqx_release.erl 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. %%--------------------------------------------------------------------
  2. %% Copyright (c) 2021-2023 EMQ Technologies Co., Ltd. All Rights Reserved.
  3. %%
  4. %% Licensed under the Apache License, Version 2.0 (the "License");
  5. %% you may not use this file except in compliance with the License.
  6. %% You may obtain a copy of the License at
  7. %%
  8. %% http://www.apache.org/licenses/LICENSE-2.0
  9. %%
  10. %% Unless required by applicable law or agreed to in writing, software
  11. %% distributed under the License is distributed on an "AS IS" BASIS,
  12. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. %% See the License for the specific language governing permissions and
  14. %% limitations under the License.
  15. %%--------------------------------------------------------------------
  16. -module(emqx_release).
  17. -export([
  18. edition/0,
  19. edition_vsn_prefix/0,
  20. edition_longstr/0,
  21. description/0,
  22. version/0,
  23. version_with_prefix/0,
  24. vsn_compare/1,
  25. vsn_compare/2
  26. ]).
  27. -include("emqx_release.hrl").
  28. -define(EMQX_DESCS, #{
  29. ee => "EMQX Enterprise",
  30. ce => "EMQX"
  31. }).
  32. -define(EMQX_REL_NAME, #{
  33. ee => <<"Enterprise">>,
  34. ce => <<"Opensource">>
  35. }).
  36. -define(EMQX_REL_VSNS, #{
  37. ee => ?EMQX_RELEASE_EE,
  38. ce => ?EMQX_RELEASE_CE
  39. }).
  40. -define(EMQX_REL_VSN_PREFIX, #{
  41. ee => "e",
  42. ce => "v"
  43. }).
  44. %% @doc Return EMQX description.
  45. description() ->
  46. maps:get(edition(), ?EMQX_DESCS).
  47. %% @doc Return EMQX edition info.
  48. %% Read info from persistent_term at runtime.
  49. %% Or meck this function to run tests for another edition.
  50. -spec edition() -> ce | ee.
  51. -ifdef(EMQX_RELEASE_EDITION).
  52. edition() -> ?EMQX_RELEASE_EDITION.
  53. -else.
  54. edition() -> ce.
  55. -endif.
  56. %% @doc Return EMQX version prefix string.
  57. edition_vsn_prefix() ->
  58. maps:get(edition(), ?EMQX_REL_VSN_PREFIX).
  59. %% @doc Return EMQX edition name, ee => Enterprise ce => Opensource.
  60. edition_longstr() ->
  61. maps:get(edition(), ?EMQX_REL_NAME).
  62. %% @doc Return the release version with prefix.
  63. version_with_prefix() ->
  64. edition_vsn_prefix() ++ version().
  65. %% @doc Return the release version.
  66. version() ->
  67. case lists:keyfind(emqx_vsn, 1, ?MODULE:module_info(compile)) of
  68. %% For TEST build or dependency build.
  69. false ->
  70. build_vsn();
  71. %% For emqx release build
  72. {_, Vsn} ->
  73. VsnStr = build_vsn(),
  74. case string:str(Vsn, VsnStr) of
  75. 1 ->
  76. ok;
  77. _ ->
  78. erlang:error(#{
  79. reason => version_mismatch,
  80. source => VsnStr,
  81. built_for => Vsn
  82. })
  83. end,
  84. Vsn
  85. end.
  86. build_vsn() ->
  87. maps:get(edition(), ?EMQX_REL_VSNS).
  88. %% @doc Compare the given version with the current running version,
  89. %% return 'newer' 'older' or 'same'.
  90. vsn_compare("v" ++ Vsn) ->
  91. vsn_compare(?EMQX_RELEASE_CE, Vsn);
  92. vsn_compare("e" ++ Vsn) ->
  93. vsn_compare(?EMQX_RELEASE_EE, Vsn).
  94. %% @private Compare the second argument with the first argument, return
  95. %% 'newer' 'older' or 'same' semver comparison result.
  96. vsn_compare(Vsn1, Vsn2) ->
  97. ParsedVsn1 = parse_vsn(Vsn1),
  98. ParsedVsn2 = parse_vsn(Vsn2),
  99. case ParsedVsn1 =:= ParsedVsn2 of
  100. true ->
  101. same;
  102. false when ParsedVsn1 < ParsedVsn2 ->
  103. newer;
  104. false ->
  105. older
  106. end.
  107. %% @private Parse the version string to a tuple.
  108. %% Return {{Major, Minor, Patch}, Suffix}.
  109. %% Where Suffix is either an empty string or a tuple like {"rc", 1}.
  110. %% NOTE: taking the nature ordering of the suffix:
  111. %% {"alpha", _} < {"beta", _} < {"rc", _} < ""
  112. parse_vsn(Vsn) ->
  113. try
  114. [V1, V2, V3 | Suffix0] = string:tokens(Vsn, ".-"),
  115. Suffix =
  116. case Suffix0 of
  117. "" ->
  118. %% "5.1.0"
  119. "";
  120. ["g" ++ _] ->
  121. %% "5.1.0-g53ab85b1"
  122. "";
  123. [ReleaseStage, Number | _] ->
  124. %% "5.1.0-rc.1" or "5.1.0-rc.1-g53ab85b1"
  125. {ReleaseStage, list_to_integer(Number)}
  126. end,
  127. {{list_to_integer(V1), list_to_integer(V2), list_to_integer(V3)}, Suffix}
  128. catch
  129. _:_ ->
  130. erlang:error({invalid_version_string, Vsn})
  131. end.