From 5881303c3e06f9d631804150c78be7fc10d15779 Mon Sep 17 00:00:00 2001 From: Asaf Shakarzy Date: Fri, 14 Mar 2025 12:40:12 +0200 Subject: [PATCH] feat(parser-angular): add scope filtering option to Angular commit parser resolves #1215 --- src/semantic_release/commit_parser/angular.py | 27 ++++++++++++++-- .../commit_parser/test_conventional.py | 31 +++++++++++++++++++ 2 files changed, 55 insertions(+), 3 deletions(-) diff --git a/src/semantic_release/commit_parser/angular.py b/src/semantic_release/commit_parser/angular.py index ca739cc91..1765fd5d9 100644 --- a/src/semantic_release/commit_parser/angular.py +++ b/src/semantic_release/commit_parser/angular.py @@ -94,6 +94,9 @@ class AngularParserOptions(ParserOptions): one of these prefixes, it will not be considered a valid commit message. """ + allowed_scopes: Tuple[str, ...] = () + """If set, only commits with a matching scope will be considered.""" + default_bump_level: LevelBump = LevelBump.NO_RELEASE """The minimum bump level to apply to valid commit message.""" @@ -335,10 +338,28 @@ def is_merge_commit(commit: Commit) -> bool: return len(commit.parents) > 1 def parse_commit(self, commit: Commit) -> ParseResult: - if not (parsed_msg_result := self.parse_message(force_str(commit.message))): + parsed_msg_result = self.parse_message(force_str(commit.message)) + + if not parsed_msg_result: + return _logged_parse_error( + commit, f"Unable to parse commit message: {commit.message!r}" + ) + + # Check if we have defined allowed scopes + has_allowed_scopes = bool(self.options.allowed_scopes) + has_scope = bool(parsed_msg_result.scope) + is_scope_allowed = ( + has_scope and parsed_msg_result.scope in self.options.allowed_scopes + ) + + # If no allowed_scopes are defined, skip filtering + if not has_allowed_scopes: + return ParsedCommit.from_parsed_message_result(commit, parsed_msg_result) + + # If allowed_scopes are defined, enforce filtering + if not has_scope or not is_scope_allowed: return _logged_parse_error( - commit, - f"Unable to parse commit message: {commit.message!r}", + commit, f"Skipping commit due to scope filtering: {commit.message!r}" ) return ParsedCommit.from_parsed_message_result(commit, parsed_msg_result) diff --git a/tests/unit/semantic_release/commit_parser/test_conventional.py b/tests/unit/semantic_release/commit_parser/test_conventional.py index 078e1ecd5..1ab4580b3 100644 --- a/tests/unit/semantic_release/commit_parser/test_conventional.py +++ b/tests/unit/semantic_release/commit_parser/test_conventional.py @@ -1246,3 +1246,34 @@ def test_parser_ignore_merge_commit( assert isinstance(parsed_result, ParseError) assert "Ignoring merge commit" in parsed_result.error + +@pytest.mark.parametrize( + "commit_message, allowed_scopes, expected_result", + [ + ("feat(pkg1): add feature A", ("pkg1",), True), + ("fix(pkg2): fix something", ("pkg1",), False), + ("chore(pkg3): maintenance task", ("pkg3",), True), + ("docs(pkg1): update documentation", ("pkg1", "pkg3"), True), + ("feat(pkg4): add feature B", (), True), # Empty tuple means no scope restriction + ("fix: global fix", ("pkg1",), False), # No scope in message, should not pass + ], +) +def test_parser_scope_filtering(make_commit_obj: MakeCommitObjFn, commit_message, allowed_scopes, expected_result): + """Tests whether ConventionalCommitParser correctly filters commits based on the allowed_scopes option.""" + parser = ConventionalCommitParser( + options=ConventionalCommitParserOptions(allowed_scopes=allowed_scopes) + ) + + parsed_results = parser.parse(make_commit_obj(commit_message)) + + # Ensure that `parsed_results` is a list and extract the first element (if any) + assert isinstance(parsed_results, list), f"Expected list but got {type(parsed_results)}" + assert len(parsed_results) > 0, "Expected at least one parsed result" + + result = parsed_results[0] # Extract the first parsed commit or error + + if expected_result: + assert isinstance(result, ParsedCommit), f"Expected ParsedCommit but got {result}" + else: + assert isinstance(result, ParseError), f"Expected ParseError but got {result}" + assert "Skipping commit due to scope filtering" in result.error pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy