Files
fusion/scripts/lib/channel-changeset-scope.mjs
gsxdsm ff165ecb5a fix: scope beta release notes to that beta's changesets; stable keeps full-cycle rollup
Pre-mode preserves consumed changeset .md files, so every beta's distilled notes and GitHub prerelease body aggregated the entire cycle since the last stable (v0.73.0-beta.4 shipped the full 0.72.0→0.73.0 aggregate). Betas now distill only changesets not yet recorded in pre.json's consumed ledger, and fail loudly when a beta would ship nothing new. Stable promotion still feeds the full preserved set, keeping its notes an explicit rollup of every beta in the cycle.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 12:18:24 -07:00

50 lines
2.3 KiB
JavaScript

/*
FNXC:Changelog 2026-07-23-10:40:
Beta releases must show notes for ONLY the changesets new in that beta, not the whole pre cycle.
Changesets pre-mode preserves every consumed .md file on disk (recording consumed names in pre.json's `changesets` array), so a naive read of `.changeset/*.md` re-aggregates the entire cycle into every beta's distilled notes and GitHub prerelease body — v0.73.0-beta.4 shipped the full 0.72.0→0.73.0 aggregate instead of its own handful of fixes.
This module scopes the note-feeding changeset set per channel:
- beta: exclude names already recorded in pre.json (already released in a prior beta of this cycle);
- stable: keep the FULL set — the stable release's notes are intentionally a rollup of every change across all betas in the cycle.
Pure and side-effect free so it is unit-testable outside the release script.
*/
/**
* Strip the `.md` extension from a changeset filename to get the changeset
* name as recorded in pre.json's `changesets` array.
*/
export function changesetNameFromFile(file) {
return file.replace(/\.md$/, "");
}
/**
* Select which pending changesets feed release notes for the given channel.
*
* @param {"beta"|"stable"} channel
* @param {Array<{file: string}>} summaries - entries from readChangesetSummaries();
* only `.file` is inspected, extra fields pass through untouched.
* @param {string[]} preReleasedNames - pre.json `changesets` array (names of
* changesets consumed by prior betas in this pre cycle). Pass [] when there
* is no pre.json (first beta of a cycle) or on the stable channel.
* @returns {{ selected: Array, alreadyReleased: Array }}
*/
export function selectChannelChangesets(channel, summaries, preReleasedNames) {
if (channel !== "beta") {
// FNXC:Changelog 2026-07-23-10:40:
// Stable = full-cycle rollup. Every preserved changeset from every beta
// (plus any landed after the last beta) is included so the stable
// changelog and GitHub Release aggregate the whole cycle.
return { selected: summaries, alreadyReleased: [] };
}
const released = new Set(preReleasedNames);
const selected = [];
const alreadyReleased = [];
for (const summary of summaries) {
if (released.has(changesetNameFromFile(summary.file))) {
alreadyReleased.push(summary);
} else {
selected.push(summary);
}
}
return { selected, alreadyReleased };
}