Write release notification comments to PRs (#3622)

This commit is contained in:
Bart Louwers
2025-07-16 16:07:54 +02:00
committed by GitHub
parent a465aee324
commit 635c3727bb
4 changed files with 186 additions and 1 deletions

155
.github/scripts/notify-release-on-prs.ts vendored Normal file
View File

@@ -0,0 +1,155 @@
import { Octokit } from '@octokit/rest';
import { parseArgs } from 'node:util';
import * as core from "@actions/core";
const { values } = parseArgs({
options: {
tag: { type: 'string', short: 't' }
},
allowPositionals: false,
strict: true
});
function errMessage(err: unknown) {
return err instanceof Error ? err.message : `${err}`;
}
const owner = 'maplibre';
const repo = 'maplibre-native';
function extractPrNumbers(params: {
releaseBody: string;
owner: string;
repo: string;
}): Set<number> {
const { releaseBody, owner, repo } = params;
const prs = new Set<number>();
const esc = (s: string) => s.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
const urlRegex = new RegExp(
`https?:\\/\\/github\\.com\\/${esc(owner)}\\/${esc(repo)}\\/pull\\/(\\d+)`,
'g'
);
for (const match of releaseBody.matchAll(urlRegex)) {
prs.add(Number(match[1]));
}
return prs;
}
async function createOrUpdateReleaseNotification({
octokit,
prNumber,
tag,
owner,
repo
}: {
owner: string,
repo: string,
octokit: Octokit,
prNumber: number,
tag: string
}) {
const m = tag.match(/^([A-Za-z0-9]+)-v(.+)$/i);
const platform = m?.[1]?.toLowerCase();
const version = m?.[2] ?? '';
if (!platform || !version) {
throw new Error(`Failed to parse platform or version from ${tag}`);
}
const MARKER = `<!-- release-notification-${platform} -->`;
function linkText() {
if (platform === 'ios') {
return `MapLibre iOS ${version}`;
} else if (platform === 'android') {
return `MapLibre Android ${version}`;
}
return tag;
}
const { data: comments } = await octokit.issues.listComments({
owner,
repo,
issue_number: prNumber
});
const existing = comments.find((({ body }) => body?.includes(MARKER)));
const releaseUrl = `https://github.com/${owner}/${repo}/releases/tag/${tag}`;
releaseUrl
const body = `
${MARKER}
🚀 This PR has been included in the [${linkText()}](${releaseUrl}) release.
`.trim();
if (existing) {
await octokit.issues.updateComment({
owner,
repo,
comment_id: existing.id,
body
});
console.log(`Updated comment on PR #${prNumber}`);
} else {
await octokit.issues.createComment({
owner,
repo,
issue_number: prNumber,
body
});
console.log(`Created comment on PR #${prNumber}`);
}
}
try {
const { tag } = values;
if (!tag) {
throw new Error("pass tag with --tag");
}
const token = process.env.GITHUB_TOKEN;
if (!token) {
throw new Error('GITHUB_TOKEN environment variable is required');
}
const octokit = new Octokit({ auth: token });
const release = await octokit.repos.getReleaseByTag({ owner, repo, tag });
const releaseBody = release.data.body || '';
if (!releaseBody) {
throw new Error(`No release notes found for tag '${tag}'.`);
}
const prs = extractPrNumbers({
owner,
releaseBody,
repo
});
if (prs.size === 0) {
console.log(`No PR references found in release notes for tag '${tag}'.`);
process.exit(0);
}
for (const prNumber of prs) {
try {
await createOrUpdateReleaseNotification({
octokit,
owner,
prNumber,
repo,
tag
});
} catch (err) {
console.error(`Failed to comment on PR #${prNumber}: ${errMessage(err)}`);
}
}
} catch (err) {
core.setFailed(errMessage(err));
}