zed/script/get-release-notes-since
Joseph T. Lyons 6d4ecac610
Add a get-release-notes-since script (#18445)
Release Notes:

- N/A
2024-09-27 10:59:19 -04:00

125 lines
3.3 KiB
JavaScript
Executable file

#!/usr/bin/env node --redirect-warnings=/dev/null
const { execFileSync } = require("child_process");
const { GITHUB_ACCESS_TOKEN } = process.env;
main();
async function main() {
const startDate = new Date(process.argv[2]);
const today = new Date();
console.log(`Release notes from ${startDate} to ${today}\n`);
const releases = await getReleases(startDate, today);
const previewReleases = releases.filter((release) =>
release.tagName.includes("-pre"),
);
const stableReleases = releases.filter(
(release) => !release.tagName.includes("-pre"),
);
// Filter out all preview release, as all of those changes have made it to the stable release, except for the latest preview release
const aggregatedReleases = stableReleases
.concat(previewReleases[0])
.reverse();
const aggregatedReleaseTitles = aggregatedReleases
.map((release) => release.name)
.join(", ");
console.log();
console.log(`Release titles: ${aggregatedReleaseTitles}`);
console.log("Release notes:");
console.log();
for (const release of aggregatedReleases) {
const publishedDate = release.publishedAt.split("T")[0];
console.log(`${release.name}: ${publishedDate}`);
console.log();
console.log(release.description);
console.log();
}
}
async function getReleases(startDate, endDate) {
const query = `
query ($owner: String!, $repo: String!, $cursor: String) {
repository(owner: $owner, name: $repo) {
releases(first: 100, orderBy: {field: CREATED_AT, direction: DESC}, after: $cursor) {
nodes {
tagName
name
createdAt
publishedAt
description
url
author {
login
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
}
`;
let allReleases = [];
let hasNextPage = true;
let cursor = null;
while (hasNextPage) {
const response = await fetch("https://api.github.com/graphql", {
method: "POST",
headers: {
Authorization: `Bearer ${GITHUB_ACCESS_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
query,
variables: { owner: "zed-industries", repo: "zed", cursor },
}),
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
if (data.errors) {
throw new Error(`GraphQL error: ${JSON.stringify(data.errors)}`);
}
if (!data.data || !data.data.repository || !data.data.repository.releases) {
throw new Error(`Unexpected response structure: ${JSON.stringify(data)}`);
}
const releases = data.data.repository.releases.nodes;
allReleases = allReleases.concat(releases);
hasNextPage = data.data.repository.releases.pageInfo.hasNextPage;
cursor = data.data.repository.releases.pageInfo.endCursor;
lastReleaseOnPage = releases[releases.length - 1];
if (
releases.length > 0 &&
new Date(lastReleaseOnPage.createdAt) < startDate
) {
break;
}
}
const filteredReleases = allReleases.filter((release) => {
const releaseDate = new Date(release.createdAt);
return releaseDate >= startDate && releaseDate <= endDate;
});
return filteredReleases;
}