-module(version_bump@plugins@commit_analyzer).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/version_bump/plugins/commit_analyzer.gleam").
-export([analyze/1, plugin/0]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC(
" The `commit-analyzer` plugin: determines the release type implied by a set\n"
" of conventional commits, mirroring `@semantic-release/commit-analyzer`.\n"
"\n"
" Rules (the highest matching type wins):\n"
" - any breaking change -> Major\n"
" - else any `feat` -> Minor\n"
" - else any `fix` or `perf` -> Patch\n"
" - otherwise -> no release\n"
"\n"
" The pure `analyze` function holds all the logic so it can be unit-tested\n"
" without a context; `plugin/0` wraps it as the `analyze_commits` hook.\n"
).
-file("src/version_bump/plugins/commit_analyzer.gleam", 23).
?DOC(" Classify a single commit into the release type it warrants, if any.\n").
-spec classify(version_bump@commit_parser:conventional_commit()) -> gleam@option:option(version_bump@semver:release_type()).
classify(Commit) ->
case erlang:element(6, Commit) of
true ->
{some, major};
false ->
case erlang:element(3, Commit) of
{some, <<"feat"/utf8>>} ->
{some, minor};
{some, <<"fix"/utf8>>} ->
{some, patch};
{some, <<"perf"/utf8>>} ->
{some, patch};
_ ->
none
end
end.
-file("src/version_bump/plugins/commit_analyzer.gleam", 37).
?DOC(
" Keep whichever of two optional release types is higher in precedence.\n"
" `None` means \"no release\", which is lower than any concrete type.\n"
).
-spec keep_highest(
gleam@option:option(version_bump@semver:release_type()),
gleam@option:option(version_bump@semver:release_type())
) -> gleam@option:option(version_bump@semver:release_type()).
keep_highest(Current, Candidate) ->
case {Current, Candidate} of
{none, Other} ->
Other;
{Other@1, none} ->
Other@1;
{{some, A}, {some, B}} ->
case version_bump@semver:release_type_rank(B) > version_bump@semver:release_type_rank(
A
) of
true ->
{some, B};
false ->
{some, A}
end
end.
-file("src/version_bump/plugins/commit_analyzer.gleam", 56).
?DOC(
" Determine the release type for a list of conventional commits.\n"
"\n"
" Returns the highest release type any commit warrants, or `None` when no\n"
" commit triggers a release. This is the pure core of the plugin.\n"
).
-spec analyze(list(version_bump@commit_parser:conventional_commit())) -> gleam@option:option(version_bump@semver:release_type()).
analyze(Commits) ->
gleam@list:fold(
Commits,
none,
fun(Acc, Commit) -> keep_highest(Acc, classify(Commit)) end
).
-file("src/version_bump/plugins/commit_analyzer.gleam", 64).
?DOC(
" The `analyze_commits` hook: read already-parsed commits from the context and\n"
" report the implied release type.\n"
).
-spec analyze_commits(
version_bump@config:plugin_spec(),
version_bump@context:context()
) -> {ok, gleam@option:option(version_bump@semver:release_type())} |
{error, version_bump@error:release_error()}.
analyze_commits(_, Context) ->
{ok, analyze(erlang:element(7, Context))}.
-file("src/version_bump/plugins/commit_analyzer.gleam", 72).
?DOC(" The `commit-analyzer` plugin, implementing only `analyze_commits`.\n").
-spec plugin() -> version_bump@plugin:plugin().
plugin() ->
_record = version_bump@plugin:new(<<"commit-analyzer"/utf8>>),
{plugin,
erlang:element(2, _record),
erlang:element(3, _record),
{some, fun analyze_commits/2},
erlang:element(5, _record),
erlang:element(6, _record),
erlang:element(7, _record),
erlang:element(8, _record),
erlang:element(9, _record),
erlang:element(10, _record),
erlang:element(11, _record)}.