Skip to content

Add interactive release note generator#649

Open
everettbu wants to merge 1 commit into
mainfrom
release-notes
Open

Add interactive release note generator#649
everettbu wants to merge 1 commit into
mainfrom
release-notes

Conversation

@everettbu

Copy link
Copy Markdown

Mirror of facebook/react#35949
Original author: jackpope


Add an interactive release notes app (scripts/release-notes/) for triaging commits and generating markdown.

Run yarn gen-data -v <version> to pull commits since a tag, then yarn dev to launch a Vite app where you can mark commits to include, tag and group them, filter the list, and get a live markdown preview. Triage state persists to a local JSON file.

This is good for a first pass on what to include. Then you can copy the markdown out to reword messages and do additional custom grouping or formatting changes.

@greptile-apps

greptile-apps Bot commented Mar 3, 2026

Copy link
Copy Markdown

Greptile Summary

Adds a self-contained interactive release notes tool under scripts/release-notes/. A Node script (gen-data.mjs) pulls commits since a given git tag and resolves GitHub usernames via gh CLI, while a Vite + React app provides a UI for triaging commits, assigning tags, filtering, and generating/previewing release notes markdown. State is persisted to a local JSON file via a custom Vite server plugin.

  • The app is well-structured with clean separation between data generation, API layer, and UI components
  • Commit table uses @tanstack/react-table for sorting, filtering, and global search
  • Tag management supports creating, editing, coloring, and grouping commits as features
  • Minor concerns around the custom markdownToHtml renderer (no URL protocol sanitization in dangerouslySetInnerHTML output) and pipe-delimited git log parsing fragility — both low risk for a local-only dev tool

Confidence Score: 4/5

  • This PR is safe to merge — it adds an isolated local dev tool under scripts/ with no impact on the main React codebase.
  • The release notes tool is self-contained under scripts/release-notes/ and does not modify any existing source code. The only issues found are minor style concerns (custom markdown renderer sanitization, git log parsing edge case) that are low risk given this is a local-only developer tool. The static state.json import issue was already noted in a prior review thread.
  • scripts/release-notes/src/components/ReleaseNotes.jsx (custom HTML renderer with dangerouslySetInnerHTML) and scripts/release-notes/gen-data.mjs (commit parsing logic).

Important Files Changed

Filename Overview
scripts/release-notes/gen-data.mjs Commit data generation script; uses %h (abbreviated hash) but names it fullHash, and pipe-delimited parsing can break on author names containing `
scripts/release-notes/src/App.jsx Main app component; static import of state.json will crash on fresh clone before state is persisted. fetchState is imported but unused.
scripts/release-notes/plugins/api.js Vite server plugin for reading/writing state JSON; no body size limit on POST but acceptable for local-only usage.
scripts/release-notes/src/components/CommitTable.jsx Commit table with filtering and sorting using @tanstack/react-table; well-structured with no issues found.
scripts/release-notes/src/components/ReleaseNotes.jsx Release notes markdown generator with preview; markdownToHtml applies link regex after escapeHtml which re-introduces unescaped href attributes from user-influenced data.
scripts/release-notes/src/components/TagManager.jsx Tag CRUD component; straightforward implementation with no issues.
scripts/release-notes/src/components/TagPicker.jsx Simple tag toggle component; no issues found.
scripts/release-notes/vite.config.js Vite config with React plugin and custom API plugin; ignores state.json from watch. No issues.
scripts/release-notes/package.json Package manifest with appropriate dependencies for the release notes tool.

Fix All in Claude Code Fix All in Codex

Last reviewed commit: 4b56ae7

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

17 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

Comment thread scripts/release-notes/gen-data.mjs
Comment thread scripts/release-notes/src/App.jsx
…aging commits and generating markdown.

Run yarn gen-data -v <version> to pull commits since a tag, then yarn dev to launch a Vite app where you can mark commits to include, tag and group them, filter the list, and get a live markdown preview with copy-to-clipboard. Triage state persists to a local JSON file.
Comment on lines +74 to +78
let content = escapeHtml(line.slice(2));
// Links: [text](url)
content = content.replace(
/\[([^\]]+)\]\(([^)]+)\)/g,
'<a href="$2" target="_blank">$1</a>'

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

markdownToHtml can render javascript: links from commit summaries

The escapeHtml call on line 74 escapes <, >, and &, but does not affect markdown link syntax ([text](url)). The subsequent link regex on lines 76-78 then converts these into raw <a href="$2"> tags via dangerouslySetInnerHTML (line 184).

If a commit summary contains markdown link syntax like [click](javascript:alert(1)), it passes through escapeHtml unchanged (no HTML chars to escape), the link regex matches it, and the result is an <a href="javascript:alert(1)"> element rendered in the DOM.

Since this is a local dev tool processing commits from your own repo, the risk is low — but it's worth sanitizing the href capture to only allow http:/https: protocols, especially since escapeHtml also doesn't escape " which could allow attribute breakout via crafted URLs containing double quotes.

Prompt To Fix With AI
This is a comment left during a code review.
Path: scripts/release-notes/src/components/ReleaseNotes.jsx
Line: 74-78

Comment:
**`markdownToHtml` can render `javascript:` links from commit summaries**

The `escapeHtml` call on line 74 escapes `<`, `>`, and `&`, but does not affect markdown link syntax (`[text](url)`). The subsequent link regex on lines 76-78 then converts these into raw `<a href="$2">` tags via `dangerouslySetInnerHTML` (line 184).

If a commit summary contains markdown link syntax like `[click](javascript:alert(1))`, it passes through `escapeHtml` unchanged (no HTML chars to escape), the link regex matches it, and the result is an `<a href="javascript:alert(1)">` element rendered in the DOM.

Since this is a local dev tool processing commits from your own repo, the risk is low — but it's worth sanitizing the `href` capture to only allow `http:`/`https:` protocols, especially since `escapeHtml` also doesn't escape `"` which could allow attribute breakout via crafted URLs containing double quotes.

How can I resolve this? If you propose a fix, please make it concise.

Fix in Claude Code Fix in Codex

const commits = listOfCommits.split('\n').map((commitMessage, index) => {
const diffMatch = body[index]?.match(/D\d+/);
const diff = diffMatch != null && diffMatch[0];
const [hash, date, name] = commitMessage.split('|');

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pipe delimiter can split author names incorrectly

The format string on line 78 is %h|%ai|%aN|%ae, producing 4 pipe-delimited fields. The destructuring here only captures 3 values (hash, date, name), which works in the common case. However, if an author's Git display name (%aN) contains a | character, split('|') would produce more than 4 segments, and name would be truncated to only the portion before the first | in the name.

Consider using a delimiter that's less likely to appear in names (e.g., \x00 null byte), or using a fixed number of splits:

Suggested change
const [hash, date, name] = commitMessage.split('|');
const parts = commitMessage.split('|');
const [hash, date] = parts;
const name = parts.slice(2, -1).join('|');

This takes the email (last field) off the end and joins the remaining middle fields back, preserving any | in the author name.

Prompt To Fix With AI
This is a comment left during a code review.
Path: scripts/release-notes/gen-data.mjs
Line: 96

Comment:
**Pipe delimiter can split author names incorrectly**

The format string on line 78 is `%h|%ai|%aN|%ae`, producing 4 pipe-delimited fields. The destructuring here only captures 3 values (`hash`, `date`, `name`), which works in the common case. However, if an author's Git display name (`%aN`) contains a `|` character, `split('|')` would produce more than 4 segments, and `name` would be truncated to only the portion before the first `|` in the name.

Consider using a delimiter that's less likely to appear in names (e.g., `\x00` null byte), or using a fixed number of splits:

```suggestion
    const parts = commitMessage.split('|');
    const [hash, date] = parts;
    const name = parts.slice(2, -1).join('|');
```

This takes the email (last field) off the end and joins the remaining middle fields back, preserving any `|` in the author name.

How can I resolve this? If you propose a fix, please make it concise.

Fix in Claude Code Fix in Codex

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants