From cfb9fc4642c8b0e13892159eb119f871122f34a7 Mon Sep 17 00:00:00 2001 From: Chad Hietala Date: Wed, 28 Oct 2026 11:20:50 -0400 Subject: [PATCH 1/3] fix(release): resolve stacked changeset pull requests Signed-off-by: Chad Hietala --- scripts/changeset-format.test.mjs | 10 ++++++++-- scripts/changeset-github.mjs | 6 +++--- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/scripts/changeset-format.test.mjs b/scripts/changeset-format.test.mjs index 11e199f979..9c99134f9c 100644 --- a/scripts/changeset-format.test.mjs +++ b/scripts/changeset-format.test.mjs @@ -114,7 +114,8 @@ test("the Changesets formatter produces readable Markdown without encoded metada title: "Edited title without a category", user: { login: "Alice" }, merged_at: "2026-01-01", - base: { ref: "main" }, + base: { ref: "topic-branch" }, + merge_commit_sha: commit, }, ]), ), @@ -210,7 +211,12 @@ test("version-packages assembles changesets across bump types and preserves old git("commit", "-qm", "Legacy change"); await write( "mock-github.mjs", - `globalThis.fetch = async (url) => new Response(JSON.stringify([{number: url.includes(${JSON.stringify(first)}) ? 10 : url.includes(${JSON.stringify(second)}) ? 11 : 12, title: "Edited title", user: {login: "Author"}, merged_at: "2026-01-01", base: {ref: "main"}}]), {status: 200});`, + `globalThis.fetch = async (url) => { + const commit = url.split("/").at(-2); + const pull = {number: commit === ${JSON.stringify(first)} ? 10 : commit === ${JSON.stringify(second)} ? 11 : 12, title: "Edited title", user: {login: "Author"}, merged_at: "2026-01-01", base: {ref: commit === ${JSON.stringify(second)} ? "topic-branch" : "main"}, merge_commit_sha: commit}; + const other = {number: 99, user: {login: "Other"}, merged_at: "2026-01-02", base: {ref: "main"}, merge_commit_sha: "another-commit"}; + return new Response(JSON.stringify(commit === ${JSON.stringify(second)} ? [other, pull] : [pull]), {status: 200}); + };`, ); assert.throws(() => execFileSync(process.execPath, ["scripts/check-release-pr-title.mjs"], { diff --git a/scripts/changeset-github.mjs b/scripts/changeset-github.mjs index f4ac2bd4cb..b9b9f5bd2a 100644 --- a/scripts/changeset-github.mjs +++ b/scripts/changeset-github.mjs @@ -17,9 +17,9 @@ export async function pullRequestFor(commit, id) { throw new Error( `GitHub pull request lookup for changeset ${id} failed: HTTP ${response.status}.`, ); - const pulls = (await response.json()).filter( - (pull) => pull.merged_at && pull.base?.ref === "main", - ); + const merged = (await response.json()).filter((pull) => pull.merged_at); + const matches = merged.filter((pull) => pull.merge_commit_sha === commit); + const pulls = matches.length ? matches : merged; if (pulls.length !== 1) throw new Error( `Changeset ${id}: expected one merged pull request for commit ${commit}, found ${pulls.length}.`, From 116faec89be0b09c8ef6c93443e181b6ff85d730 Mon Sep 17 00:00:00 2001 From: Chad Hietala Date: Wed, 28 Oct 2026 11:22:24 -0400 Subject: [PATCH 2/3] test(release): cover ambiguous pull request lookup Signed-off-by: Chad Hietala --- scripts/changeset-format.test.mjs | 48 ++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/scripts/changeset-format.test.mjs b/scripts/changeset-format.test.mjs index 9c99134f9c..6230394099 100644 --- a/scripts/changeset-format.test.mjs +++ b/scripts/changeset-format.test.mjs @@ -103,23 +103,17 @@ test("the Changesets formatter produces readable Markdown without encoded metada if (oldToken === undefined) delete process.env.GITHUB_TOKEN; else process.env.GITHUB_TOKEN = oldToken; }); - t.mock.method( - globalThis, - "fetch", - async () => - new Response( - JSON.stringify([ - { - number: 10, - title: "Edited title without a category", - user: { login: "Alice" }, - merged_at: "2026-01-01", - base: { ref: "topic-branch" }, - merge_commit_sha: commit, - }, - ]), - ), - ); + let pulls = [ + { + number: 10, + title: "Edited title without a category", + user: { login: "Alice" }, + merged_at: "2026-01-01", + base: { ref: "topic-branch" }, + merge_commit_sha: commit, + }, + ]; + t.mock.method(globalThis, "fetch", async () => new Response(JSON.stringify(pulls))); const line = await formatter.getReleaseLine({ id: "example", summary: "Add a tool.", commit }); assert.match( line, @@ -127,6 +121,26 @@ test("the Changesets formatter produces readable Markdown without encoded metada ); assert.match(line, /#### Contributors\n\n- \[@Alice\]\(https:\/\/github\.com\/Alice\)/u); assert.doesNotMatch(line, /