Repository: relekang/python-semantic-release (python)

Issue:
Configurable tag names
## Description

Currently when a commit is tagged, the tag name and message are both fixed to the version number.

https://github.com/relekang/python-semantic-release/blob/1dd84847a9eaf8d2467ae5b4ee82492ef563612f/semantic_release/vcs_helpers.py#L198-L204

It would be nice if the user were able to configure a template for the tag name or message.

## Use cases

One major use case would be when `python-semantic-release` is being used in a staging environment. The tags could take the form `vX.Y.X-staging`. Note that this would not be a prerelease specification. `python-semantic-release` only supports versioning at the `major`, `minor`, and `patch` levels so this would template would live outside the scope of semantic versioning. It would exist solely as git tags.



## Possible implementation

https://github.com/relekang/python-semantic-release/blob/18e1d70138125f93664f3c9b3c1e08c57f392977/semantic_release/cli.py#L173-L187

The calling function already has access to the config variables, so it would be straightforward to add a `tag_template` configuration variable.


Pull request:
feat: custom git tag format support
Related to #316

Ability to define custom git tag format via `tag_format` config option

Also the JS implementation of the semantic release [already has the same feature](https://github.com/semantic-release/semantic-release/blob/master/docs/usage/configuration.md#tagformat)


Patch:
diff --git a/docs/configuration.rst b/docs/configuration.rst
index cb5eb22..2a13859 100644
--- a/docs/configuration.rst
+++ b/docs/configuration.rst
@@ -435,3 +435,17 @@ If enabled, the status of the head commit will be checked and a release will onl
 if the status is success.
 
 Default: `false`
+
+.. _config-tag_format:
+
+``tag_format``
+------------------
+Git tag format. Accepts the following variables as format fields:
+
+================  ========
+Variable          Contents
+================  ========
+``{version}``     The new version number in the format ``X.Y.Z``.
+================  ========
+
+Default: ``v{version}``
diff --git a/semantic_release/defaults.cfg b/semantic_release/defaults.cfg
index f45e8a7..6ceee2b 100644
--- a/semantic_release/defaults.cfg
+++ b/semantic_release/defaults.cfg
@@ -24,3 +24,4 @@ changelog_file=CHANGELOG.md
 changelog_placeholder=<!--next-version-placeholder-->
 changelog_scope=true
 tag_commit=true
+tag_format=v{version}
diff --git a/semantic_release/vcs_helpers.py b/semantic_release/vcs_helpers.py
index 6ca139f..31d2a36 100644
--- a/semantic_release/vcs_helpers.py
+++ b/semantic_release/vcs_helpers.py
@@ -196,11 +196,13 @@ def update_changelog_file(version: str, content_to_add: str):
 @LoggedFunction(logger)
 def tag_new_version(version: str):
     """
-    Create a new tag with the version number, prefixed with v.
+    Create a new tag with the version number, prefixed with v by default.
 
     :param version: The version number used in the tag as a string.
     """
-    return repo.git.tag("-a", f"v{version}", m=f"v{version}")
+    tag_format = config.get("tag_format")
+    tag = tag_format.format(version=version)
+    return repo.git.tag("-a", tag, m=tag)
 
 
 @check_repo


Test patch:
diff --git a/tests/test_vcs_helpers.py b/tests/test_vcs_helpers.py
index 6bc5420..969a0be 100644
--- a/tests/test_vcs_helpers.py
+++ b/tests/test_vcs_helpers.py
@@ -103,9 +103,13 @@ def test_add_and_commit(mock_git, mocker, params):
     mock_git.commit.assert_called_once_with(**params["commit_args"])
 
 
-def test_tag_new_version(mock_git):
+def test_tag_new_version(mock_git, mocker):
+    mocker.patch(
+        "semantic_release.vcs_helpers.config.get",
+        return_value="ver{version}",
+    )
     tag_new_version("1.0.0")
-    mock_git.tag.assert_called_with("-a", "v1.0.0", m="v1.0.0")
+    mock_git.tag.assert_called_with("-a", "ver1.0.0", m="ver1.0.0")
 
 
 def test_push_new_version(mock_git):