Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bugfix/85 wrong type used in chapters definition #122

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 10 additions & 14 deletions .github/workflows/release_draft.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,20 +65,16 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag-name: ${{ github.event.inputs.tag-name }}
from-tag-name: ${{ github.event.inputs.from-tag-name }}
chapters: '[
{"title": "No entry 🚫", "label": "duplicate"},
{"title": "No entry 🚫", "label": "invalid"},
{"title": "No entry 🚫", "label": "wontfix"},
{"title": "No entry 🚫", "label": "no RN"},
{"title": "Breaking Changes 💥", "label": "breaking-change"},
{"title": "New Features 🎉", "label": "enhancement"},
{"title": "New Features 🎉", "label": "feature"},
{"title": "Bugfixes 🛠", "label": "bug"},
{"title": "Infrastructure ⚙️", "label": "infrastructure"},
{"title": "Silent-live 🤫", "label": "silent-live"},
{"title": "Documentation 📜", "label": "documentation"}
]'
chapters: |
- { title: No entry 🚫, label: duplicate }
- { title: Breaking Changes 💥, label: breaking-change }
- { title: New Features 🎉, label: enhancement }
- { title: New Features 🎉, label: feature }
- { title: Bugfixes 🛠, label: bug }
- { title: Infrastructure ⚙️, label: infrastructure }
- { title: Silent-live 🤫, label: silent-live }
- { title: Documentation 📜, label: documentation }
MobiTikula marked this conversation as resolved.
Show resolved Hide resolved

skip-release-notes-label: 'no RN'
verbose: true

Expand Down
38 changes: 21 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ Generate Release Notes action is dedicated to enhance the quality and organizati
- **Required**: Yes

### `chapters`
- **Description**: A JSON string defining chapters and corresponding labels for categorization. Each chapter should have a title and a label matching your GitHub issues and PRs.
- **Description**: An YAML array defining chapters and corresponding labels for categorization. Each chapter should have a title and a label matching your GitHub issues and PRs.
- **Required**: Yes

### `row-format-issue`
Expand Down Expand Up @@ -140,12 +140,11 @@ Add the following step to your GitHub workflow (in example are used non-default
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag-name: "v0.1.0"
chapters: '[
{"title": "Breaking Changes 💥", "label": "breaking-change"},
{"title": "New Features 🎉", "label": "enhancement"},
{"title": "New Features 🎉", "label": "feature"},
{"title": "Bugfixes 🛠", "label": "bug"}
]'
chapters: |
- {"title": "Breaking Changes 💥", "label": "breaking-change"}
- {"title": "New Features 🎉", "label": "enhancement"}
- {"title": "New Features 🎉", "label": "feature"}
- {"title": "Bugfixes 🛠", "label": "bug"}
MobiTikula marked this conversation as resolved.
Show resolved Hide resolved
```

#### Full example
Expand All @@ -157,12 +156,12 @@ Add the following step to your GitHub workflow (in example are used non-default
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag-name: "v0.1.0"
chapters: '[
{"title": "Breaking Changes 💥", "label": "breaking-change"},
{"title": "New Features 🎉", "label": "enhancement"},
{"title": "New Features 🎉", "label": "feature"},
{"title": "Bugfixes 🛠", "label": "bug"}
]'
chapters: |
- {"title": "Breaking Changes 💥", "label": "breaking-change"}
- {"title": "New Features 🎉", "label": "enhancement"}
- {"title": "New Features 🎉", "label": "feature"}
- {"title": "Bugfixes 🛠", "label": "bug"}
MobiTikula marked this conversation as resolved.
Show resolved Hide resolved

duplicity-scope: 'service'
duplicity-icon: '🔁'
published-at: true
Expand Down Expand Up @@ -375,11 +374,16 @@ Create *.sh file and place it in the project root.

# Set environment variables based on the action inputs
export INPUT_TAG_NAME="v0.2.0"

export INPUT_CHAPTERS='[
{"title": "Breaking Changes 💥", "label": "breaking-change"},
{"title": "New Features 🎉", "label": "enhancement"},
{"title": "New Features 🎉", "label": "feature"},
{"title": "Bugfixes 🛠", "label": "bug"}
{ title: No entry 🚫, label: duplicate },
{ title: Breaking Changes 💥, label: breaking-change },
{ title: New Features 🎉, label: enhancement },
{ title: New Features 🎉, label: feature },
{ title: Bugfixes 🛠, label: bug },
{ title: Infrastructure ⚙️, label: infrastructure },
{ title: Silent-live 🤫, label: silent-live },
{ title: Documentation 📜, label: documentation }
]'
export INPUT_WARNINGS="true"
export INPUT_PUBLISHED_AT="true"
Expand Down
3 changes: 2 additions & 1 deletion action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@ inputs:
description: 'The tag name of the release to generate notes for.'
required: true
chapters:
description: 'JSON string defining chapters and corresponding labels for categorization.'
description: 'An string representation of YAML array defining chapters and corresponding labels for categorization. (Created by used "|".)'
required: false
default: ''
duplicity-scope:
description: 'Allow duplicity of issue lines in chapters. Scopes: custom, service, both, none.'
required: false
Expand Down
24 changes: 10 additions & 14 deletions examples/release_draft.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,20 +51,16 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag-name: ${{ github.event.inputs.tag-name }}
from-tag-name: ${{ github.event.inputs.from-tag-name }}
chapters: '[
{"title": "No entry 🚫", "label": "duplicate"},
{"title": "No entry 🚫", "label": "invalid"},
{"title": "No entry 🚫", "label": "wontfix"},
{"title": "No entry 🚫", "label": "no RN"},
{"title": "Breaking Changes 💥", "label": "breaking-change"},
{"title": "New Features 🎉", "label": "enhancement"},
{"title": "New Features 🎉", "label": "feature"},
{"title": "Bugfixes 🛠", "label": "bug"},
{"title": "Infrastructure ⚙️", "label": "infrastructure"},
{"title": "Silent-live 🤫", "label": "silent-live"},
{"title": "Documentation 📜", "label": "documentation"}
]'
chapters: |
- { title: No entry 🚫, label: duplicate }
- { title: Breaking Changes 💥, label: breaking-change }
- { title: New Features 🎉, label: enhancement }
- { title: New Features 🎉, label: feature }
- { title: Bugfixes 🛠, label: bug }
- { title: Infrastructure ⚙️, label: infrastructure }
- { title: Silent-live 🤫, label: silent-live }
- { title: Documentation 📜, label: documentation }
MobiTikula marked this conversation as resolved.
Show resolved Hide resolved

skip-release-notes-label: 'no RN'
verbose: true

Expand Down
4 changes: 2 additions & 2 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ def run() -> None:

ActionInputs.validate_inputs()
# Load custom chapters configuration
custom_chapters = CustomChapters(print_empty_chapters=ActionInputs.get_print_empty_chapters()).from_json(
ActionInputs.get_chapters_json()
custom_chapters = CustomChapters(print_empty_chapters=ActionInputs.get_print_empty_chapters()).from_yaml_array(
ActionInputs.get_chapters()
)

generator = ReleaseNotesGenerator(py_github, custom_chapters)
Expand Down
34 changes: 24 additions & 10 deletions release_notes_generator/action_inputs.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,15 @@
This module contains the ActionInputs class which is responsible for handling the inputs provided to the GH action.
"""

import json
import logging
import os
import sys
import re

MobiTikula marked this conversation as resolved.
Show resolved Hide resolved
from typing import Optional

MobiTikula marked this conversation as resolved.
Show resolved Hide resolved
import yaml

from release_notes_generator.utils.constants import (
GITHUB_REPOSITORY,
GITHUB_TOKEN,
Expand Down Expand Up @@ -98,11 +101,24 @@ def is_from_tag_name_defined() -> bool:
return value.strip() != ""

@staticmethod
def get_chapters_json() -> str:
def get_chapters() -> Optional[list[dict[str, str]]]:
"""
Get the chapters JSON from the action inputs.
Get list of the chapters from the action inputs. Each chapter is a dict.
"""
return get_action_input(CHAPTERS)
# Get the 'chapters' input from environment variables
chapters_input: str = get_action_input(CHAPTERS, default="")

# Parse the received string back to YAML array input.
try:
chapters = yaml.safe_load(chapters_input)
if not isinstance(chapters, list):
logger.error("Error: 'chapters' input is not a valid YAML list.")
return None
except yaml.YAMLError as exc:
logger.error("Error parsing 'chapters' input: {%s}", exc)
return None

return chapters

@staticmethod
def get_duplicity_scope() -> DuplicityScopeEnum:
Expand Down Expand Up @@ -243,11 +259,9 @@ def validate_inputs() -> None:
if not isinstance(from_tag_name, str):
errors.append("From tag name must be a string.")

chapters_json = ActionInputs.get_chapters_json()
try:
json.loads(chapters_json)
except json.JSONDecodeError:
errors.append("Chapters JSON must be a valid JSON string.")
chapters = ActionInputs.get_chapters()
if chapters is None:
errors.append("Chapters must be a valid yaml array.")

duplicity_icon = ActionInputs.get_duplicity_icon()
if not isinstance(duplicity_icon, str) or not duplicity_icon.strip() or len(duplicity_icon) != 1:
Expand Down Expand Up @@ -293,7 +307,7 @@ def validate_inputs() -> None:

logger.debug("Repository: %s/%s", owner, repo_name)
logger.debug("Tag name: %s", tag_name)
logger.debug("Chapters JSON: %s", chapters_json)
logger.debug("Chapters: %s", chapters)
logger.debug("Published at: %s", published_at)
logger.debug("Skip release notes labels: %s", ActionInputs.get_skip_release_notes_labels())
logger.debug("Verbose logging: %s", verbose)
Expand Down
13 changes: 5 additions & 8 deletions release_notes_generator/model/custom_chapters.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@
notes.
"""

import json

from release_notes_generator.action_inputs import ActionInputs
from release_notes_generator.model.base_chapters import BaseChapters
from release_notes_generator.model.chapter import Chapter
Expand Down Expand Up @@ -58,17 +56,16 @@ def populate(self, records: dict[int, Record]) -> None:
ch.add_row(nr, records[nr].to_chapter_row())
self.populated_record_numbers_list.append(nr)

def from_json(self, json_string: str) -> "CustomChapters":
def from_yaml_array(self, chapters: list[dict[str, str]]) -> "CustomChapters":
"""
Populates the custom chapters from a JSON string.

@param json_string: The JSON string containing the custom chapters.
@param chapters: A list of dictionaries where each dictionary represents a chapter.
@return: The instance of the CustomChapters class.
"""
data = json.loads(json_string)
for item in data:
title = item["title"]
labels = [item["label"]]
for chapter in chapters:
title = chapter["title"]
labels = [chapter["label"]]
if title not in self.chapters:
self.chapters[title] = Chapter(title, labels)
else:
Expand Down
2 changes: 1 addition & 1 deletion release_notes_generator/utils/pull_reuqest_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
#

"""
This module contains the PullRequestUtils class which is responsible for extracting information from pull requests.
This module contains the PullRequestRecord class which is responsible for representing a record in the release notes.
"""

import re
Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ PyGithub==1.59.0
pylint==3.2.6
requests==2.31.0
black==24.8.0
PyYAML==6.0.2
semver==3.0.2
9 changes: 4 additions & 5 deletions tests/release_notes/model/test_custom_chapters.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,17 +149,16 @@ def test_populate_none_duplicity_scope(custom_chapters, mocker):
# from_json


def test_custom_chapters_from_json():
def test_custom_chapters_from_yaml_array():
custom_chapters = CustomChapters()
json_string = """
[
yaml_array_in_string = [
{"title": "Breaking Changes 💥", "label": "breaking-change"},
{"title": "New Features 🎉", "label": "enhancement"},
{"title": "New Features 🎉", "label": "feature"},
{"title": "Bugfixes 🛠", "label": "bug"}
]
MobiTikula marked this conversation as resolved.
Show resolved Hide resolved
"""
custom_chapters.from_json(json_string)

custom_chapters.from_yaml_array(yaml_array_in_string)

assert "Breaking Changes 💥" in custom_chapters.titles
assert "New Features 🎉" in custom_chapters.titles
Expand Down
12 changes: 5 additions & 7 deletions tests/release_notes/test_release_notes_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,14 +78,12 @@ def __init__(self, name):


DEFAULT_CHANGELOG_URL = "http://example.com/changelog"
default_chapters_json = json.dumps(
[
default_chapters = [
{"title": "Breaking Changes 💥", "label": "breaking-change"},
{"title": "New Features 🎉", "label": "feature"},
{"title": "New Features 🎉", "label": "enhancement"},
{"title": "Bugfixes 🛠", "label": "bug"},
]
)

RELEASE_NOTES_NO_DATA = """### Breaking Changes 💥
No entries detected.
Expand Down Expand Up @@ -302,7 +300,7 @@ def __init__(self, name):

def test_build_no_data():
custom_chapters = CustomChapters()
custom_chapters.from_json(default_chapters_json)
custom_chapters.from_yaml_array(default_chapters)

expected_release_notes = RELEASE_NOTES_NO_DATA

Expand All @@ -318,7 +316,7 @@ def test_build_no_data():

def test_build_no_data_no_warnings(mocker):
custom_chapters = CustomChapters()
custom_chapters.from_json(default_chapters_json)
custom_chapters.from_yaml_array(default_chapters)
mocker.patch("release_notes_generator.builder.ActionInputs.get_warnings", return_value=False)

expected_release_notes = RELEASE_NOTES_NO_DATA_NO_WARNING
Expand All @@ -335,7 +333,7 @@ def test_build_no_data_no_warnings(mocker):

def test_build_no_data_no_warnings_no_empty_chapters(mocker):
custom_chapters_no_empty_chapters = CustomChapters()
custom_chapters_no_empty_chapters.from_json(default_chapters_json)
custom_chapters_no_empty_chapters.from_yaml_array(default_chapters)
custom_chapters_no_empty_chapters.print_empty_chapters = False
mocker.patch("release_notes_generator.builder.ActionInputs.get_warnings", return_value=False)
mocker.patch("release_notes_generator.builder.ActionInputs.get_print_empty_chapters", return_value=False)
Expand All @@ -354,7 +352,7 @@ def test_build_no_data_no_warnings_no_empty_chapters(mocker):

def test_build_no_data_no_empty_chapters(mocker):
custom_chapters_no_empty_chapters = CustomChapters()
custom_chapters_no_empty_chapters.from_json(default_chapters_json)
custom_chapters_no_empty_chapters.from_yaml_array(default_chapters)
custom_chapters_no_empty_chapters.print_empty_chapters = False
mocker.patch("release_notes_generator.builder.ActionInputs.get_print_empty_chapters", return_value=False)

Expand Down
21 changes: 15 additions & 6 deletions tests/test_action_inputs.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@
success_case = {
"get_github_repository": "owner/repo_name",
"get_tag_name": "tag_name",
"get_from_tag_name": "from_tag_name",
"get_chapters_json": '{"chapter": "content"}',
"get_chapters": [{"title": "Title", "label": "Label"}],
"get_duplicity_scope": "custom",
"get_duplicity_icon": "🔁",
"get_warnings": True,
Expand All @@ -40,7 +39,7 @@
("get_github_repository", "owner/", "Owner and Repo must be a non-empty string."),
("get_tag_name", "", "Tag name must be a non-empty string."),
("get_from_tag_name", 1, "From tag name must be a string."),
("get_chapters_json", "invalid_json", "Chapters JSON must be a valid JSON string."),
("get_chapters", None, "Chapters must be a valid yaml array."),
("get_warnings", "not_bool", "Warnings must be a boolean."),
("get_published_at", "not_bool", "Published at must be a boolean."),
("get_print_empty_chapters", "not_bool", "Print empty chapters must be a boolean."),
Expand Down Expand Up @@ -108,9 +107,19 @@ def test_get_tag_name(mocker):
assert ActionInputs.get_tag_name() == "v1.0.0"


def test_get_chapters_json(mocker):
mocker.patch("release_notes_generator.action_inputs.get_action_input", return_value='{"chapters": []}')
assert ActionInputs.get_chapters_json() == '{"chapters": []}'
def test_get_chapters_success(mocker):
mocker.patch("release_notes_generator.action_inputs.get_action_input", return_value="[{\"title\": \"Title\", \"label\": \"Label\"}]")
assert ActionInputs.get_chapters() == [{"title": "Title", "label": "Label"}]


def test_get_chapters_exception(mocker):
mocker.patch("release_notes_generator.action_inputs.get_action_input", return_value="wrong value")
assert None == ActionInputs.get_chapters()


def test_get_chapters_yaml_error(mocker):
mocker.patch("release_notes_generator.action_inputs.get_action_input", return_value="[{\"title\": \"Title\" \"label\": \"Label\"}]")
assert None == ActionInputs.get_chapters()


def test_get_warnings(mocker):
Expand Down
Loading