mirror of
https://github.com/better-auth/better-auth.git
synced 2026-10-20 20:26:55 -05:00
ci(release): source release notes from changesets (#11195)
This commit is contained in:
@@ -502,8 +502,8 @@ function loadPreviousPrereleaseChangesets(version: string): Set<string> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects release entries using git history as the ground truth,
|
||||
* enriched with changeset descriptions where available.
|
||||
* Collects release entries from consumed changesets and enriches them with
|
||||
* pull request metadata from git history.
|
||||
*
|
||||
* Handles the cherry-pick history gap (where the previous tag is not
|
||||
* a direct ancestor) using PR-number deduplication.
|
||||
@@ -650,18 +650,13 @@ export async function collectEntries(
|
||||
|
||||
if (seenPRs.has(prNumber)) continue;
|
||||
|
||||
// A PR with a changeset should appear even if its type is docs:/chore:/etc.
|
||||
// A consumed changeset is the release intent. Git history only provides
|
||||
// metadata for that entry.
|
||||
const subject = parsed.subject.replace(/\s*\(#\d+\)$/, "").trim();
|
||||
const descMatch = changesetByDesc.get(subject.toLowerCase());
|
||||
const changeset = changesetByPR.get(prNumber) ?? descMatch;
|
||||
if (descMatch) consumedOrphans.add(descMatch);
|
||||
|
||||
if (
|
||||
!changeset &&
|
||||
["chore", "docs", "ci", "test", "style", "build"].includes(parsed.type)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
if (!changeset) continue;
|
||||
|
||||
seenPRs.add(prNumber);
|
||||
|
||||
@@ -671,13 +666,13 @@ export async function collectEntries(
|
||||
let packageName: string;
|
||||
let breaking = parsed.breaking;
|
||||
|
||||
const changesetDescription = changeset?.description ?? null;
|
||||
if (changeset?.breaking) breaking = true;
|
||||
const changesetDescription = changeset.description;
|
||||
if (changeset.breaking) breaking = true;
|
||||
|
||||
title = subject;
|
||||
domain = resolveDomain(parsed.scope || undefined, []);
|
||||
packageName =
|
||||
changeset?.packageNames.length === 1
|
||||
changeset.packageNames.length === 1
|
||||
? changeset.packageNames[0]!
|
||||
: resolvePackage(parsed.scope || undefined, []);
|
||||
|
||||
@@ -687,20 +682,20 @@ export async function collectEntries(
|
||||
title = prInfo.title;
|
||||
domain = classifyEntry(prInfo, parsed.scope || undefined, prInfo.files);
|
||||
packageName =
|
||||
changeset?.packageNames.length === 1
|
||||
changeset.packageNames.length === 1
|
||||
? changeset.packageNames[0]!
|
||||
: resolvePackage(parsed.scope || undefined, prInfo.files);
|
||||
if (prInfo.labels.includes("breaking")) breaking = true;
|
||||
}
|
||||
|
||||
const releasePackages =
|
||||
changeset?.packageNames.length && changeset.packageNames.length > 0
|
||||
changeset.packageNames.length > 0
|
||||
? [...new Set(changeset.packageNames)]
|
||||
: [packageName];
|
||||
|
||||
for (const releasePackage of releasePackages) {
|
||||
entries.push({
|
||||
id: `${changeset ? `pr-${prNumber}` : `git-${prNumber}`}:${releasePackage}`,
|
||||
id: `pr-${prNumber}:${releasePackage}`,
|
||||
rewriteKey: `pr-${prNumber}`,
|
||||
title,
|
||||
changesetDescription,
|
||||
|
||||
@@ -184,9 +184,11 @@ function createChangesetStateFixture(
|
||||
interface ReleaseFixtureOptions {
|
||||
mergeVersionPR?: boolean;
|
||||
consumeLaterChangeset?: boolean;
|
||||
includePRWithoutChangeset?: boolean;
|
||||
splitVersionCommit?: boolean;
|
||||
separateChangesetCommit?: boolean;
|
||||
staleReleaseTag?: boolean;
|
||||
supersedeChangeset?: boolean;
|
||||
uppercaseChangesetId?: boolean;
|
||||
}
|
||||
|
||||
@@ -220,7 +222,7 @@ function createReleaseWithFollowUpCommit(options: ReleaseFixtureOptions = {}): {
|
||||
: options.separateChangesetCommit
|
||||
? "standalone-description"
|
||||
: "pr-42";
|
||||
const changesetPath = `.changeset/${changesetId}.md`;
|
||||
let changesetPath = `.changeset/${changesetId}.md`;
|
||||
const changesetDescription = options.separateChangesetCommit
|
||||
? "Require explicit migration"
|
||||
: "Require an explicit migration after the release.";
|
||||
@@ -246,6 +248,38 @@ function createReleaseWithFollowUpCommit(options: ReleaseFixtureOptions = {}): {
|
||||
"fix(session): require explicit migration (#42)",
|
||||
]);
|
||||
|
||||
if (options.includePRWithoutChangeset) {
|
||||
writeFixtureFile(
|
||||
workspace,
|
||||
"packages/better-auth/vitest.config.ts",
|
||||
"export default {};",
|
||||
);
|
||||
git(workspace, ["add", "."]);
|
||||
git(workspace, ["commit", "-m", "fix: isolate package tests (#43)"]);
|
||||
}
|
||||
|
||||
if (options.supersedeChangeset) {
|
||||
rmSync(resolve(workspace, changesetPath));
|
||||
changesetPath = ".changeset/pr-44.md";
|
||||
writeFixtureFile(
|
||||
workspace,
|
||||
changesetPath,
|
||||
[
|
||||
"---",
|
||||
'"better-auth": patch',
|
||||
"---",
|
||||
"",
|
||||
"Replace the superseded release intent.",
|
||||
].join("\n"),
|
||||
);
|
||||
git(workspace, ["add", "."]);
|
||||
git(workspace, [
|
||||
"commit",
|
||||
"-m",
|
||||
"revert: replace the superseded change (#44)",
|
||||
]);
|
||||
}
|
||||
|
||||
rmSync(resolve(workspace, changesetPath));
|
||||
if (options.splitVersionCommit) {
|
||||
git(workspace, ["add", "."]);
|
||||
@@ -533,6 +567,28 @@ describe("release changeset collection", () => {
|
||||
}
|
||||
});
|
||||
|
||||
it("uses consumed changesets as the release entry source", () => {
|
||||
const fixture = createReleaseWithFollowUpCommit({
|
||||
includePRWithoutChangeset: true,
|
||||
supersedeChangeset: true,
|
||||
});
|
||||
try {
|
||||
const result = collectReleaseNotes("2.0.0", {
|
||||
branch: "HEAD",
|
||||
commitRef: fixture.commitRef,
|
||||
workspace: fixture.workspace,
|
||||
});
|
||||
|
||||
expect(result.status, result.stderr).toBe(0);
|
||||
expect(result.stdout).toContain("Replace the superseded release intent.");
|
||||
expect(result.stdout).toContain("pull/44");
|
||||
expect(result.stdout).not.toContain("pull/42");
|
||||
expect(result.stdout).not.toContain("pull/43");
|
||||
} finally {
|
||||
rmSync(fixture.workspace, { recursive: true });
|
||||
}
|
||||
});
|
||||
|
||||
it("preserves mixed-case changeset identifiers", () => {
|
||||
const fixture = createReleaseWithFollowUpCommit({
|
||||
uppercaseChangesetId: true,
|
||||
|
||||
Reference in New Issue
Block a user