Skip to content

Fature/99 super chapters#281

Merged
miroslavpojer merged 26 commits intomasterfrom
fature/99-Super-chapters
Apr 8, 2026
Merged

Fature/99 super chapters#281
miroslavpojer merged 26 commits intomasterfrom
fature/99-Super-chapters

Conversation

@miroslavpojer
Copy link
Copy Markdown
Collaborator

@miroslavpojer miroslavpojer commented Apr 2, 2026

Overview

Adds super-chapters as a new optional input that lets users group existing custom chapters under top-level ## headings in the release notes output.

Previously, all custom chapters rendered as flat ### headings. With super chapters, users can declare label-based groupings (e.g. "Module A", "Module B") that wrap the matching records under a ## heading, with the regular chapter titles nested as ### inside. Records not matched by any super chapter fall through to an ## Uncategorized section.

Key changes:

  • ActionInputs.get_super_chapters() parses the new super-chapters YAML input (mirrors get_chapters() pattern)
  • CustomChapters._to_string_with_super_chapters() refactored into focused helpers and extended with an uncategorized fallback
  • _record_labels now tracks all records (including label-less COH-routed ones) so they appear in the fallback
  • UNCATEGORIZED_CHAPTER_TITLE constant extracted to keep the contract-visible string stable

Release Notes

  • New super-chapters input: group release note chapters under top-level ## headings by label
  • Records not matching any super-chapter label are collected under an ## Uncategorized fallback section

Related

Closes #99

Summary by CodeRabbit

  • New Features

    • Super Chapters: Group custom chapters under higher-level headings by label matching; includes support for hierarchy-based records.
    • Configurable open-hierarchy sub-issue icon: New input to customize the icon displayed for open sub-issues.
  • Documentation

    • Added comprehensive super chapters configuration guide with examples and behavior details.

@miroslavpojer miroslavpojer self-assigned this Apr 2, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 2, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

This pull request introduces a "super chapters" feature enabling hierarchical organization of release notes by grouping regular chapters under higher-level category headings. The implementation adds new action inputs (super-chapters and open-hierarchy-sub-issue-icon), extends CustomChapters with label-based grouping logic, and enhances HierarchyIssueRecord with label filtering during rendering.

Changes

Cohort / File(s) Summary
Action Configuration
action.yml, release_notes_generator/utils/constants.py
Added super-chapters and open-hierarchy-sub-issue-icon action inputs; introduced constants for these inputs plus UNCATEGORIZED_CHAPTER_TITLE.
Configuration & Input Parsing
release_notes_generator/action_inputs.py
Added get_super_chapters() method to parse and validate super-chapter YAML input; updated logging and validation flow to include super chapters.
Documentation
docs/configuration_reference.md, docs/features/custom_chapters.md, docs/features/issue_hierarchy_support.md, .github/copilot-instructions.md
Documented super-chapters input and "Super Chapters" feature; linked super chapters to hierarchy support; added TDD workflow directives.
Core Feature Implementation
release_notes_generator/chapters/custom_chapters.py
Added SuperChapter dataclass; refactored to_string() to render flat or super-chapter-grouped output; added _to_string_with_super_chapters() helper with uncategorized fallback section; updated record tracking and label normalization.
Label Utilities
release_notes_generator/utils/utils.py
Introduced normalize_labels() function to normalize string/list inputs into deduplicated label lists.
Hierarchy Record Label Filtering
release_notes_generator/model/record/hierarchy_issue_record.py
Extended to_chapter_row() with label_filter and exclude_labels parameters; added has_matching_labels() and has_unmatched_descendants() helpers; refactored child rendering to support label-based filtering with open-hierarchy icon injection.
Test Infrastructure & Helpers
tests/unit/conftest.py
Added make_super_chapters_cc() helper and minimal mock factories for hierarchy testing; introduced patch_hierarchy_action_inputs fixture for consistent test setup.
Feature Tests
tests/unit/release_notes_generator/chapters/test_custom_chapters.py, tests/unit/release_notes_generator/model/test_hierarchy_issue_record.py, tests/unit/release_notes_generator/test_action_inputs.py
Added comprehensive test coverage for super-chapter parsing, grouping, uncategorized rendering, label filtering, hierarchy record label matching, and action input validation.
Type Annotation Modernization
release_notes_generator/data/utils/bulk_sub_issue_collector.py
Updated type hints to PEP 604 union syntax (`X

Sequence Diagram

sequenceDiagram
    participant Action as GitHub Action
    participant Input as ActionInputs
    participant CC as CustomChapters
    participant HRecord as HierarchyIssueRecord
    participant Output as Release Notes

    Action->>Input: get_super_chapters()
    Input->>Input: Parse YAML, validate entries
    Input-->>Action: Return list[dict] with{title, labels}
    
    Action->>CC: __init__(super_chapters=...)
    CC->>CC: Initialize _super_chapters list
    
    Action->>CC: populate(records)
    CC->>CC: Track record labels via get_labels()
    
    Action->>CC: to_string()
    alt Has super chapters
        CC->>CC: For each super chapter by label
        CC->>HRecord: to_chapter_row(label_filter=super_labels)
        HRecord->>HRecord: has_matching_labels(label_filter)
        HRecord->>HRecord: Filter sub-hierarchy/sub-issues by labels
        HRecord-->>CC: Filtered markdown row
        CC->>Output: Render nested heading structure
        CC->>CC: Collect unmatched records
        CC->>Output: Render ## Uncategorized section
    else No super chapters
        CC->>Output: Render flat chapter structure
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related issues

  • Super chapters #99 — Implements the "super chapters" feature for hierarchical chapter organization as described in the issue objectives.

Possibly related PRs

Suggested labels

enhancement

Suggested reviewers

  • tmikula-dev
  • jakipatryk
  • Zejnilovic

Poem

🐰 Hop into chapters nested deep,
Super headings, secrets we keep,
Labels guide the records along,
Organized tales, a harmonious song,
Release notes blooming, forever sweet! 🌾✨

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Title check ⚠️ Warning Title 'Fature/99 super chapters' contains a typo ('Fature' instead of 'Feature') and uses a vague branch-name style format unsuitable for PR history. Change title to 'Add super-chapters feature for grouping release notes by label' or similar descriptive phrasing without typos.
Docstring Coverage ⚠️ Warning Docstring coverage is 68.65% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description check ✅ Passed Description follows the template structure with all required sections (Overview, Release Notes, Related) properly filled with clear, specific details about the feature and changes.
Linked Issues check ✅ Passed Code changes comprehensively implement issue #99 objectives: super-chapter parsing, label-based grouping, multi-matching support, and uncategorized fallback are all implemented as required.
Out of Scope Changes check ✅ Passed All changes directly support super-chapters feature; documentation updates, type modernization, and test infrastructure are appropriately scoped to feature implementation.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fature/99-Super-chapters

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@miroslavpojer miroslavpojer marked this pull request as ready for review April 2, 2026 10:18
@miroslavpojer miroslavpojer requested a review from Copilot April 2, 2026 10:18
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds support for super chapters to the release notes generator, allowing users to group existing custom chapters under higher-level ## headings based on labels, while preserving the original flat ### rendering when the feature is not configured.

Changes:

  • Introduces a new optional super-chapters action input (YAML) and wires it through ActionInputs.
  • Extends CustomChapters rendering to support super-chapter grouping plus an ## Uncategorized fallback.
  • Adds unit tests and updates documentation/action metadata for the new input.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
action.yml Adds the super-chapters input and exports it as INPUT_SUPER_CHAPTERS for runtime consumption.
release_notes_generator/action_inputs.py Implements ActionInputs.get_super_chapters() and logs parsed super-chapter config during validation.
release_notes_generator/chapters/custom_chapters.py Adds super-chapter parsing and grouped rendering logic with an Uncategorized fallback.
release_notes_generator/utils/constants.py Adds SUPER_CHAPTERS input key constant and extracts UNCATEGORIZED_CHAPTER_TITLE.
docs/features/custom_chapters.md Documents configuration, rendering, behavior, and validation rules for super chapters.
docs/configuration_reference.md Adds super-chapters to the inputs reference table.
tests/unit/release_notes_generator/test_action_inputs.py Adds unit tests covering parsing/validation behavior for get_super_chapters().
tests/unit/release_notes_generator/chapters/test_custom_chapters.py Adds unit tests for grouped super-chapter output behavior and fallback behavior.
tests/unit/conftest.py Adds a helper to construct CustomChapters instances with super-chapter behavior patched in tests.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (2)
action.yml (1)

33-38: Consider documenting uncategorized fallback in the input description.

You already document matching and multi-membership; adding one line about the automatic Uncategorized section would make behavior complete directly in action.yml.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@action.yml` around lines 33 - 38, Update the description for the
super-chapters input in action.yml to mention the automatic fallback: add a
sentence to the existing description block (the `description` key for the
super-chapter array) stating that any records not matching any super-chapter
label will be placed into an automatic "Uncategorized" section; keep it brief
and match the tone of the surrounding bullets.
release_notes_generator/chapters/custom_chapters.py (1)

235-244: Temporary mutation of chapter.rows is a code smell.

While the try/finally ensures restoration, directly mutating shared state can be fragile and isn't thread-safe. Consider either passing filter criteria to Chapter.to_string or creating a lightweight wrapper that yields filtered rows without mutation.

Also, the dual check str(rid) in matching_ids or rid in matching_ids suggests type inconsistency between row IDs (possibly int) and matching_ids (always str). Consider normalizing ID types upstream for cleaner comparisons.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@release_notes_generator/chapters/custom_chapters.py` around lines 235 - 244,
The helper _render_chapter_for_ids currently mutates chapter.rows; instead avoid
shared-state mutation by building a filtered_rows dict and invoking
Chapter.to_string on a non-mutated object—either (A) add an optional parameter
to Chapter.to_string like rows/filter_ids and pass filtered_rows, or (B) create
a lightweight shallow copy of the Chapter (e.g., new_chapter = Chapter(...same
metadata..., rows=filtered_rows) or add a Chapter.with_rows(rows) factory) and
call new_chapter.to_string; also normalize ID comparisons by converting
matching_ids to a consistent type (e.g., set[str] = {str(x) for x in
matching_ids}) or casting rid once when creating filtered_rows so you can remove
the dual check (str(rid) in matching_ids or rid in matching_ids).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/features/custom_chapters.md`:
- Line 258: Update the sentence "Within each super chapter, records are routed
to regular chapters by the normal label matching rules." to use a hyphenated
compound adjective for clarity — change "label matching rules" to
"label-matching rules" so the line reads: "Within each super chapter, records
are routed to regular chapters by the normal label-matching rules."

In `@release_notes_generator/action_inputs.py`:
- Around line 175-195: get_super_chapters currently only YAML-parses the input
and leaves semantic validation to CustomChapters._parse_super_chapters; move
that full validation into the ActionInputs boundary by having get_super_chapters
perform the same semantic checks and return only validated structures
(list[dict[str,str]]). Specifically, extend get_super_chapters to validate each
entry's type and required keys/fields (the same contract enforced in
CustomChapters._parse_super_chapters), log and skip or error on invalid entries
consistently, and ensure the return value is strictly the validated list so
CustomChapters no longer needs to re-validate; update/remove the redundant
checks in CustomChapters._parse_super_chapters accordingly.

In `@release_notes_generator/chapters/custom_chapters.py`:
- Around line 367-399: Change the _parse_super_chapters signature to accept
mixed YAML types (use list[dict[str, Any]] for raw_super_chapters) and validate
the title before using it: after extracting entry["title"] in
_parse_super_chapters, ensure it's a str (if not, logger.warning and continue),
and keep using SuperChapter(title=title, labels=...) and _normalize_labels as
before; also adjust the local typing for labels_input to reflect str | list[str]
if you keep annotations.

---

Nitpick comments:
In `@action.yml`:
- Around line 33-38: Update the description for the super-chapters input in
action.yml to mention the automatic fallback: add a sentence to the existing
description block (the `description` key for the super-chapter array) stating
that any records not matching any super-chapter label will be placed into an
automatic "Uncategorized" section; keep it brief and match the tone of the
surrounding bullets.

In `@release_notes_generator/chapters/custom_chapters.py`:
- Around line 235-244: The helper _render_chapter_for_ids currently mutates
chapter.rows; instead avoid shared-state mutation by building a filtered_rows
dict and invoking Chapter.to_string on a non-mutated object—either (A) add an
optional parameter to Chapter.to_string like rows/filter_ids and pass
filtered_rows, or (B) create a lightweight shallow copy of the Chapter (e.g.,
new_chapter = Chapter(...same metadata..., rows=filtered_rows) or add a
Chapter.with_rows(rows) factory) and call new_chapter.to_string; also normalize
ID comparisons by converting matching_ids to a consistent type (e.g., set[str] =
{str(x) for x in matching_ids}) or casting rid once when creating filtered_rows
so you can remove the dual check (str(rid) in matching_ids or rid in
matching_ids).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b625f1e8-a06c-426d-9639-b30f9cd8a5dc

📥 Commits

Reviewing files that changed from the base of the PR and between 77b645a and b5b068c.

📒 Files selected for processing (9)
  • action.yml
  • docs/configuration_reference.md
  • docs/features/custom_chapters.md
  • release_notes_generator/action_inputs.py
  • release_notes_generator/chapters/custom_chapters.py
  • release_notes_generator/utils/constants.py
  • tests/unit/conftest.py
  • tests/unit/release_notes_generator/chapters/test_custom_chapters.py
  • tests/unit/release_notes_generator/test_action_inputs.py

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@release_notes_generator/action_inputs.py`:
- Around line 208-223: The code currently accepts any non-missing "title" value
which may be non-string or blank; update the validation around entry["title"] in
the super-chapter parsing block so that you only accept a title that is a
non-empty string (e.g., check isinstance(title, str) and title.strip() != ""),
log a warning and continue if the title is invalid, and only pass the
cleaned/stripped title into result.append({"title": title, "labels":
normalized}) (keep using normalize_labels and the existing logging patterns).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f83123e6-7884-4ada-81f2-3e9f9139277a

📥 Commits

Reviewing files that changed from the base of the PR and between b5b068c and d9291bc.

📒 Files selected for processing (7)
  • docs/features/custom_chapters.md
  • release_notes_generator/action_inputs.py
  • release_notes_generator/chapters/custom_chapters.py
  • release_notes_generator/utils/utils.py
  • tests/unit/conftest.py
  • tests/unit/release_notes_generator/chapters/test_custom_chapters.py
  • tests/unit/release_notes_generator/test_action_inputs.py
✅ Files skipped from review due to trivial changes (1)
  • docs/features/custom_chapters.md
🚧 Files skipped from review as they are similar to previous changes (4)
  • tests/unit/release_notes_generator/test_action_inputs.py
  • tests/unit/conftest.py
  • tests/unit/release_notes_generator/chapters/test_custom_chapters.py
  • release_notes_generator/chapters/custom_chapters.py

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
release_notes_generator/action_inputs.py (1)

211-226: ⚠️ Potential issue | 🟡 Minor

Strip the validated title before appending.

Line 212 validates that title.strip() is non-empty, but Line 226 appends the original title value with potential leading/trailing whitespace. This could produce headings like " Module A " in the release notes.

Proposed fix
             title = entry["title"]
             if not isinstance(title, str) or not title.strip():
                 logger.warning("Skipping super-chapter with invalid title value: %r", title)
                 continue
+            title = title.strip()
 
             raw_labels = entry.get("labels", entry.get("label"))
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@release_notes_generator/action_inputs.py` around lines 211 - 226, The
validated title may contain leading/trailing whitespace—after confirming
title.strip() is non-empty, replace or assign a stripped version (e.g., title =
title.strip() or use title_stripped) before appending; update the code that
builds the output (the result.append({"title": title, "labels": normalized})
call) to use the stripped title so headings are normalized, leaving label
normalization via normalize_labels unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@release_notes_generator/action_inputs.py`:
- Around line 211-226: The validated title may contain leading/trailing
whitespace—after confirming title.strip() is non-empty, replace or assign a
stripped version (e.g., title = title.strip() or use title_stripped) before
appending; update the code that builds the output (the result.append({"title":
title, "labels": normalized}) call) to use the stripped title so headings are
normalized, leaving label normalization via normalize_labels unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4be0854c-caad-4b3c-8aab-3e5bef3e0bb2

📥 Commits

Reviewing files that changed from the base of the PR and between d9291bc and d0250fd.

📒 Files selected for processing (2)
  • release_notes_generator/action_inputs.py
  • tests/unit/release_notes_generator/test_action_inputs.py
✅ Files skipped from review due to trivial changes (1)
  • tests/unit/release_notes_generator/test_action_inputs.py

…ents (#280)

* feat: enhance hierarchy issue rendering logic for open and closed parents
* feat: add support for highlighting open sub-issues under closed hierarchy parents
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (1)
tests/unit/release_notes_generator/utils/test_gh_action.py (1)

22-36: Cover the explicit default= path too.

These assertions lock in the implicit default="" call, but the contract change also depends on forwarding a caller-supplied default unchanged. A small get_action_input("explicit-default", "fallback") case would keep that branch covered.

🧪 Suggested test
+def test_get_input_with_explicit_default(mocker):
+    mock_getenv = mocker.patch("os.getenv", side_effect=lambda name, default=None: default)
+
+    result = get_action_input("explicit-default", "fallback")
+
+    mock_getenv.assert_called_with("INPUT_EXPLICIT_DEFAULT", default="fallback")
+    assert result == "fallback"

As per coding guidelines, "Test return values, exceptions, log messages, and exit codes in Python tests".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/unit/release_notes_generator/utils/test_gh_action.py` around lines 22 -
36, Add a test that exercises the explicit default path for get_action_input:
call get_action_input("explicit-default", "fallback") in
tests/unit/release_notes_generator/utils/test_gh_action.py, mock os.getenv and
assert it was called with the environment key "INPUT_EXPLICIT_DEFAULT" and
default="fallback", and assert the function returns the mocked value; reference
get_action_input to locate the implementation and the existing tests for
pattern.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/features/custom_chapters.md`:
- Around line 218-315: The docs duplicate the entire "## Super Chapters" section
back-to-back; remove the second copy so there's a single consolidated "## Super
Chapters" section (look for the repeated "## Super Chapters" heading). In that
remaining section add a short sentence to Rendering or Behavior stating the
fallback: "Records that do not match any super-chapter labels are grouped under
## Uncategorized." Also ensure the Validation paragraph still appears once and
mentions skipped entries as before.

In `@release_notes_generator/chapters/custom_chapters.py`:
- Around line 421-425: The constructor is re-parsing already-validated
super-chapter entries causing duplicated validation; replace the duplicate calls
so self._super_chapters is assigned the validated, normalized output from
ActionInputs.get_super_chapters() only (do not call _parse_super_chapters on
that value), remove the redundant parsing calls around the constructor and the
block referenced (including the repeated section covering the 429-474 region),
and leave the standalone _parse_super_chapters method only for the original
raw-YAML parsing path if still needed; target symbols: self._super_chapters,
_parse_super_chapters, and ActionInputs.get_super_chapters.
- Around line 91-99: The class contains unresolved duplicate members—remove the
later duplicates and keep only the first occurrence of each: delete the second
__init__ duplicate and the later definitions of _to_string_with_super_chapters
and _parse_super_chapters; ensure the kept _to_string_with_super_chapters is the
first version that preserves the "## Uncategorized" fallback logic so unmatched
records are collected, and ensure the kept _parse_super_chapters is the first
version that does not re-validate/normalize input (leaving validation to
ActionInputs.get_super_chapters()); update imports/types only if needed after
removing the duplicates.

In `@release_notes_generator/model/record/hierarchy_issue_record.py`:
- Around line 225-254: The code that prefixes open-child icons currently
prepends the icon before the child's existing "- " list marker (see
sub_hierarchy_issue.to_chapter_row() handling and the open_icon_prefix /
sub_issue_block construction), which breaks nested Markdown and leaves stray
spaces when the icon is empty; change the logic to detect and preserve an
existing leading list marker (the initial "-" and following space) and insert
the icon immediately after that marker (e.g., "- " -> "- {icon} " only when icon
non-empty, otherwise leave as "- "), update both the sub_hierarchy_issue branch
and the sub_issue block where open_icon_prefix is used
(ActionInputs.get_open_hierarchy_sub_issue_icon()), and add regression
assertions that verify the rendered output begins with "- 🟡" when icon set and
remains "- " when icon is empty.

---

Nitpick comments:
In `@tests/unit/release_notes_generator/utils/test_gh_action.py`:
- Around line 22-36: Add a test that exercises the explicit default path for
get_action_input: call get_action_input("explicit-default", "fallback") in
tests/unit/release_notes_generator/utils/test_gh_action.py, mock os.getenv and
assert it was called with the environment key "INPUT_EXPLICIT_DEFAULT" and
default="fallback", and assert the function returns the mocked value; reference
get_action_input to locate the implementation and the existing tests for
pattern.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b4d7d817-034a-47e2-933f-b6b4ec8142c4

📥 Commits

Reviewing files that changed from the base of the PR and between d0250fd and 30754f3.

📒 Files selected for processing (11)
  • action.yml
  • docs/features/custom_chapters.md
  • docs/features/issue_hierarchy_support.md
  • release_notes_generator/action_inputs.py
  • release_notes_generator/chapters/custom_chapters.py
  • release_notes_generator/model/record/hierarchy_issue_record.py
  • release_notes_generator/utils/constants.py
  • release_notes_generator/utils/gh_action.py
  • tests/unit/conftest.py
  • tests/unit/release_notes_generator/model/test_hierarchy_issue_record.py
  • tests/unit/release_notes_generator/utils/test_gh_action.py
🚧 Files skipped from review as they are similar to previous changes (4)
  • action.yml
  • release_notes_generator/action_inputs.py
  • release_notes_generator/utils/constants.py
  • tests/unit/conftest.py

@miroslavpojer miroslavpojer marked this pull request as draft April 2, 2026 15:16
@miroslavpojer miroslavpojer added the work in progress Work on this item is not yet finished (mainly intended for PRs) label Apr 6, 2026
@miroslavpojer miroslavpojer marked this pull request as ready for review April 6, 2026 16:36
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 15 out of 15 changed files in this pull request and generated 2 comments.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 15 out of 15 changed files in this pull request and generated 1 comment.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 15 out of 15 changed files in this pull request and generated 2 comments.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 15 out of 15 changed files in this pull request and generated 3 comments.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 15 out of 15 changed files in this pull request and generated 2 comments.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 15 out of 15 changed files in this pull request and generated 1 comment.

Copy link
Copy Markdown
Collaborator Author

@miroslavpojer miroslavpojer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have done self review as I was writing it for a long time with pauses.

- Prefer TDD workflow:
- Must create or update `SPEC.md` in the relevant package directory before writing any code, listing scenarios, inputs, and expected outputs.
- Must propose the full set of test cases (name + one-line intent + input summary + expected output summary) and wait for user confirmation before writing any code.
- Must be ready to add, remove, or rename tests based on user feedback before proceeding.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line means, you are always doing a planning of task in PLAN mode before implementing? If not, would this line mean, that the implementation can stop to get confirmation from user and will spent extra premium requests.

From this section I am not sure, if TDD is now way how to implement new things, since it has a big part of the copilot doc, but is Preferred workflow.

Copy link
Copy Markdown
Collaborator Author

@miroslavpojer miroslavpojer Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The TDD block is marked Prefer (not Must), so it's being trialed rather than enforced.

  • The plan-then-confirm checkpoint is useful for bigger changes but too heavy for quick fixes
  • Worth tracking whether the extra round-trip pays off in practice

Final Note: I am experimenting with this approach, here.

def _collect_super_chapter_ids(self, sc: SuperChapter) -> set[str]:
"""Return record IDs whose labels match the given super chapter."""
matching: set[str] = set()
for rid, labels in self._record_labels.items():
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What rid stands for please?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Short for record ID — the unique PR or issue number used as the key in _record_labels.

result.append({"title": title, "labels": normalized})
logger.debug("Validated super-chapter '%s' with labels: %s", title, normalized)
ActionInputs._super_chapters_raw = super_chapters_input
ActionInputs._super_chapters_cache = result
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this cache var solving?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

get_super_chapters() reads and parses a YAML env var. The cache avoids re-parsing the same string on every call.

Copy link
Copy Markdown
Collaborator

@tmikula-dev tmikula-dev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic looks correct. It is complex huge feature/refactor. During review I was little lost with the naming like coh, rid etc. But since you are the key developer, it is important that you are familiar with them. I left few comments, to understand some stuff, but approving the logic.

@miroslavpojer miroslavpojer merged commit 11f97ad into master Apr 8, 2026
8 checks passed
@miroslavpojer miroslavpojer deleted the fature/99-Super-chapters branch April 8, 2026 11:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

work in progress Work on this item is not yet finished (mainly intended for PRs)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Super chapters

3 participants