Skip to content

Commit

Permalink
# Do not fail when unknown placeholder received
Browse files Browse the repository at this point in the history
- ActionInput now can hold static values.
- Improved unknown placeholder logic for detection and removing of them.
  • Loading branch information
miroslavpojer committed Nov 22, 2024
1 parent 66e52bd commit 01078ba
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 40 deletions.
48 changes: 42 additions & 6 deletions release_notes_generator/action_inputs.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import logging
import os
import sys
import re

from release_notes_generator.utils.constants import (
GITHUB_REPOSITORY,
Expand All @@ -38,11 +39,10 @@
DUPLICITY_ICON,
ROW_FORMAT_LINK_PR,
ROW_FORMAT_ISSUE,
ROW_FORMAT_PR,
ROW_FORMAT_PR, SUPPORTED_ROW_FORMAT_KEYS,
)
from release_notes_generator.utils.enums import DuplicityScopeEnum
from release_notes_generator.utils.gh_action import get_action_input
from release_notes_generator.utils.utils import detect_row_format_invalid_keywords

logger = logging.getLogger(__name__)

Expand All @@ -53,6 +53,10 @@ class ActionInputs:
A class representing the inputs provided to the GH action.
"""

_row_format_issue = None
_row_format_pr = None
_row_format_link_pr = None

@staticmethod
def get_github_repository() -> str:
"""
Expand Down Expand Up @@ -159,14 +163,18 @@ def get_row_format_issue() -> str:
"""
Get the issue row format for the release notes.
"""
return get_action_input(ROW_FORMAT_ISSUE, "{number} _{title}_ in {pull-requests}").strip()
if ActionInputs._row_format_issue is None:
ActionInputs._row_format_issue = ActionInputs._clean_row_format_invalid_keywords(get_action_input(ROW_FORMAT_ISSUE, "{number} _{title}_ in {pull-requests}").strip())
return ActionInputs._row_format_issue

@staticmethod
def get_row_format_pr() -> str:
"""
Get the pr row format for the release notes.
"""
return get_action_input(ROW_FORMAT_PR, "{number} _{title}_").strip()
if ActionInputs._row_format_pr is None:
ActionInputs._row_format_pr = ActionInputs._clean_row_format_invalid_keywords(get_action_input(ROW_FORMAT_PR, "{number} _{title}_").strip())
return ActionInputs._row_format_pr

@staticmethod
def get_row_format_link_pr() -> bool:
Expand Down Expand Up @@ -223,13 +231,13 @@ def validate_inputs():
if not isinstance(row_format_issue, str) or not row_format_issue.strip():
errors.append("Issue row format must be a non-empty string.")

errors.extend(detect_row_format_invalid_keywords(row_format_issue))
ActionInputs._detect_row_format_invalid_keywords(row_format_issue)

row_format_pr = ActionInputs.get_row_format_pr()
if not isinstance(row_format_pr, str) or not row_format_pr.strip():
errors.append("PR Row format must be a non-empty string.")

errors.extend(detect_row_format_invalid_keywords(row_format_pr, row_type="PR"))
ActionInputs._detect_row_format_invalid_keywords(row_format_pr, row_type="PR")

row_format_link_pr = ActionInputs.get_row_format_link_pr()
ActionInputs.validate_input(row_format_link_pr, bool, "'row-format-link-pr' value must be a boolean.", errors)
Expand All @@ -252,3 +260,31 @@ def validate_inputs():
logger.debug("Verbose logging: %s", verbose)
logger.debug("Warnings: %s", warnings)
logger.debug("Print empty chapters: %s", print_empty_chapters)

@staticmethod
def _detect_row_format_invalid_keywords(row_format: str, row_type: str = "Issue") -> None:
"""
Detects invalid keywords in the row format.
@param row_format: The row format to be checked for invalid keywords.
@param row_type: The type of row format. Default is "Issue".
@return: None
"""
keywords_in_braces = re.findall(r"\{(.*?)\}", row_format)
invalid_keywords = [keyword for keyword in keywords_in_braces if keyword not in SUPPORTED_ROW_FORMAT_KEYS]
for invalid_keyword in invalid_keywords:
logger.error(f"Invalid `{invalid_keyword}` detected in `{row_type}` row format keyword(s) found: {', '.join(invalid_keywords)}. Will be removed from string.")

@staticmethod
def _clean_row_format_invalid_keywords(row_format: str) -> str:
"""
Detects and clean invalid keywords in the row format.
@param row_format: The row format to be checked for invalid keywords.
@return: The cleaned row format.
"""
keywords_in_braces = re.findall(r"\{(.*?)\}", row_format)
invalid_keywords = [keyword for keyword in keywords_in_braces if keyword not in SUPPORTED_ROW_FORMAT_KEYS]
for invalid_keyword in invalid_keywords:
row_format = row_format.replace(f"{{{invalid_keyword}}}", "")
return row_format
16 changes: 0 additions & 16 deletions release_notes_generator/utils/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,19 +57,3 @@ def get_change_url(
changelog_url = f"https://github.com/{repo.full_name}/compare/{rls.tag_name}...{tag_name}"

return changelog_url


def detect_row_format_invalid_keywords(row_format: str, row_type: str = "Issue") -> list[str]:
"""
Detects invalid keywords in the row format.
@param row_format: The row format to be checked for invalid keywords.
@param row_type: The type of row format. Default is "Issue".
@return: A list of errors if invalid keywords are found, otherwise an empty list.
"""
errors = []
keywords_in_braces = re.findall(r"\{(.*?)\}", row_format)
invalid_keywords = [keyword for keyword in keywords_in_braces if keyword not in SUPPORTED_ROW_FORMAT_KEYS]
if invalid_keywords:
errors.append(f"Invalid {row_type} row format keyword(s) found: {', '.join(invalid_keywords)}")
return errors
37 changes: 37 additions & 0 deletions tests/test_action_inputs.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
import logging

import pytest

Expand Down Expand Up @@ -44,6 +45,8 @@
("get_verbose", "not_bool", "Verbose logging must be a boolean."),
("get_duplicity_icon", "", "Duplicity icon must be a non-empty string and have a length of 1."),
("get_duplicity_icon", "Oj", "Duplicity icon must be a non-empty string and have a length of 1."),
("get_row_format_issue", "", "Issue row format must be a non-empty string."),
("get_row_format_pr", "", "PR Row format must be a non-empty string."),
]


Expand Down Expand Up @@ -157,3 +160,37 @@ def test_get_duplicity_scope_wrong_value(mocker):

assert ActionInputs.get_duplicity_scope() == "BOTH"
mock_error.assert_called_with("Error: '%s' is not a valid DuplicityType.", "HUH")


def test_detect_row_format_invalid_keywords_no_invalid_keywords(caplog):
caplog.set_level(logging.ERROR)
row_format = "{number} _{title}_ in {pull-requests}"
ActionInputs._detect_row_format_invalid_keywords(row_format)
assert len(caplog.records) == 0


def test_detect_row_format_invalid_keywords_with_invalid_keywords(caplog):
caplog.set_level(logging.ERROR)
row_format = "{number} _{title}_ in {pull-requests} {invalid_key} {another_invalid}"
ActionInputs._detect_row_format_invalid_keywords(row_format)
assert len(caplog.records) == 2
expected_errors = [
"Invalid `invalid_key` detected in `Issue` row format keyword(s) found: invalid_key, another_invalid. Will be removed from string.",
"Invalid `another_invalid` detected in `Issue` row format keyword(s) found: invalid_key, another_invalid. Will be removed from string."
]
actual_errors = [record.getMessage() for record in caplog.records]
assert actual_errors == expected_errors


def test_clean_row_format_invalid_keywords_no_keywords():
row_format = "{number} _{title}_ in {pull-requests}"
cleaned_format = ActionInputs._clean_row_format_invalid_keywords(row_format)
assert cleaned_format == row_format


def test_clean_row_format_invalid_keywords_nested_braces():
row_format = "{number} _{title}_ in {pull-requests} {invalid_key} {another_invalid}"
expected_format = "{number} _{title}_ in {pull-requests} "
cleaned_format = ActionInputs._clean_row_format_invalid_keywords(row_format)
assert cleaned_format == expected_format

6 changes: 6 additions & 0 deletions tests/test_release_notes_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

from release_notes_generator.generator import ReleaseNotesGenerator
from release_notes_generator.model.custom_chapters import CustomChapters
from release_notes_generator.utils.constants import ROW_FORMAT_ISSUE


# generate_release_notes tests
Expand Down Expand Up @@ -111,6 +112,11 @@ def test_generate_release_notes_latest_release_found_by_created_at(
mock_rate_limit.core.remaining = 1000
github_mock.get_rate_limit.return_value = mock_rate_limit

mock_get_action_input = mocker.patch("release_notes_generator.utils.gh_action.get_action_input")
mock_get_action_input.side_effect = lambda first_arg, **kwargs: (
"{number} _{title}_ in {pull-requests} {unknown} {another-unknown}" if first_arg == ROW_FORMAT_ISSUE else None
)

custom_chapters = CustomChapters(print_empty_chapters=True)

release_notes = ReleaseNotesGenerator(github_mock, custom_chapters).generate()
Expand Down
20 changes: 2 additions & 18 deletions tests/utils/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#

from release_notes_generator.utils.utils import get_change_url, detect_row_format_invalid_keywords
from release_notes_generator.action_inputs import ActionInputs
from release_notes_generator.utils.utils import get_change_url


# get_change_url
Expand All @@ -33,19 +33,3 @@ def test_get_change_url_no_git_release(mock_repo):
def test_get_change_url_with_git_release(mock_repo, mock_git_release):
url = get_change_url(tag_name="v2.0.0", repository=mock_repo, git_release=mock_git_release)
assert url == "https://github.com/org/repo/compare/v1.0.0...v2.0.0"


# detect_row_format_invalid_keywords


def test_valid_row_format():
row_format = "{number} - {title} in {pull-requests}"
errors = detect_row_format_invalid_keywords(row_format)
assert not errors, "Expected no errors for valid keywords"


def test_multiple_invalid_keywords():
row_format = "{number} - {link} - {Title} and {Pull-requests}"
errors = detect_row_format_invalid_keywords(row_format)
assert len(errors) == 1
assert "Invalid Issue row format keyword(s) found: link, Title, Pull-requests" in errors[0]

0 comments on commit 01078ba

Please sign in to comment.