Skip to content

Fix release notes parser to handle bot-generated content#66

Open
yhwang wants to merge 1 commit into
prestodb:masterfrom
yhwang:refine-release-note-pattern
Open

Fix release notes parser to handle bot-generated content#66
yhwang wants to merge 1 commit into
prestodb:masterfrom
yhwang:refine-release-note-pattern

Conversation

@yhwang
Copy link
Copy Markdown
Member

@yhwang yhwang commented Apr 21, 2026

The regex pattern was greedy and incorrectly captured bot-generated 'Summary by Sourcery' content within release notes sections. This caused the parser to fail with 'expect section header' errors.

Changes:

  • Changed regex from greedy to reluctant quantifier (.*?)
  • Replaced negative lookahead with positive lookahead for clarity
  • Added \s* to handle optional whitespace before 'Summary by'
  • Pattern now stops before any bot-generated content

The fix maintains backward compatibility with all existing test cases while correctly handling PRs with bot-generated summaries.

Test coverage:

  • Added test case for Sourcery bot content
  • All 36 TestCheckReleaseNotesTask tests pass
  • All TestGenerateReleaseNotesTask tests pass
  • No regressions detected

The regex pattern was greedy and incorrectly captured bot-generated
'Summary by Sourcery' content within release notes sections. This
caused the parser to fail with 'expect section header' errors.

Changes:
- Changed regex from greedy to reluctant quantifier (.*?)
- Replaced negative lookahead with positive lookahead for clarity
- Added \s* to handle optional whitespace before 'Summary by'
- Pattern now stops before any bot-generated content

The fix maintains backward compatibility with all existing test cases
while correctly handling PRs with bot-generated summaries.

Test coverage:
- Added test case for Sourcery bot content
- All 36 TestCheckReleaseNotesTask tests pass
- All TestGenerateReleaseNotesTask tests pass
- No regressions detected

Signed-off-by: Yihong Wang <yh.wang@ibm.com>
@yhwang yhwang requested review from a team as code owners April 21, 2026 20:24
@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented Apr 21, 2026

Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Adjusts the release-notes regex to stop before bot-generated "Summary by" footers and adds a targeted test to ensure PRs with Sourcery bot content are parsed correctly without regressing existing behavior.

Sequence diagram for release notes parsing with bot-generated Summary by content

sequenceDiagram
    participant CiJob
    participant GenerateReleaseNotesTask
    participant ReleaseNotesParser
    participant ReleaseNotePattern

    CiJob->>GenerateReleaseNotesTask: run()
    GenerateReleaseNotesTask->>ReleaseNotesParser: parse(prBody)
    ReleaseNotesParser->>ReleaseNotePattern: match("== release notes ==...Summary by Sourcery...")
    Note over ReleaseNotePattern: Pattern: == release note(s)? ==\w*\n?(.*?)(?=\s*Summary by|\z)
    ReleaseNotePattern-->>ReleaseNotesParser: match groups
    Note over ReleaseNotesParser: Group 2 contains only release notes section
    ReleaseNotesParser-->>GenerateReleaseNotesTask: ReleaseNotes
    GenerateReleaseNotesTask-->>CiJob: success (no "expect section header" error)
Loading

File-Level Changes

Change Details Files
Update release-notes extraction regex to be non-greedy and explicitly stop before bot-generated "Summary by" sections.
  • Switch main capture group from a tempered-dot pattern with negative lookahead to a reluctant quantifier to avoid over-capturing content
  • Replace the negative lookahead construction with a trailing positive lookahead that matches either optional whitespace plus "Summary by" or end-of-string
  • Allow optional whitespace before the "Summary by" marker so bot footers with varying spacing are handled consistently
presto-release-tools/src/main/java/com/facebook/presto/release/tasks/GenerateReleaseNotesTask.java
Broaden test coverage to include release notes with Sourcery bot-generated summaries.
  • Register a new release-notes fixture containing Sourcery bot content in the map of valid release-notes samples
  • Add a corresponding text fixture file under test resources to exercise parsing when a bot-generated "Summary by" footer is present
presto-release-tools/src/test/java/com/facebook/presto/release/tasks/TestCheckReleaseNotesTask.java
presto-release-tools/src/test/resources/release-notes-test/pr/release_notes_with_sourcery_bot.txt

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@yhwang
Copy link
Copy Markdown
Member Author

yhwang commented Apr 21, 2026

cc @unidevel

Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

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

Hey - I've found 1 issue, and left some high level feedback:

  • The updated pattern stops on any Summary by preceded by optional whitespace anywhere in the text, which may prematurely terminate content if Summary by appears in the middle of a sentence; consider tightening the lookahead to something like (?=\n\s*Summary by|\z) so it only triggers at the start of a line.
  • The comment above RELEASE_NOTE_PATTERN still refers to stopping before a "\nSummary by" footer, but the regex now uses \s*Summary by; either align the implementation with the comment or update the comment to reflect the broader matching behavior.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The updated pattern stops on any `Summary by` preceded by optional whitespace anywhere in the text, which may prematurely terminate content if `Summary by` appears in the middle of a sentence; consider tightening the lookahead to something like `(?=\n\s*Summary by|\z)` so it only triggers at the start of a line.
- The comment above `RELEASE_NOTE_PATTERN` still refers to stopping before a "\nSummary by" footer, but the regex now uses `\s*Summary by`; either align the implementation with the comment or update the comment to reflect the broader matching behavior.

## Individual Comments

### Comment 1
<location path="presto-release-tools/src/main/java/com/facebook/presto/release/tasks/GenerateReleaseNotesTask.java" line_range="88-91" />
<code_context>
     // Pattern: "== release note(s)? ==" followed by optional whitespace and newline, then captures content
     // until it encounters "\nSummary by" or reaches end of string
-    protected static final Pattern RELEASE_NOTE_PATTERN = Pattern.compile("== release note(s)? ==\\w*\\n?((?:(?!\\nSummary by).)*)", CASE_INSENSITIVE + MULTILINE + DOTALL);
+    protected static final Pattern RELEASE_NOTE_PATTERN = Pattern.compile("== release note(s)? ==\\w*\\n?(.*?)(?=\\s*Summary by|\\z)", CASE_INSENSITIVE + MULTILINE + DOTALL);
     protected static final Pattern HEADER_PATTERN = Pattern.compile("(.*) change(s)$", CASE_INSENSITIVE);
     public static final List<Pattern> VALID_SECTION_HEADERS = ImmutableList.of(
</code_context>
<issue_to_address>
**suggestion (bug_risk):** The `Summary by` lookahead should likely be anchored to the start of a line to avoid truncating notes that mention it in the middle of text.

With `MULTILINE + DOTALL`, `(?=\s*Summary by|\z)` will end the match on any `Summary by` preceded by whitespace anywhere in the body, not only on footer lines. A note like `... as summarized in Summary by XYZ ...` would be truncated. If this is meant to target only footer-style lines, anchor to line start, e.g. `(?=^\s*Summary by|\z)` (keeping `MULTILINE`).

```suggestion
    // Matches release notes section and stops capturing before "Summary by" footer (added by bots like Sourcery)
    // Pattern: "== release note(s)? ==" followed by optional whitespace and newline, then captures content
    // until it encounters a line starting with "Summary by" or reaches end of string
    protected static final Pattern RELEASE_NOTE_PATTERN = Pattern.compile("== release note(s)? ==\\w*\\n?(.*?)(?=^\\s*Summary by|\\z)", CASE_INSENSITIVE + MULTILINE + DOTALL);
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines 88 to +91
// Matches release notes section and stops capturing before "Summary by" footer (added by bots like Sourcery)
// Pattern: "== release note(s)? ==" followed by optional whitespace and newline, then captures content
// until it encounters "\nSummary by" or reaches end of string
protected static final Pattern RELEASE_NOTE_PATTERN = Pattern.compile("== release note(s)? ==\\w*\\n?((?:(?!\\nSummary by).)*)", CASE_INSENSITIVE + MULTILINE + DOTALL);
protected static final Pattern RELEASE_NOTE_PATTERN = Pattern.compile("== release note(s)? ==\\w*\\n?(.*?)(?=\\s*Summary by|\\z)", CASE_INSENSITIVE + MULTILINE + DOTALL);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

suggestion (bug_risk): The Summary by lookahead should likely be anchored to the start of a line to avoid truncating notes that mention it in the middle of text.

With MULTILINE + DOTALL, (?=\s*Summary by|\z) will end the match on any Summary by preceded by whitespace anywhere in the body, not only on footer lines. A note like ... as summarized in Summary by XYZ ... would be truncated. If this is meant to target only footer-style lines, anchor to line start, e.g. (?=^\s*Summary by|\z) (keeping MULTILINE).

Suggested change
// Matches release notes section and stops capturing before "Summary by" footer (added by bots like Sourcery)
// Pattern: "== release note(s)? ==" followed by optional whitespace and newline, then captures content
// until it encounters "\nSummary by" or reaches end of string
protected static final Pattern RELEASE_NOTE_PATTERN = Pattern.compile("== release note(s)? ==\\w*\\n?((?:(?!\\nSummary by).)*)", CASE_INSENSITIVE + MULTILINE + DOTALL);
protected static final Pattern RELEASE_NOTE_PATTERN = Pattern.compile("== release note(s)? ==\\w*\\n?(.*?)(?=\\s*Summary by|\\z)", CASE_INSENSITIVE + MULTILINE + DOTALL);
// Matches release notes section and stops capturing before "Summary by" footer (added by bots like Sourcery)
// Pattern: "== release note(s)? ==" followed by optional whitespace and newline, then captures content
// until it encounters a line starting with "Summary by" or reaches end of string
protected static final Pattern RELEASE_NOTE_PATTERN = Pattern.compile("== release note(s)? ==\\w*\\n?(.*?)(?=^\\s*Summary by|\\z)", CASE_INSENSITIVE + MULTILINE + DOTALL);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant