diff --git a/.github/workflows/elixir.yml b/.github/workflows/elixir.yml index 231dbdf..73349f4 100644 --- a/.github/workflows/elixir.yml +++ b/.github/workflows/elixir.yml @@ -17,8 +17,8 @@ jobs: - name: Set up Elixir uses: erlef/setup-beam@v1 with: - elixir-version: '1.13.3' - otp-version: '24.3' + elixir-version: '1.14.0' + otp-version: '25.2' - name: Restore dependencies cache uses: actions/cache@v3 with: diff --git a/.tool-versions b/.tool-versions index 7386990..13eee92 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,2 +1,2 @@ -erlang 24.3 -elixir 1.13.3-otp-24 +erlang 25.2 +elixir 1.14.0-otp-25 diff --git a/config/config.exs b/config/config.exs index 7ca393f..155d2b6 100644 --- a/config/config.exs +++ b/config/config.exs @@ -1,19 +1,15 @@ import Config config :versioce, - files: ["README.md"], - global: false, - pre_hooks: [], post_hooks: [Versioce.PostHooks.Changelog, Versioce.PostHooks.Git.Release] config :versioce, :git, + additional_files: ["CHANGELOG.md"], commit_message_template: ":clap: Bump version to {version}", tag_template: "v{version}", - tag_message_template: ":clap: Release v{version}\n{tag_changelog}", - additional_files: ["CHANGELOG.md"] + tag_message_template: ":clap: Release v{version}\n{tag_changelog}" config :versioce, :changelog, - datagrabber: Versioce.Changelog.DataGrabber.Git, anchors: %{ added: [ ":sparkles:", diff --git a/lib/Config/config.ex b/lib/Config/config.ex index d1ed733..c708fd2 100644 --- a/lib/Config/config.ex +++ b/lib/Config/config.ex @@ -9,40 +9,65 @@ defmodule Versioce.Config do Other config namespaces: `Versioce.Config.Git` + `Versioce.Config.Changelog` """ import Versioce.Config.Macros, only: :macros + alias Versioce.Config.Macros.Description value( :files, ["README.md"], - "Files to be updated with new version. File paths should be relative to your `mix.exs`" + %Description{ + description: "Files to be updated with new version. File paths should be relative to your `mix.exs`", + } ) value( :global, false, - "Whether the update will be global in file.\nBy default versioce will update only the first version in file it finds" + %Description{ + description: "Whether the update will be global in file.\nBy default versioce will update only the first version in file it finds", + example: true + } ) value( :calver_format, "YYYY.0M.0D", - """ - What format to use for version when using CalVer. - It should be still 3 values separated by a dot semver style. - - Available parts are: - YYYY - Full year - 2006, 2016, 2106 - MM - Short month - 1, 2 ... 11, 12 - 0M - Zero-padded month - 01, 02 ... 11, 12 - DD - Short day - 1, 2 ... 30, 31 - 0D - Zero-padded day - 01, 02 ... 30, 31 - """ + %Description{ + description: """ + What format to use for version when using CalVer. + It should be still 3 values separated by a dot semver style. + + Available parts are: + YYYY - Full year - 2006, 2016, 2106 + MM - Short month - 1, 2 ... 11, 12 + 0M - Zero-padded month - 01, 02 ... 11, 12 + DD - Short day - 1, 2 ... 30, 31 + 0D - Zero-padded day - 01, 02 ... 30, 31 + """, + example: "YYYY_MM_DD" + } ) - value(:pre_hooks, [], "Hooks to run before the version bumping") - value(:post_hooks, [], "Hooks to run after the version bumping") + value( + :pre_hooks, + [], + %Description{ + description: "Hooks to run before the version bumping", + example: [Versioce.PreHooks.Inspect] + } + ) + + value( + :post_hooks, + [], + %Description{ + description: "Hooks to run after the version bumping", + example: [Versioce.PostHooks.Inspect] + } + ) defmodule Git do @moduledoc """ @@ -52,31 +77,46 @@ defmodule Versioce.Config do value( [:git, :dirty_add], false, - "Whether to add all the files in `git add` or only from `Versioce.Config.files/0` and `Versioce.Config.Git.additional_files/0`. By default only `Versioce.Config.files/0`" + %Description{ + description: "Whether to add all the files in `git add` or only from `Versioce.Config.files/0` and `Versioce.Config.Git.additional_files/0`. By default only `Versioce.Config.files/0`", + example: true + } ) value( [:git, :additional_files], [], - "Additional files to add in `git add`. No effect if `Versioce.Config.Git.dirty_add/0` is set to `true`" + %Description{ + description: "Additional files to add in `git add`. No effect if `Versioce.Config.Git.dirty_add/0` is set to `true`", + example: ["CHANGELOG.md"] + } ) value( [:git, :commit_message_template], "Bump version to {version}", - "Template for the commit message. `{version}` will be replaced with the version you bumped to" + %Description{ + description: "Template for the commit message. `{version}` will be replaced with the version you bumped to", + example: "Bumping my awesome app to {version}" + } ) value( [:git, :tag_template], "{version}", - "Template for the tag annotation. `{version}` will be replaced with the version you bumped to" + %Description{ + description: "Template for the tag annotation. `{version}` will be replaced with the version you bumped to", + example: "v{version}" + } ) value( [:git, :tag_message_template], - "Release version to {version}", - "Template for the tag message. `{version}` will be replaced with the version you bumped to, `{tag_changelog} with relevant changelog part.`" + "Release {version}", + %Description{ + description: "Template for the tag message. `{version}` will be replaced with the version you bumped to, `{tag_changelog} with relevant changelog part.`", + example: "v{version}\n{tag_changelog}" + } ) end @@ -89,7 +129,9 @@ defmodule Versioce.Config do value( [:changelog, :datagrabber], Versioce.Changelog.DataGrabber.Git, - "Data grabber for changelog generation. This data is further converted to a proper format with `Versioce.Config.Changelog.formatter/0`. For custom datagrabber see `Versioce.Changelog.DataGrabber`" + %Description{ + description: "Data grabber for changelog generation. This data is further converted to a proper format with `Versioce.Config.Changelog.formatter/0`. For custom datagrabber see `Versioce.Changelog.DataGrabber`", + } ) value( @@ -102,37 +144,52 @@ defmodule Versioce.Config do fixed: ["[FIXED]"], security: ["[SEC]"] }, - "Anchors to look for in `Versioce.Changelog.DataGrabber.Git`. They will be converted to `Versioce.Changelog.Anchors` struct" + %Description{ + description: "Anchors to look for in `Versioce.Changelog.DataGrabber.Git`. They will be converted to `Versioce.Changelog.Anchors` struct", + } ) value( [:changelog, :formatter], Versioce.Changelog.Formatter.Keepachangelog, - "Formatter for changelog generation. Formats data from grabbed by `Versioce.Config.Changelog.datagrabber`. For custom formatter see `Versioce.Changelog.Formatter`" + %Description{ + description: "Formatter for changelog generation. Formats data from grabbed by `Versioce.Config.Changelog.datagrabber`. For custom formatter see `Versioce.Changelog.Formatter`", + } ) value( [:changelog, :unanchored_section], :other, - "Section in changelog where unanchored entries should be placed. If `nil`, they are ignored and won't be added to the changelog. For more info see `Versioce.Changelog.Formatter.Keepachangelog`" + %Description{ + description: "Section in changelog where unanchored entries should be placed. If `nil`, they are ignored and won't be added to the changelog. For more info see `Versioce.Changelog.Formatter.Keepachangelog`", + } ) value( [:changelog, :changelog_file], "CHANGELOG.md", - "File to put your changelog in. File path should be relative to your `mix.exs`" + %Description{ + description: "File to put your changelog in. File path should be relative to your `mix.exs`", + example: "OTHERFILE.md" + } ) value( [:changelog, :keepachangelog_semantic], true, - "Whether the project adheres to Semantic Versioning. Used in a `Versioce.Changelog.Formatter.Keepachangelog`" + %Description{ + description: "Whether the project adheres to Semantic Versioning. Used in a `Versioce.Changelog.Formatter.Keepachangelog`", + example: false + } ) value( [:changelog, :git_origin], nil, - "Project repository url for changelog footer generation. If nil, footer section will be ignored. For more info see `Versioce.Changelog.Formatter.Keepachangelog.make_footer/1`" + %Description{ + description: "Project repository url for changelog footer generation. If nil, footer section will be ignored. For more info see `Versioce.Changelog.Formatter.Keepachangelog.make_footer/1`", + example: Mix.Project.config()[:source_url] + } ) end end diff --git a/lib/Config/config_macros.ex b/lib/Config/config_macros.ex index bc5b66d..117f90a 100644 --- a/lib/Config/config_macros.ex +++ b/lib/Config/config_macros.ex @@ -1,5 +1,13 @@ +defmodule Versioce.Config.Macros.Description do + @moduledoc false + defstruct description: "", example: nil + + @type t :: __MODULE__ +end + defmodule Versioce.Config.Macros do @moduledoc false + alias Versioce.Config.Macros.Description @doc """ Macro to define a simple config value or by path. @@ -10,30 +18,35 @@ defmodule Versioce.Config.Macros do `key`s should be unique for their module. When called, value will either be picked from Application or default. + In description the example value can be set via `:example` key. If not set, the default + value will be used as an example one. + ex.: - value :foo, "default value", "description" - value [:spam, :eggs], %{}, "another description" + value :foo, "default value", %Description{doc: "description", example: "example value"} + value [:spam, :eggs], %{}, %Description{doc: "description"} """ - defmacro value(key_or_path, default, doc \\ "") + defmacro value(key_or_path, default, doc \\ %Description{description: "", example: ""}) defmacro value(key, default, doc) when is_atom(key) do quote do @doc """ Get config value for #{to_string(unquote(key))} - #{unquote(doc)} + Default value: #{inspect(unquote(default))} + + #{unquote(doc).description} You can configure it with: config :versioce, - #{to_string(unquote(key))}: #{inspect(unquote(default))} + #{to_string(unquote(key))}: #{inspect(if example = unquote(doc).example, do: example, else: unquote(default))} Value for this configuration should either be a literal value or a function of 0 arity, that will return the value, ex: config :versioce, - #{to_string(unquote(key))}: fn -> #{inspect(unquote(default))} end + #{to_string(unquote(key))}: fn -> #{inspect(if example = unquote(doc).example, do: example, else: unquote(default))} end """ def unquote(key)() do case Application.fetch_env(:versioce, unquote(key)) do @@ -59,18 +72,20 @@ defmodule Versioce.Config.Macros do @doc """ Get config value for #{to_string(unquote(t))} - #{unquote(doc)} + Default value: #{inspect(unquote(default))} + + #{unquote(doc).description} You can configure it with: config :versioce, #{inspect(unquote(h))}, - #{to_string(unquote(t))}: #{inspect(unquote(default))} + #{to_string(unquote(t))}: #{inspect(if example = unquote(doc).example, do: example, else: unquote(default))} Value for this configuration should either be a literal value or a function of 0 arity, that will return the value, ex: config :versioce, #{inspect(unquote(h))}, - #{to_string(unquote(t))}: fn -> #{inspect(unquote(default))} end + #{to_string(unquote(t))}: fn -> #{inspect(if example = unquote(doc).example, do: example, else: unquote(default))} end """ def unquote(t)() do with {:ok, val} <- Application.fetch_env(:versioce, unquote(h)), diff --git a/lib/Hooks/git_hooks.ex b/lib/Hooks/git_hooks.ex index 5251d72..43789ec 100644 --- a/lib/Hooks/git_hooks.ex +++ b/lib/Hooks/git_hooks.ex @@ -54,7 +54,19 @@ if Versioce.Utils.deps_loaded?([Git]) do message = Versioce.Config.Git.tag_message_template() |> String.replace("{version}", version, global: true) - |> String.replace( + |> maybe_add_changelog(version) + + version + |> Versioce.Git.get_tag_name() + |> Versioce.Git.tag(message, ["--cleanup=whitespace"]) + + {:ok, version} + end + + defp maybe_add_changelog(message, version) do + if String.contains?(message, "{tag_changelog}") do + String.replace( + message, "{tag_changelog}", fn _ -> ChangelogConf.datagrabber().get_version() @@ -63,12 +75,9 @@ if Versioce.Utils.deps_loaded?([Git]) do end, global: true ) - - version - |> Versioce.Git.get_tag_name() - |> Versioce.Git.tag(message, ["--cleanup=whitespace"]) - - {:ok, version} + else + message + end end end diff --git a/test/bumper_test.exs b/test/bumper_test.exs index 0fe88ca..6907cbc 100644 --- a/test/bumper_test.exs +++ b/test/bumper_test.exs @@ -91,7 +91,7 @@ defmodule VersioceTest.Bumper do assert helper_bump(["2.3.3-foo"], vers) == "2.3.3-foo" assert helper_bump(["2.3.3+bar"], vers) == "2.3.3+bar" assert helper_bump(["2.3.3-foo+bar"], vers) == "2.3.3-foo+bar" - assert helper_bump(["2.3.3-foo.3-1+bar.50-6"], vers) == "2.3.3-foo.3-1+bar50-6" + assert helper_bump(["2.3.3-foo.3-1+bar.50-6"], vers) == "2.3.3-foo.3-1+bar.50-6" assert_raise Version.InvalidVersionError, fn -> helper_bump(["2.3.3-foo[]"], vers)