Skip to content

Commit 5d8c769

Browse files
Feature/141 add support for coderabbit summary in pr description (#144)
* #141 - Add support for coderabbit summary in PR description - Added support for coderabbit Summary as a source for Release Notes.
1 parent 3129da4 commit 5d8c769

File tree

8 files changed

+316
-118
lines changed

8 files changed

+316
-118
lines changed

.github/workflows/release_draft.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,17 @@ jobs:
6767
tag-name: ${{ github.event.inputs.tag-name }}
6868
chapters: |
6969
- { title: No entry 🚫, label: duplicate }
70+
- { title: No entry 🚫, label: no RN }
7071
- { title: Breaking Changes 💥, label: breaking-change }
7172
- { title: New Features 🎉, label: enhancement }
7273
- { title: New Features 🎉, label: feature }
7374
- { title: Bugfixes 🛠, label: bug }
7475
- { title: Infrastructure ⚙️, label: infrastructure }
7576
- { title: Silent-live 🤫, label: silent-live }
7677
- { title: Documentation 📜, label: documentation }
78+
coderabbit-support-active: 'true'
79+
coderabbit-release-notes-title: 'Summary by CodeRabbit'
80+
coderabbit-summary-ignore-groups: 'Documentation, Tests, Chores, Bug Fixes, Refactor'
7781

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

README.md

Lines changed: 80 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -39,84 +39,40 @@ Generate Release Notes action is dedicated to enhance the quality and organizati
3939
- **Python 3.11+**: Ensure you have Python 3.11 installed on your system.
4040

4141
## Inputs
42-
### `GITHUB_TOKEN`
43-
- **Description**: Your GitHub token for authentication. Store it as a secret and reference it in the workflow file as secrets.GITHUB_TOKEN.
44-
- **Required**: Yes
45-
46-
### `tag-name`
47-
- **Description**: 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.
48-
- **Required**: Yes
49-
50-
### `from-tag-name`
51-
- **Description**: The name of the tag from which you want to generate release notes.
52-
- **Required**: No
53-
- **Default**: ``
54-
55-
### `chapters`
56-
- **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.
57-
- **Required**: Yes
58-
59-
### `row-format-issue`
60-
- **Description**: 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.
61-
- **Required**: No
62-
- **Default**: `"{number} _{title}_ in {pull-requests}"`
63-
64-
### `row-format-pr`
65-
- **Description**: 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.
66-
- **Required**: No
67-
- **Default**: `"{number} _{title}_"`
68-
69-
### `row-format-link-pr`
70-
- **Description**: If defined `true`, the PR row will begin with a `"PR: "` string. Otherwise, no prefix will be added.
71-
- **Required**: No
72-
- **Default**: true
73-
74-
### `duplicity-scope`
75-
- **Description**: Set to `custom` to allow duplicity issue lines to be shown only in custom chapters. Options: `custom`, `service`, `both`, `none`.
76-
- **Required**: No
77-
- **Default**: `both`
78-
79-
### `duplicity-icon`
80-
- **Description**: The icon used to indicate duplicity issue lines in the release notes. Icon will be placed at the beginning of the line.
81-
- **Required**: No
82-
- **Default**: `🔔`
83-
84-
### `published-at`
85-
- **Description**: 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.
86-
- **Required**: No
87-
- **Default**: false
88-
89-
### `skip-release-notes-labels`
90-
- **Description**: List labels used for detection if issues or pull requests are ignored in the Release Notes generation process. Example: `skip-release-notes, question`.
91-
- **Required**: No
92-
- **Default**: `skip-release-notes`
93-
- Notes:
94-
- If used on issue then Issue will be skipped during Release Notes generation.
95-
- If used on PR with issue then on PR it will be ignored and PR will show as part of issue's release notes.
96-
- If used on PR without issue then PR will be skipped during Release Notes generation.
97-
98-
### `verbose`
99-
- **Description**: Set to true to enable verbose logging for detailed output during the action's execution.
100-
- **Required**: No
101-
- **Default**: false
102-
- **Note**: If workflow run in debug regime, 'verbose' logging is activated.
103-
104-
### `release-notes-title`
105-
- **Description**: The title of the release notes section in the PR description.
106-
- **Required**: No
107-
- **Default**: `[Rr]elease [Nn]otes:`
10842

109-
### Feature controls
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 | '' |
61+
62+
> **Notes**
63+
> - `skip-release-notes-labels`
64+
> - If used on issue then Issue will be skipped during Release Notes generation.
65+
> - If used on PR with issue then on PR it will be ignored and PR will show as part of issue's release notes.
66+
> - If used on PR without issue then PR will be skipped during Release Notes generation.
67+
> - `verbose`
68+
> - If workflow run in debug regime, 'verbose' logging is activated.
11069
111-
### `warnings`
112-
- **Description**: Set to true to print service chapters in the release notes. These warnings identify issues without release notes, without user-defined labels, or without associated pull requests, and PRs without linked issues.
113-
- **Required**: No
114-
- **Default**: true (Service chapters are printed.)
70+
### Feature controls
11571

116-
### `print-empty-chapters`
117-
- **Description**: Set it to true to print chapters with no issues or PRs.
118-
- **Required**: No
119-
- **Default**: true (Empty chapters are printed.)
72+
| Name | Description | Required | Default |
73+
|----------------|-----------------------------------------------------------------------------------------------------------------------------|----------|--------------------------------------|
74+
| `warnings` | Set to true to print service chapters in the release notes. These warnings identify issues without release notes, without user-defined labels, or without associated pull requests, and PRs without linked issues. | No | true (Service chapters are printed.) |
75+
| `print-empty-chapters` | Set it to true to print chapters with no issues or PRs. | No | true (Empty chapters are printed.) |
12076

12177
## Outputs
12278
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.
@@ -154,7 +110,7 @@ Add the following step to your GitHub workflow (in example are used non-default
154110
```yaml
155111
- name: Generate Release Notes
156112
id: release_notes_generator
157-
uses: AbsaOSS/generate-release-notes@v0.2.0
113+
uses: AbsaOSS/generate-release-notes@v0.7.0
158114
env:
159115
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
160116
with:
@@ -173,38 +129,74 @@ Add the following step to your GitHub workflow (in example are used non-default
173129
verbose: false
174130
release-notes-title: '[Rr]elease Notes:'
175131

132+
coderabbit-support-active: true
133+
coderabbit-release-notes-title: 'Summary by CodeRabbit'
134+
coderabbit-summary-ignore-groups: 'Documentation, Tests, Chores, Bug Fixes, Refactor'
135+
176136
warnings: false
177137
print-empty-chapters: false
178138
```
179139
180140
## Features
181141
### Built-in
182142
#### Release Notes Extraction Process
183-
This feature searches for release notes in the description of GitHub pull requests, making it easier for maintainers to track changes and updates.
184-
- **Format:**
185-
- The release notes section have to begin with the title `Release Notes:` (case-sensitive), followed by the release notes in bullet points. [Markdown formatting is supported](https://www.markdownguide.org/basic-syntax/#unordered-lists).
186-
- If no release notes line is detected under the `Release Notes:` title, no release notes will be printed in the output.
143+
144+
This feature automatically extracts release notes from GitHub pull request descriptions to help maintainers track meaningful changes.
145+
146+
##### 🔍 How Detection Works
147+
148+
- The Action looks for a specific section in the PR body, defined by:
149+
- `release-notes-title`: A regex pattern to match the release notes section header.
150+
- `coderabbit-support-active`: Enables fallback support for CodeRabbit summaries.
151+
- ✅ _Used only if no section matching `release-notes-title` is found._
152+
153+
##### 📏 Detection Rules
154+
- The release notes section:
155+
- Can be **anywhere in the PR body**
156+
- Must begin with a header that matches either:
157+
- `release-notes-title`
158+
- or `coderabbit-release-notes-title` (when CodeRabbit support is active)
159+
- Supports [Markdown formatting](https://www.markdownguide.org/basic-syntax/#unordered-lists)
160+
- Only the **first matching section** is extracted
161+
- Is **optional** – the Action will still proceed even if no notes are found
162+
- Will be **skipped silently** if the PR has a label listed in `skip-release-notes-labels`
163+
164+
> 🔕 If no valid section is found, the output Release Notes record will not contain any release notes.
165+
187166
- **Example:**
188167
- Here are examples of how to structure the release notes:
189-
```
190-
Release Notes:
168+
169+
```markdown
170+
## Release Notes:
191171
- This update introduces a new caching mechanism that improves performance by 20%.
192172
- The caching mechanism reduces database queries.
193173
- Optimized for high-traffic scenarios.
194174
- Includes support for distributed caching.
195175
196-
Release Notes:
176+
## Release Notes:
197177
* This update introduces a new caching mechanism that improves performance by 20%.
198178
* Affected only specific edge cases.
199179
200-
Release Notes:
180+
## Release Notes:
201181
+ This update introduces a new caching mechanism that improves performance by 20%.
202182
203-
```
204-
The extraction process supports all three types of bullet points: `-`, `*`, and `+`, and their combinations. (GitHub documentation do not recommend to mix them.)
183+
## Summary by CodeRabbit
205184
206-
- **Best Practice:** Select one character from `-`, `*`, `+` for bullet points. The Markdown parser will automatically format them as a list.
207-
- **Optional usage:** The release notes section is not mandatory for GH action to work.
185+
- **New Features**
186+
- Introduced a new feature.
187+
188+
- **Documentation**
189+
- Added new descriptions.
190+
191+
- **Chores**
192+
- Added configuration files for code style.
193+
194+
- **Tests**
195+
- Introduced a complete test suite for all classes.
196+
```
197+
> The extraction process supports all three types of bullet points: `-`, `*`, and `+`, and their combinations. (GitHub documentation do not recommend to mix them.)
198+
>
199+
> **Best Practice:** Select one character from `-`, `*`, `+` for bullet points. The Markdown parser will automatically format them as a list.
208200

209201
#### Handling Multiple PRs
210202
If an issue is linked to multiple PRs, the action fetches and aggregates contributions from all linked PRs.

action.yml

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ inputs:
2121
description: 'The tag name of the release to generate notes for.'
2222
required: true
2323
chapters:
24-
description: 'An string representation of YAML array defining chapters and corresponding labels for categorization. (Created by used "|".)'
24+
description: 'A string representation of a YAML array defining chapters and corresponding labels for categorization. (Created by used "|".)'
2525
required: false
2626
default: ''
2727
duplicity-scope:
@@ -60,6 +60,18 @@ inputs:
6060
description: 'The title of the release notes section in the PR body. Value supports regex.'
6161
required: false
6262
default: '[Rr]elease [Nn]otes:'
63+
coderabbit-support-active:
64+
description: 'Enable CodeRabbit support. If true, the action will use CodeRabbit to generate release notes.'
65+
required: false
66+
default: 'false'
67+
coderabbit-release-notes-title:
68+
description: 'The title of the CodeRabbit summary in the PR body. Value supports regex.'
69+
required: false
70+
default: 'Summary by CodeRabbit'
71+
coderabbit-summary-ignore-groups:
72+
description: 'List of "group names" to be ignored by release notes detection logic.'
73+
required: false
74+
default: ''
6375
row-format-issue:
6476
description: 'Format of the issue row in the release notes. Available placeholders: {number}, {title}, {pull-requests}. Placeholders are case-insensitive.'
6577
required: false
@@ -129,6 +141,9 @@ runs:
129141
INPUT_PRINT_EMPTY_CHAPTERS: ${{ inputs.print-empty-chapters }}
130142
INPUT_VERBOSE: ${{ inputs.verbose }}
131143
INPUT_RELEASE_NOTES_TITLE: ${{ inputs.release-notes-title }}
144+
INPUT_CODERABBIT_SUPPORT_ACTIVE: ${{ inputs.coderabbit-support-active }}
145+
INPUT_CODERABBIT_RELEASE_NOTES_TITLE: ${{ inputs.coderabbit-release-notes-title }}
146+
INPUT_CODERABBIT_SUMARY_IGNORE_GROUPS: ${{ inputs.coderabbit-summary-ignore-groups }}
132147
INPUT_GITHUB_REPOSITORY: ${{ github.repository }}
133148
INPUT_ROW_FORMAT_ISSUE: ${{ inputs.row-format-issue }}
134149
INPUT_ROW_FORMAT_PR: ${{ inputs.row-format-pr }}

release_notes_generator/action_inputs.py

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,18 @@
4545
RELEASE_NOTE_TITLE_DEFAULT,
4646
SUPPORTED_ROW_FORMAT_KEYS,
4747
FROM_TAG_NAME,
48+
CODERABBIT_SUPPORT_ACTIVE,
49+
CODERABBIT_RELEASE_NOTES_TITLE,
50+
CODERABBIT_RELEASE_NOTE_TITLE_DEFAULT,
51+
CODERABBIT_SUMMARY_IGNORE_GROUPS,
4852
)
4953
from release_notes_generator.utils.enums import DuplicityScopeEnum
5054
from release_notes_generator.utils.gh_action import get_action_input
5155

5256
logger = logging.getLogger(__name__)
5357

5458

55-
# pylint: disable=too-many-branches, too-many-statements, too-many-locals
59+
# pylint: disable=too-many-branches, too-many-statements, too-many-locals, too-many-public-methods
5660
class ActionInputs:
5761
"""
5862
A class representing the inputs provided to the GH action.
@@ -178,6 +182,38 @@ def get_release_notes_title() -> str:
178182
return get_action_input(RELEASE_NOTES_TITLE, RELEASE_NOTE_TITLE_DEFAULT) # type: ignore[return-value]
179183
# mypy: string is returned as default
180184

185+
@staticmethod
186+
def is_coderabbit_support_active() -> bool:
187+
"""
188+
Get the CodeRabbit support active parameter value from the action inputs.
189+
"""
190+
return get_action_input(CODERABBIT_SUPPORT_ACTIVE, "false").lower() == "true" # type: ignore[union-attr]
191+
192+
@staticmethod
193+
def get_coderabbit_release_notes_title() -> str:
194+
"""
195+
Get the CodeRabbit release notes title from the action inputs.
196+
"""
197+
return get_action_input(CODERABBIT_RELEASE_NOTES_TITLE, CODERABBIT_RELEASE_NOTE_TITLE_DEFAULT) # type: ignore[return-value]
198+
199+
@staticmethod
200+
def get_coderabbit_summary_ignore_groups() -> list[str]:
201+
"""
202+
Get the CodeRabbit summary title types to ignore.
203+
"""
204+
ignore_groups: list[str] = []
205+
raw = get_action_input(CODERABBIT_SUMMARY_IGNORE_GROUPS, "")
206+
if not isinstance(raw, str):
207+
logger.error("Error: 'coderabbit_summary_ignore_groups' is not a valid string.")
208+
return ignore_groups
209+
210+
titles = raw.strip()
211+
if titles:
212+
separator = "," if "," in titles else "\n"
213+
ignore_groups = [title.strip() for title in titles.split(separator)]
214+
215+
return ignore_groups
216+
181217
# Features
182218
@staticmethod
183219
def get_warnings() -> bool:
@@ -298,6 +334,20 @@ def validate_inputs() -> None:
298334
if not isinstance(release_notes_title, str) or len(release_notes_title) == 0:
299335
errors.append("Release Notes title must be a non-empty string and have non-zero length.")
300336

337+
coderabbit_support_active = ActionInputs.is_coderabbit_support_active()
338+
coderabbit_release_notes_title = ActionInputs.get_coderabbit_release_notes_title()
339+
coderabbit_summary_ignore_groups = ActionInputs.get_coderabbit_summary_ignore_groups()
340+
341+
if coderabbit_support_active:
342+
if not isinstance(coderabbit_release_notes_title, str) or len(coderabbit_release_notes_title) == 0:
343+
errors.append("CodeRabbit Release Notes title must be a non-empty string and have non-zero length.")
344+
345+
for group in coderabbit_summary_ignore_groups:
346+
if not isinstance(group, str) or len(group) == 0:
347+
errors.append(
348+
"CodeRabbit summary ignore groups must be a non-empty string and have non-zero length."
349+
)
350+
301351
row_format_issue = ActionInputs.get_row_format_issue()
302352
if not isinstance(row_format_issue, str) or not row_format_issue.strip():
303353
errors.append("Issue row format must be a non-empty string.")
@@ -332,6 +382,9 @@ def validate_inputs() -> None:
332382
logger.debug("Warnings: %s", warnings)
333383
logger.debug("Print empty chapters: %s", print_empty_chapters)
334384
logger.debug("Release notes title: %s", release_notes_title)
385+
logger.debug("CodeRabbit support active: %s", coderabbit_support_active)
386+
logger.debug("CodeRabbit release notes title: %s", coderabbit_release_notes_title)
387+
logger.debug("CodeRabbit summary ignore groups: %s", coderabbit_summary_ignore_groups)
335388

336389
@staticmethod
337390
def _detect_row_format_invalid_keywords(row_format: str, row_type: str = "Issue", clean: bool = False) -> str:

0 commit comments

Comments
 (0)