-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)}.