Skip to content

Commit 958877a

Browse files
Feature/165 introduce regimes prepare default one (#166)
* #165 - Introduce regimes - prepare default one - Implemented default regime.
1 parent ed943b5 commit 958877a

File tree

13 files changed

+376
-243
lines changed

13 files changed

+376
-243
lines changed

README.md

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
- [Motivation](#motivation)
44
- [Requirements](#requirements)
55
- [Inputs](#inputs)
6+
- [Feature controls](#feature-controls)
7+
- [Regimes](#regimes)
68
- [Outputs](#outputs)
79
- [Usage Example](#usage-example)
810
- [Features](#features)
@@ -40,24 +42,25 @@ Generate Release Notes action is dedicated to enhance the quality and organizati
4042

4143
## Inputs
4244

43-
| Name | Description | Required | Default |
44-
|----------------|-----------------------------------------------------------------------------------------------------------------------------|----------|-----------------------------------------|
45-
| `GITHUB_TOKEN` | Your GitHub token for authentication. Store it as a secret and reference it in the workflow file as secrets.GITHUB_TOKEN. | Yes | |
46-
| `tag-name` | The name of the tag for which you want to generate release notes. This should be the same as the tag name used in the release workflow. | Yes | |
47-
| `from-tag-name` | The name of the tag from which you want to generate release notes. | No | '' |
48-
| `chapters` | 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. | Yes | |
49-
| `row-format-issue` | The format of the row for the issue in the release notes. The format can contain placeholders for the issue `number`, `title`, and issues `pull-requests`. The placeholders are case-sensitive. | No | `"{number} _{title}_ in {pull-requests}"` |
50-
| `row-format-pr` | The format of the row for the PR in the release notes. The format can contain placeholders for the PR `number`, and `title`. The placeholders are case-sensitive. | No | `"{number} _{title}_"` |
51-
| `row-format-link-pr` | If defined `true`, the PR row will begin with a `"PR: "` string. Otherwise, no prefix will be added. | No | true |
52-
| `duplicity-scope` | Set to `custom` to allow duplicity issue lines to be shown only in custom chapters. Options: `custom`, `service`, `both`, `none`. | No | `both` |
53-
| `duplicity-icon` | The icon used to indicate duplicity issue lines in the release notes. Icon will be placed at the beginning of the line. | No | `🔔` |
54-
| `published-at` | Set to true to enable the use of the `published-at` timestamp as the reference point for searching closed issues and PRs, instead of the `created-at` date of the latest release. If first release, repository creation date is used. | No | false |
55-
| `skip-release-notes-labels` | List labels used for detection if issues or pull requests are ignored in the Release Notes generation process. Example: `skip-release-notes, question`. | No | `skip-release-notes` |
56-
| `verbose` | Set to true to enable verbose logging for detailed output during the action's execution. | No | false |
57-
| `release-notes-title` | The title of the release notes section in the PR description. | No | `[Rr]elease [Nn]otes:` |
58-
| `coderabbit-support-active` | Enable CodeRabbit support. If true, the action will use CodeRabbit to generate release notes. | No | false |
59-
| `coderabbit-release-notes-title` | The title of the CodeRabbit summary in the PR body. Value supports regex. | No | `Summary by CodeRabbit` |
60-
| `coderabbit-summary-ignore-groups` | List of "group names" to be ignored by release notes detection logic. Example: `Documentation, Tests, Chores, Bug Fixes`. | No | '' |
45+
| Name | Description | Required | Default |
46+
|------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------|-------------------------------------------|
47+
| `GITHUB_TOKEN` | Your GitHub token for authentication. Store it as a secret and reference it in the workflow file as secrets.GITHUB_TOKEN. | Yes | |
48+
| `tag-name` | The name of the tag for which you want to generate release notes. This should be the same as the tag name used in the release workflow. | Yes | |
49+
| `from-tag-name` | The name of the tag from which you want to generate release notes. | No | '' |
50+
| `chapters` | 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. | Yes | |
51+
| `regime` | Controls the regime of the action. Options: `default`. See more about the [Regimes](#regimes). | No | `default` |
52+
| `row-format-issue` | The format of the row for the issue in the release notes. The format can contain placeholders for the issue `number`, `title`, and issues `pull-requests`. The placeholders are case-sensitive. | No | `"{number} _{title}_ in {pull-requests}"` |
53+
| `row-format-pr` | The format of the row for the PR in the release notes. The format can contain placeholders for the PR `number`, and `title`. The placeholders are case-sensitive. | No | `"{number} _{title}_"` |
54+
| `row-format-link-pr` | If defined `true`, the PR row will begin with a `"PR: "` string. Otherwise, no prefix will be added. | No | true |
55+
| `duplicity-scope` | Set to `custom` to allow duplicity issue lines to be shown only in custom chapters. Options: `custom`, `service`, `both`, `none`. | No | `both` |
56+
| `duplicity-icon` | The icon used to indicate duplicity issue lines in the release notes. Icon will be placed at the beginning of the line. | No | `🔔` |
57+
| `published-at` | Set to true to enable the use of the `published-at` timestamp as the reference point for searching closed issues and PRs, instead of the `created-at` date of the latest release. If first release, repository creation date is used. | No | false |
58+
| `skip-release-notes-labels` | List labels used for detection if issues or pull requests are ignored in the Release Notes generation process. Example: `skip-release-notes, question`. | No | `skip-release-notes` |
59+
| `verbose` | Set to true to enable verbose logging for detailed output during the action's execution. | No | false |
60+
| `release-notes-title` | The title of the release notes section in the PR description. | No | `[Rr]elease [Nn]otes:` |
61+
| `coderabbit-support-active` | Enable CodeRabbit support. If true, the action will use CodeRabbit to generate release notes. | No | false |
62+
| `coderabbit-release-notes-title` | The title of the CodeRabbit summary in the PR body. Value supports regex. | No | `Summary by CodeRabbit` |
63+
| `coderabbit-summary-ignore-groups` | List of "group names" to be ignored by release notes detection logic. Example: `Documentation, Tests, Chores, Bug Fixes`. | No | '' |
6164

6265
> **Notes**
6366
> - `skip-release-notes-labels`
@@ -78,6 +81,20 @@ Generate Release Notes action is dedicated to enhance the quality and organizati
7881
> - `warnings`
7982
> - **Disabling this feature will hide service chapter showing direct commits!** These cannot be visible in custom chapters as they do not have labels!
8083
84+
### Regimes
85+
86+
### Default regime
87+
88+
The basic regime for this action.
89+
90+
- **Data management**
91+
- The issue type is not used. It can lead to placing Epic and other issues without linked PR into service chapters. If you need to use issue type use another regime.
92+
- **Release notes**
93+
- Organized by custom chapters defined by user using labels.
94+
- Used these `types of rows`:
95+
- Issue with/without linked Pull Request(s).
96+
- Pull Request without linked Issue.
97+
- Direct commits (without Issue and Pull Request).
8198

8299
## Outputs
83100
The output of the action is a markdown string containing the release notes for the specified tag. This string can be used in subsequent steps to publish the release notes to a file, create a GitHub release, or send notifications.

action.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ inputs:
3232
description: 'The tag name of the previous release to use as a start reference point for the current release notes.'
3333
required: false
3434
default: ''
35+
regime:
36+
description: 'Regime of the release notes generation. Options: default.'
37+
required: false
38+
default: 'default'
3539
duplicity-icon:
3640
description: 'Icon to be used for duplicity warning. Icon is placed before the record line.'
3741
required: false
@@ -133,6 +137,7 @@ runs:
133137
INPUT_TAG_NAME: ${{ inputs.tag-name }}
134138
INPUT_CHAPTERS: ${{ inputs.chapters }}
135139
INPUT_FROM_TAG_NAME: ${{ inputs.from-tag-name }}
140+
INPUT_REGIME: ${{ inputs.regime }}
136141
INPUT_DUPLICITY_SCOPE: ${{ inputs.duplicity-scope }}
137142
INPUT_DUPLICITY_ICON: ${{ inputs.duplicity-icon }}
138143
INPUT_WARNINGS: ${{ inputs.warnings }}

release_notes_generator/action_inputs.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ class ActionInputs:
6363
A class representing the inputs provided to the GH action.
6464
"""
6565

66+
REGIME_DEFAULT = "default"
67+
6668
_row_format_issue = None
6769
_row_format_pr = None
6870
_row_format_link_pr = None
@@ -160,6 +162,13 @@ def get_chapters() -> list[dict[str, str]]:
160162

161163
return chapters
162164

165+
@staticmethod
166+
def get_regime() -> str:
167+
"""
168+
Get the regime parameter value from the action inputs.
169+
"""
170+
return get_action_input("regime", "default") # type: ignore[return-value] # default defined
171+
163172
@staticmethod
164173
def get_duplicity_scope() -> DuplicityScopeEnum:
165174
"""
@@ -365,6 +374,11 @@ def validate_inputs() -> None:
365374
if not isinstance(duplicity_icon, str) or not duplicity_icon.strip() or len(duplicity_icon) != 1:
366375
errors.append("Duplicity icon must be a non-empty string and have a length of 1.")
367376

377+
regime = ActionInputs.get_regime()
378+
ActionInputs.validate_input(regime, str, "Regime must be a string.", errors)
379+
if regime not in [ActionInputs.REGIME_DEFAULT]:
380+
errors.append(f"Regime '{regime}' is not supported.")
381+
368382
warnings = ActionInputs.get_warnings()
369383
ActionInputs.validate_input(warnings, bool, "Warnings must be a boolean.", errors)
370384

@@ -421,6 +435,7 @@ def validate_inputs() -> None:
421435
logger.debug("Tag name: %s", tag_name)
422436
logger.debug("From tag name: %s", from_tag_name)
423437
logger.debug("Chapters: %s", chapters)
438+
logger.debug("Regime: %s", regime)
424439
logger.debug("Published at: %s", published_at)
425440
logger.debug("Skip release notes labels: %s", ActionInputs.get_skip_release_notes_labels())
426441
logger.debug("Verbose logging: %s", verbose)

release_notes_generator/builder/__init__.py

Whitespace-only changes.
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#
2+
# Copyright 2023 ABSA Group Limited
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
#
16+
17+
"""
18+
This module contains the ReleaseNotesBuilder class which is responsible for building of the release notes.
19+
"""
20+
from abc import ABCMeta, abstractmethod
21+
22+
from release_notes_generator.action_inputs import ActionInputs
23+
from release_notes_generator.model.custom_chapters import CustomChapters
24+
from release_notes_generator.model.record import Record
25+
26+
27+
class ReleaseNotesBuilder(metaclass=ABCMeta):
28+
"""
29+
A class representing the Release Notes Builder.
30+
The class is responsible for building the release notes based on the records, changelog URL, formatter, and custom
31+
chapters.
32+
"""
33+
34+
def __init__(
35+
self,
36+
records: dict[int | str, Record],
37+
changelog_url: str,
38+
custom_chapters: CustomChapters,
39+
):
40+
self.records = records
41+
self.changelog_url = changelog_url
42+
self.custom_chapters = custom_chapters
43+
44+
self.warnings = ActionInputs.get_warnings()
45+
self.print_empty_chapters = ActionInputs.get_print_empty_chapters()
46+
47+
@abstractmethod
48+
def build(self) -> str:
49+
"""
50+
Build the release notes based on the records, changelog URL, formatter, and custom chapters.
51+
52+
@return: The release notes as a string.
53+
"""

release_notes_generator/builder.py renamed to release_notes_generator/builder/default_builder.py

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -21,34 +21,19 @@
2121
import logging
2222
from itertools import chain
2323

24-
from release_notes_generator.model.custom_chapters import CustomChapters
25-
from release_notes_generator.model.record import Record
24+
from release_notes_generator.builder.base_builder import ReleaseNotesBuilder
2625
from release_notes_generator.model.service_chapters import ServiceChapters
27-
from release_notes_generator.action_inputs import ActionInputs
2826

2927
logger = logging.getLogger(__name__)
3028

3129

32-
class ReleaseNotesBuilder:
30+
class DefaultReleaseNotesBuilder(ReleaseNotesBuilder):
3331
"""
3432
A class representing the Release Notes Builder.
3533
The class is responsible for building the release notes based on the records, changelog URL, formatter, and custom
3634
chapters.
3735
"""
3836

39-
def __init__(
40-
self,
41-
records: dict[int | str, Record],
42-
changelog_url: str,
43-
custom_chapters: CustomChapters,
44-
):
45-
self.records = records
46-
self.changelog_url = changelog_url
47-
self.custom_chapters = custom_chapters
48-
49-
self.warnings = ActionInputs.get_warnings()
50-
self.print_empty_chapters = ActionInputs.get_print_empty_chapters()
51-
5237
def build(self) -> str:
5338
"""
5439
Build the release notes based on the records, changelog URL, formatter, and custom chapters.

release_notes_generator/generator.py

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,11 @@
2828
from release_notes_generator.filter import FilterByRelease
2929
from release_notes_generator.miner import DataMiner
3030
from release_notes_generator.action_inputs import ActionInputs
31-
from release_notes_generator.builder import ReleaseNotesBuilder
31+
from release_notes_generator.builder.base_builder import ReleaseNotesBuilder
32+
from release_notes_generator.builder.default_builder import DefaultReleaseNotesBuilder
3233
from release_notes_generator.model.custom_chapters import CustomChapters
3334
from release_notes_generator.model.record import Record
35+
from release_notes_generator.record.default_record_factory import DefaultRecordFactory
3436
from release_notes_generator.record.record_factory import RecordFactory
3537
from release_notes_generator.utils.github_rate_limiter import GithubRateLimiter
3638
from release_notes_generator.utils.utils import get_change_url
@@ -90,14 +92,25 @@ def generate(self) -> Optional[str]:
9092

9193
assert data_filtered_by_release.repository is not None, "Repository must not be None"
9294

93-
rls_notes_records: dict[int | str, Record] = RecordFactory.generate(
95+
# get record factory instance in dependency on selected regime
96+
record_factory: RecordFactory = DefaultRecordFactory()
97+
# This is a placeholder for future regimes - will be added in following issue
98+
# match ActionInputs.get_regime():
99+
# case "TODO":
100+
# record_factory = TBD
101+
102+
rls_notes_records: dict[int | str, Record] = record_factory.generate(
94103
github=self._github_instance, data=data_filtered_by_release
95104
)
96105

97-
release_notes_builder = ReleaseNotesBuilder(
98-
records=rls_notes_records,
99-
custom_chapters=self.custom_chapters,
106+
return self._get_rls_notes_builder(rls_notes_records, changelog_url, self.custom_chapters).build()
107+
108+
def _get_rls_notes_builder(
109+
self, records: dict[int | str, Record], changelog_url: str, custom_chapters: CustomChapters
110+
) -> ReleaseNotesBuilder:
111+
112+
return DefaultReleaseNotesBuilder(
113+
records=records,
114+
custom_chapters=custom_chapters,
100115
changelog_url=changelog_url,
101116
)
102-
103-
return release_notes_builder.build()

0 commit comments

Comments
 (0)