Compare commits

...

11 Commits

Author SHA1 Message Date
Joseph T Lyons
ccd8a9af89 v0.148.x stable 2024-08-14 12:45:44 -04:00
Joseph T Lyons
1dfc2fe1fa Fetch staff members from GitHub org 2024-08-11 15:10:50 -04:00
Joseph T Lyons
fb449399fc Don't thank staff members in release notes 2024-08-11 15:03:03 -04:00
Joseph T Lyons
5ec8cdcb3c Fix warning message 2024-08-11 14:49:55 -04:00
Joseph T Lyons
371b828d28 Fix warning message 2024-08-11 14:49:55 -04:00
Joseph T Lyons
fdb5c7fbd3 Update issue-detection RegEx 2024-08-11 14:45:56 -04:00
Joseph T Lyons
84d68660a3 Update the dangerfile to check for issue links 2024-08-11 14:45:56 -04:00
Joseph T Lyons
7e44cd04aa Fix isStaff boolean logic 2024-08-08 17:00:15 -04:00
Joseph T Lyons
7b8a87b61c Filter out staff members from thanks line 2024-08-08 16:26:51 -04:00
Joseph T. Lyons
79e5ea7210 Link to pull requests in changelog notes (#15996)
This PR changes how we ask users to draft up PRs and how release note
generation happens.

We no longer force the user to create the markdown URL link, but we do
ask them to use the `closes` [GitHub magic
word](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue)
to link the PR to an issue, so that the issue is closed automatically
when closing the PR.

As for the changelog release notes, we are no longer linking to the
issues, but the PR itself, which should contain the issue if a reader
wants to dive further back. This makes our output more consistent, as
every line will have a link, even if there is no issue associated, and
it removes the need for us to try to parse the issue url in the body to
try to correct mistakes in how they were forming Markdown urls - the PR
url is always returned in the request, which makes it easy. **Lastly,
it's just a lot less annoying to make the release notes.**

The new PR format will be:

```
Closes #ISSUE

Release Notes:

- Added/Fixed/Improved ...
```

The new script output format will be:

```
PR Title: theme: Use a non-transparent color for the fallback `title_bar.inactive_background`
Credit: ([#15709](https://github.com/zed-industries/zed/pull/15709); thanks [maxdeviant](https://github.com/maxdeviant))
Release Notes:

- linux: Changed the fallback color of `title_bar.inactive_background` to a non-transparent value.
--------------------------------------------------------------------------------
PR Title: Skip over folded regions when iterating over multibuffer chunks
Credit: ([#15646](https://github.com/zed-industries/zed/pull/15646); thanks [osiewicz](https://github.com/osiewicz))
Release Notes:

- Fixed poor performance when editing in the assistant panel after inserting large files using slash commands
--------------------------------------------------------------------------------
```

This still requires us to manually apply the credit line, but the line
is already fully formed, so this should still be faster than having to
manually create that line / fix any line where someone messed it up
(which was all the time). I would just automatically apply it to the
release notes, but sometimes we have multiple bullet points in a single
PR and no real structure is enforced, so I foresee doing anything
automatic breaking and needing manual adjustment.

Release Notes:

- N/A
2024-08-08 15:28:25 -04:00
Joseph T Lyons
822a4ccb6b v0.148.x preview 2024-08-07 10:59:06 -04:00
4 changed files with 91 additions and 43 deletions

View File

@@ -1,13 +1,15 @@
Closes #ISSUE
Release Notes:
- Added/Fixed/Improved ... ([#NNNNN](https://github.com/zed-industries/zed/issues/NNNNN)).
- Added/Fixed/Improved ...
Optionally, include screenshots / media showcasing your addition that can be included in the release notes.
### Or...
Closes #ISSUE
Release Notes:
- N/A

View File

@@ -1 +1 @@
dev
stable

View File

@@ -9,8 +9,10 @@ prHygiene({
});
const RELEASE_NOTES_PATTERN = new RegExp("Release Notes:\\r?\\n\\s+-", "gm");
const body = danger.github.pr.body;
const hasReleaseNotes = RELEASE_NOTES_PATTERN.test(body);
const hasReleaseNotes = RELEASE_NOTES_PATTERN.test(danger.github.pr.body);
if (!hasReleaseNotes) {
warn(
[
@@ -21,7 +23,7 @@ if (!hasReleaseNotes) {
"```",
"Release Notes:",
"",
"- (Added|Fixed|Improved) ... ([#<public_issue_number_if_exists>](https://github.com/zed-industries/zed/issues/<public_issue_number_if_exists>)).",
"- Added/Fixed/Improved ...",
"```",
"",
'If your change is not user-facing, you can use "N/A" for the entry:',
@@ -34,21 +36,28 @@ if (!hasReleaseNotes) {
);
}
const INCORRECT_ISSUE_LINK_PATTERN = new RegExp("-.*\\(#\\d+\\)", "g");
const hasIncorrectIssueLinks = INCORRECT_ISSUE_LINK_PATTERN.test(
danger.github.pr.body,
const ISSUE_LINK_PATTERN = new RegExp(
"(?:https://github\\.com/[\\w-]+/[\\w-]+/issues/\\d+|#\\d+)",
"g",
);
if (hasIncorrectIssueLinks) {
const includesIssueUrl = ISSUE_LINK_PATTERN.test(body);
if (includesIssueUrl) {
const matches = body.match(ISSUE_LINK_PATTERN);
const issues = matches
.map((match) =>
match
.replace(/^#/, "")
.replace(/https:\/\/github\.com\/zed-industries\/zed\/issues\//, ""),
)
.filter((issue, index, self) => self.indexOf(issue) === index);
warn(
[
"This PR has incorrectly formatted GitHub issue links in the release notes.",
"",
"GitHub issue links must be formatted as plain Markdown links:",
"",
"```",
"- Improved something ([#ISSUE](https://github.com/zed-industries/zed/issues/ISSUE)).",
"```",
"This PR includes links to the following GitHub Issues: " +
issues.map((issue) => `#${issue}`).join(", "),
"If this PR aims to close an issue, please include a `Closes #ISSUE` line at the top of the PR body.",
].join("\n"),
);
}

View File

@@ -1,12 +1,38 @@
#!/usr/bin/env node --redirect-warnings=/dev/null
const { execFileSync } = require("child_process");
let { GITHUB_ACCESS_TOKEN } = process.env;
const FIXES_REGEX = /(fixes|closes|completes) (.+[/#]\d+.*)$/im;
const { GITHUB_ACCESS_TOKEN } = process.env;
const GITHUB_URL = "https://github.com";
const SKIPPABLE_NOTE_REGEX = /^\s*-?\s*n\/?a\s*/ims;
const PULL_REQUEST_WEB_URL = "https://github.com/zed-industries/zed/pull";
const PULL_REQUEST_API_URL =
"https://api.github.com/repos/zed-industries/zed/pulls";
const DIVIDER = "-".repeat(80);
main();
async function main() {
const STAFF_MEMBERS = new Set(
(
await (
await fetch(
"https://api.github.com/orgs/zed-industries/teams/staff/members",
{
headers: {
Authorization: `token ${GITHUB_ACCESS_TOKEN}`,
Accept: "application/vnd.github+json",
},
},
)
).json()
).map(({ login }) => login.toLowerCase()),
);
const isStaffMember = (githubHandle) => {
githubHandle = githubHandle.toLowerCase();
return STAFF_MEMBERS.has(githubHandle);
};
// Get the last two preview tags
const [newTag, oldTag] = execFileSync(
"git",
@@ -44,51 +70,62 @@ async function main() {
// Fetch the pull requests from the GitHub API.
console.log("Merged Pull requests:");
console.log(DIVIDER);
for (const pullRequestNumber of newPullRequestNumbers) {
const webURL = `https://github.com/zed-industries/zed/pull/${pullRequestNumber}`;
const apiURL = `https://api.github.com/repos/zed-industries/zed/pulls/${pullRequestNumber}`;
const pullRequestApiURL = `${PULL_REQUEST_API_URL}/${pullRequestNumber}`;
const response = await fetch(apiURL, {
const response = await fetch(pullRequestApiURL, {
headers: {
Authorization: `token ${GITHUB_ACCESS_TOKEN}`,
},
});
// Print the pull request title and URL.
const pullRequest = await response.json();
const releaseNotesHeader = /^\s*Release Notes:(.+)/ims;
let releaseNotes = pullRequest.body || "";
let contributor = pullRequest.user?.login ?? "Unable to identify";
const releaseNotes = pullRequest.body || "";
let contributor =
pullRequest.user?.login ?? "Unable to identify contributor";
const captures = releaseNotesHeader.exec(releaseNotes);
const notes = captures ? captures[1] : "MISSING";
const skippableNoteRegex = /^\s*-?\s*n\/?a\s*/ims;
let notes = captures ? captures[1] : "MISSING";
notes = notes.trim();
const isStaff = isStaffMember(contributor);
if (skippableNoteRegex.exec(notes) != null) {
if (SKIPPABLE_NOTE_REGEX.exec(notes) != null) {
continue;
}
console.log("*", pullRequest.title);
console.log(" PR URL: ", webURL);
console.log(" Author: ", contributor);
// If the pull request contains a 'closes' line, print the closed issue.
const fixesMatch = (pullRequest.body || "").match(FIXES_REGEX);
if (fixesMatch) {
const fixedIssueURL = fixesMatch[2];
console.log(" Issue URL: ", fixedIssueURL);
}
const credit = getCreditString(pullRequestNumber, contributor, isStaff);
contributor = isStaff ? `${contributor} (staff)` : contributor;
releaseNotes = notes.trim().split("\n");
console.log(" Release Notes:");
for (const line of releaseNotes) {
console.log(` ${line}`);
}
console.log(`PR Title: ${pullRequest.title}`);
console.log(`Contributor: ${contributor}`);
console.log(`Credit: (${credit})`);
console.log("Release Notes:");
console.log();
console.log(notes);
console.log(DIVIDER);
}
}
function getCreditString(pullRequestNumber, contributor, isStaff) {
let credit = "";
if (pullRequestNumber) {
const pullRequestMarkdownLink = `[#${pullRequestNumber}](${PULL_REQUEST_WEB_URL}/${pullRequestNumber})`;
credit += pullRequestMarkdownLink;
}
if (contributor && !isStaff) {
const contributorMarkdownLink = `[${contributor}](${GITHUB_URL}/${contributor})`;
credit += `; thanks ${contributorMarkdownLink}`;
}
return credit;
}
function getPullRequestNumbers(oldTag, newTag) {
const pullRequestNumbers = execFileSync(
"git",