diff --git a/scripts/compute-next-beta.mjs b/scripts/compute-next-beta.mjs index 3a07adf5..59e2f10e 100644 --- a/scripts/compute-next-beta.mjs +++ b/scripts/compute-next-beta.mjs @@ -200,9 +200,11 @@ export function extractDeltaSection(content) { export function parseSection(section) { // Parse a CHANGELOG-section body into { 'Patch Changes': [{hash, body}, ...], ... }. - // Entries are bullets opened by `- ` at column 0; continuation lines start - // with two spaces of indentation. The Changesets renderer prefixes each - // direct entry with the short commit hash (`- 67028e1: foo...`). + // Entries are bullets opened by `- ` at column 0; continuation lines are + // 2-space-indented (or blank). The Changesets renderer prefixes each direct + // entry with the short commit hash (`- 67028e1: foo...`). Inside an open + // entry, only a `### ` group heading or a new top-level `- ` bullet ends it — + // every other line is continuation, even at column 0 (see below). const groups = {}; let currentGroup = null; let currentEntry = null; @@ -223,9 +225,18 @@ export function parseSection(section) { const m = /^- (?:([a-f0-9]{6,}): )?([\s\S]*)$/.exec(line); currentEntry = { hash: m?.[1] ?? null, body: m?.[2] ?? line.slice(2) }; groups[currentGroup].push(currentEntry); - } else if (currentEntry && (line.startsWith(' ') || line === '')) { - currentEntry.body += `\n${line.startsWith(' ') ? line.slice(2) : ''}`; + } else if (currentEntry) { + // Continuation of the open entry. Strip one list-indent level from the + // canonical 2-space form so renderNotes can re-apply it uniformly; keep a + // column-0 line verbatim. A column-0 non-blank line reaches here only + // when prettier — which `changeset version` runs over CHANGELOG.md — + // de-indented the second physical line of an inline code span that a + // changeset wrapped across a hard line break. Folding it into the entry + // instead of terminating on it keeps that line, and everything after it, + // from being dropped from the release notes. + currentEntry.body += `\n${line.startsWith(' ') ? line.slice(2) : line}`; } else { + // A stray line before any bullet is opened: nothing to attach it to. commit(); } } diff --git a/scripts/compute-next-beta.test.mjs b/scripts/compute-next-beta.test.mjs index 8bf57674..dee451e3 100644 --- a/scripts/compute-next-beta.test.mjs +++ b/scripts/compute-next-beta.test.mjs @@ -114,6 +114,22 @@ describe('parseSection', () => { expect(groups['Patch Changes'][0].hash).toBeNull(); expect(groups['Patch Changes'][0].body.startsWith('Updated dependencies')).toBe(true); }); + + test('keeps a de-indented continuation line without truncating the entry', () => { + // When a changeset wraps an inline code span across a hard line break, + // prettier (run by `changeset version` over CHANGELOG.md) de-indents the + // second physical line to column 0. It is still part of the bullet, not a + // new entry — dropping it silently truncated a shipped release note. + const section = `### Patch Changes + +- abc1234: intro sentence with a wrapped span \`ok diagnose +--redact\` and a tail sentence that must survive. +`; + const groups = parseSection(section); + expect(groups['Patch Changes']).toHaveLength(1); + const body = groups['Patch Changes'][0].body; + expect(body).toContain('--redact` and a tail sentence that must survive.'); + }); }); describe('renderNotes', () => { @@ -315,6 +331,45 @@ describe('round-trip: extractDeltaSection → parseSection → renderNotes', () // Marker at end. expect(notes).toMatch(/$/); }); + + test('does not truncate an entry whose body has a prettier-de-indented code-span wrap', () => { + // Reproduces the shape that truncated the v0.34.0 release note: a changeset + // wrapped an inline code span across a hard line break, and prettier — which + // `changeset version` runs over CHANGELOG.md — emitted the span's second + // line flush-left (column 0) while the surrounding lines stayed 2-space + // indented. The whole tail of the entry (and anything after it) was dropped. + const cliChangelog = `# @inkeep/open-knowledge + +## 0.34.0 + +### Patch Changes + +- abc1234: Migrate the toolchain from Bun to pnpm 10 and Vitest 4. + + Two small behavioral deltas ride along with the swap: \`ok diagnose +--redact\` bundles now derive doc-name tokens with sha256 instead of BLAKE2b-256; + and the file-copy API now returns HTTP 409 (previously an unhandled 500). + +## 0.33.0 + +### Patch Changes + +- old: prior beta entry +`; + const notes = renderNotes({ + packageDeltas: { cli: extractDeltaSection(cliChangelog) }, + newConsumedSet: ['remove-bun-toolchain-migration'], + prevBetaTag: 'v0.33.0-beta.12', + newCount: 1, + }); + // Everything after the wrapped span must survive to the release notes. + expect(notes).toContain('`ok diagnose'); + expect(notes).toContain('--redact` bundles now derive'); + expect(notes).toContain('HTTP 409'); + expect(notes).toContain('unhandled 500'); + // Prior-version content across the second ## heading must NOT leak in. + expect(notes).not.toContain('prior beta entry'); + }); }); describe('bumpSemver', () => {