diff --git a/scripts/sync-release-notes-from-changelog.mjs b/scripts/sync-release-notes-from-changelog.mjs index 891b87713..30cb00a2b 100644 --- a/scripts/sync-release-notes-from-changelog.mjs +++ b/scripts/sync-release-notes-from-changelog.mjs @@ -139,6 +139,19 @@ function updateReleaseNotes({ releaseId, repo, notesPath }, execFileSync = nodeE ); } +function exposeGitHubContributorMentions(notes) { + return notes.replace( + /\[@([A-Za-z0-9-]+)\]\(https:\/\/github\.com\/([A-Za-z0-9-]+)\/?\)/g, + (match, labelLogin, profileLogin) => { + if (labelLogin.toLowerCase() !== profileLogin.toLowerCase()) { + return match; + } + + return `@${profileLogin}`; + }, + ); +} + export function syncReleaseNotes(argv = process.argv.slice(2), deps = {}) { const execFileSync = deps.execFileSync ?? nodeExecFileSync; const args = parseArgs(argv); @@ -157,6 +170,8 @@ export function syncReleaseNotes(argv = process.argv.slice(2), deps = {}) { return; } + notes = exposeGitHubContributorMentions(notes); + const tempDir = mkdtempSync(path.join(tmpdir(), "paseo-release-notes-")); const notesPath = path.join(tempDir, `${targetTag}-notes.md`); writeFileSync(notesPath, notes); diff --git a/scripts/sync-release-notes-from-changelog.test.mjs b/scripts/sync-release-notes-from-changelog.test.mjs index 534ec9df6..6fc27f4d2 100644 --- a/scripts/sync-release-notes-from-changelog.test.mjs +++ b/scripts/sync-release-notes-from-changelog.test.mjs @@ -1,15 +1,15 @@ import assert from "node:assert/strict"; -import { mkdtempSync, rmSync, writeFileSync } from "node:fs"; +import { mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import path from "node:path"; import test from "node:test"; import { syncReleaseNotes } from "./sync-release-notes-from-changelog.mjs"; -function withTempChangelog(fn) { +function withTempChangelog(fn, changelogText = "## 0.1.60-beta.1 - 2026-04-20\n\n- Beta notes.\n") { const previousCwd = process.cwd(); const tempDir = mkdtempSync(path.join(tmpdir(), "paseo-release-notes-test-")); process.chdir(tempDir); - writeFileSync("CHANGELOG.md", "## 0.1.60-beta.1 - 2026-04-20\n\n- Beta notes.\n"); + writeFileSync("CHANGELOG.md", changelogText); try { fn(); @@ -63,3 +63,38 @@ test("updates an existing release body through the release id API", () => { ); }); }); + +test("converts contributor profile links to mentions in synced release notes", () => { + const changelogText = [ + "## 0.1.60-beta.1 - 2026-04-20", + "", + "- Beta notes. ([#526](https://github.com/getpaseo/paseo/pull/526) by [@therainisme](https://github.com/therainisme))", + "", + ].join("\n"); + + withTempChangelog(() => { + let syncedNotes = ""; + + const execFileSync = (command, args) => { + if (args[0] === "api" && args[1] === "repos/getpaseo/paseo/releases/tags/v0.1.60-beta.1") { + return JSON.stringify({ id: 311163621 }); + } + + if (args[0] === "api" && args[1] === "-X" && args[2] === "PATCH") { + const notesArg = args.find((arg) => arg.startsWith("body=@")); + assert.ok(notesArg, "PATCH should send the notes body from a file"); + syncedNotes = readFileSync(notesArg.slice("body=@".length), "utf8"); + return ""; + } + + throw new Error(`Unexpected gh call: ${command} ${args.join(" ")}`); + }; + + syncReleaseNotes(["--repo", "getpaseo/paseo", "--tag", "v0.1.60-beta.1"], { + execFileSync, + }); + + assert.match(syncedNotes, /by @therainisme\)/); + assert.doesNotMatch(syncedNotes, /\[@therainisme\]\(https:\/\/github\.com\/therainisme\)/); + }, changelogText); +});