Skip to content

Commit

Permalink
feat(parser_angular): allow customization in parser
Browse files Browse the repository at this point in the history
- `parser_angular_allowed_types` controls allowed types
  - defaults stay the same: build, chore, ci, docs, feat, fix, perf, style,
    refactor, test
- `parser_angular_default_level_bump` controls the default level to bump the
  version by
  - default stays at 0
- `parser_angular_minor_types` controls which types trigger a minor version
  bump
  - default stays at only 'feat'
- `parser_angular_patch_types` controls which types trigger a patch version
  - default stays at 'fix' or 'perf'
  • Loading branch information
charlesthomas authored and relekang committed Nov 21, 2021
1 parent 6801386 commit 298eebb
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 26 deletions.
4 changes: 4 additions & 0 deletions semantic_release/defaults.cfg
@@ -1,4 +1,8 @@
[semantic_release]
parser_angular_allowed_types=build,chore,ci,docs,feat,fix,perf,style,refactor,test
parser_angular_default_level_bump=0
parser_angular_minor_types=feat
parser_angular_patch_types=fix,perf
branch=master
build_command=python setup.py sdist bdist_wheel
changelog_components=semantic_release.changelog.changelog_headers
Expand Down
53 changes: 27 additions & 26 deletions semantic_release/history/parser_angular.py
Expand Up @@ -8,42 +8,32 @@

from ..errors import UnknownCommitMessageStyleError
from ..helpers import LoggedFunction
from ..settings import config
from .parser_helpers import ParsedCommit, parse_paragraphs, re_breaking

logger = logging.getLogger(__name__)

# Supported commit types for parsing
allowed_types = config.get('parser_angular_allowed_types').split(',')

# types with long names in changelog
TYPES = {
"feat": "feature",
"fix": "fix",
"test": "test",
"docs": "documentation",
"style": "style",
"refactor": "refactor",
"build": "build",
"ci": "ci",
"perf": "performance",
"chore": "chore",
}

re_parser = re.compile(
r"(?P<type>" + "|".join(TYPES.keys()) + ")"
r"(?P<type>" + "|".join(allowed_types) + ")"
r"(?:\((?P<scope>[^\n]+)\))?"
r"(?P<break>!)?: "
r"(?P<subject>[^\n]+)"
r"(:?\n\n(?P<text>.+))?",
re.DOTALL,
)

MINOR_TYPES = [
"feat",
]

PATCH_TYPES = [
"fix",
"perf",
]

MINOR_TYPES = config.get('parser_angular_minor_types').split(',')
PATCH_TYPES = config.get('parser_angular_patch_types').split(',')

@LoggedFunction(logger)
def parse_commit_message(message: str) -> ParsedCommit:
Expand All @@ -60,13 +50,19 @@ def parse_commit_message(message: str) -> ParsedCommit:
raise UnknownCommitMessageStyleError(
f"Unable to parse the given commit message: {message}"
)
parsed_break = parsed.group('break')
parsed_scope = parsed.group('scope')
parsed_subject = parsed.group('subject')
parsed_text = parsed.group('text')
parsed_type = parsed.group('type')

if parsed.group("text"):
descriptions = parse_paragraphs(parsed.group("text"))

if parsed_text:
descriptions = parse_paragraphs(parsed_text)
else:
descriptions = list()
# Insert the subject before the other paragraphs
descriptions.insert(0, parsed.group("subject"))
descriptions.insert(0, parsed_subject)

# Look for descriptions of breaking changes
breaking_descriptions = [
Expand All @@ -75,18 +71,23 @@ def parse_commit_message(message: str) -> ParsedCommit:
if match
]

level_bump = 0
if parsed.group("break") or breaking_descriptions:
level_bump = int(config.get('parser_angular_default_level_bump'))
if parsed_break or breaking_descriptions:
level_bump = 3 # Major
elif parsed.group("type") in MINOR_TYPES:
elif parsed_type in MINOR_TYPES:
level_bump = 2 # Minor
elif parsed.group("type") in PATCH_TYPES:
elif parsed_type in PATCH_TYPES:
level_bump = 1 # Patch

parsed_type_long = TYPES.get(parsed_type, parsed_type)
# first param is the key you're getting from the dict,
# second param is the default value
# allows only putting types with a long name in the TYPES dict

return ParsedCommit(
level_bump,
TYPES[parsed.group("type")],
parsed.group("scope"),
parsed_type_long,
parsed_scope,
descriptions,
breaking_descriptions,
)
32 changes: 32 additions & 0 deletions tests/parsers/test_angular.py
Expand Up @@ -3,6 +3,8 @@
from semantic_release.errors import UnknownCommitMessageStyleError
from semantic_release.history import angular_parser

from .. import mock,wrapped_config_get

text = (
"This is an long explanatory part of a commit message. It should give "
"some insight to the fix this commit adds to the codebase."
Expand Down Expand Up @@ -97,3 +99,33 @@ def test_parser_return_footer_from_commit_message():
def test_parser_should_accept_message_without_scope():
assert angular_parser("fix: superfix")[0] == 1
assert angular_parser("fix: superfix")[3][0] == "superfix"

##############################
# test custom parser options #
##############################
@mock.patch("semantic_release.history.parser_angular.config.get",
wrapped_config_get(parser_angular_default_level_bump='50'))
def test_parser_custom_default_level():
assert angular_parser("test(parser): Add a test for angular parser")[0] == 50


@mock.patch("semantic_release.history.parser_angular.config.get",
wrapped_config_get(
parser_angular_allowed_types=
'custom,build,chore,ci,docs,fix,perf,style,refactor,test'))
def test_parser_custom_allowed_types():
assert angular_parser("custom: ...")[0] == 0
assert angular_parser("custom(parser): ...")[1] == "custom"
pytest.raises(UnknownCommitMessageStyleError, angular_parser, "feat(parser): ...")


@mock.patch("semantic_release.history.parser_angular.config.get",
wrapped_config_get(parser_angular_minor_types='docs'))
def test_parser_custom_minor_types():
assert angular_parser("docs: write some docs")[0] == 2


@mock.patch("semantic_release.history.parser_angular.config.get",
wrapped_config_get(parser_angular_patch_types='test'))
def test_parser_custom_patch_types():
assert angular_parser("test(this): added a test")[0] == 1

0 comments on commit 298eebb

Please sign in to comment.