@@ -22,12 +22,12 @@ async function main() {
const startDate = new Date(process.argv[2]);
const today = new Date();
- console.log(`Changes from ${startDate} to ${today}\n`);
+ console.log(`Pull requests from ${startDate} to ${today}\n`);
let pullRequestNumbers = getPullRequestNumbers(startDate, today);
// Fetch the pull requests from the GitHub API.
- console.log("Merged Pull requests:");
+ console.log("Merged pull requests:");
for (const pullRequestNumber of pullRequestNumbers) {
const webURL = `https://github.com/zed-industries/zed/pull/${pullRequestNumber}`;
const apiURL = `https://api.github.com/repos/zed-industries/zed/pulls/${pullRequestNumber}`;
@@ -0,0 +1,125 @@
+#!/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;
+}