Skip to content

Commit 13e5c01

Browse files
Feature/20 add new warning chapter for merged p rs linking opened issues (#21)
* Add new logic to detect PRs linking to Issue in Open state. * Updated titles and defaults messages of warning chapters.
1 parent d4cdfa9 commit 13e5c01

File tree

2 files changed

+130
-10
lines changed

2 files changed

+130
-10
lines changed

dist/index.js

Lines changed: 65 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31078,14 +31078,68 @@ async function getReleaseNotesFromComments(octokit, issueNumber, issueTitle, iss
3107831078
* @returns {Promise<boolean>} True if the pull request is linked to an issue, false otherwise.
3107931079
*/
3108031080
async function isPrLinkedToIssue(octokit, prNumber, repoOwner, repoName) {
31081+
// Get the pull request details
3108131082
const pr = await octokit.rest.pulls.get({
3108231083
owner: repoOwner,
3108331084
repo: repoName,
3108431085
pull_number: prNumber
3108531086
});
31086-
return /#\d+/.test(pr.data.body);
31087+
31088+
// Regex pattern to find references to issues
31089+
const regexPattern = /([Cc]los(e|es|ed)|[Ff]ix(es|ed)?|[Rr]esolv(e|es|ed))\s*#\s*([0-9]+)/g;
31090+
31091+
// Test if the PR body contains any issue references
31092+
return regexPattern.test(pr.data.body);
31093+
}
31094+
31095+
31096+
/**
31097+
* Checks if a pull request is linked to any open issues.
31098+
* @param {Octokit} octokit - The Octokit instance.
31099+
* @param {number} prNumber - The pull request number.
31100+
* @param {string} repoOwner - The owner of the repository.
31101+
* @param {string} repoName - The name of the repository.
31102+
* @returns {Promise<boolean>} True if the pull request is linked to any open issue, false otherwise.
31103+
*/
31104+
async function isPrLinkedToOpenIssue(octokit, prNumber, repoOwner, repoName) {
31105+
// Get the pull request details
31106+
const pr = await octokit.rest.pulls.get({
31107+
owner: repoOwner,
31108+
repo: repoName,
31109+
pull_number: prNumber
31110+
});
31111+
31112+
// Regex pattern to find references to issues
31113+
const regexPattern = /([Cc]los(e|es|ed)|[Ff]ix(es|ed)?|[Rr]esolv(e|es|ed))\s*#\s*([0-9]+)/g;
31114+
31115+
// Extract all issue numbers from the PR body
31116+
const issueMatches = pr.data.body.match(regexPattern);
31117+
if (!issueMatches) {
31118+
return false; // No issue references found in PR body
31119+
}
31120+
31121+
// Check each linked issue
31122+
for (const match of issueMatches) {
31123+
const issueNumber = match.match(/#([0-9]+)/)[1];
31124+
31125+
// Get the issue details
31126+
const issue = await octokit.rest.issues.get({
31127+
owner: repoOwner,
31128+
repo: repoName,
31129+
issue_number: issueNumber
31130+
});
31131+
31132+
// If any of the issues is open, return true
31133+
if (issue.data.state === 'open') {
31134+
return true;
31135+
}
31136+
}
31137+
31138+
// If none of the issues are open, return false
31139+
return false;
3108731140
}
3108831141

31142+
3108931143
/**
3109031144
* Parses the JSON string of chapters into a map.
3109131145
* @param {string} chaptersJson - The JSON string of chapters.
@@ -31211,6 +31265,7 @@ async function run() {
3121131265
const titlesToLabelsMap = parseChaptersJson(chaptersJson);
3121231266
const chapterContents = new Map(Array.from(titlesToLabelsMap.keys()).map(label => [label, '']));
3121331267
let issuesWithoutReleaseNotes = '', issuesWithoutUserLabels = '', issuesWithoutPR = '', prsWithoutLinkedIssue = '';
31268+
let prsLinkedToOpenIssue = '';
3121431269

3121531270
// Categorize issues and PRs
3121631271
for (const issue of closedIssuesOnlyIssues) {
@@ -31257,6 +31312,10 @@ async function run() {
3125731312
for (const pr of sortedPRs) {
3125831313
if (!await isPrLinkedToIssue(octokit, pr.number, repoOwner, repoName)) {
3125931314
prsWithoutLinkedIssue += `#${pr.number} _${pr.title}_\n`;
31315+
} else {
31316+
if (await isPrLinkedToOpenIssue(octokit, pr.number, repoOwner, repoName)) {
31317+
prsLinkedToOpenIssue += `#${pr.number} _${pr.title}_\n`;
31318+
}
3126031319
}
3126131320
}
3126231321
}
@@ -31280,10 +31339,11 @@ async function run() {
3128031339
});
3128131340

3128231341
if (warnings) {
31283-
releaseNotes += "### Issues without Pull Request ⚠️\n" + (issuesWithoutPR || "All issues linked to a Pull Request.") + "\n\n";
31284-
releaseNotes += "### Issues without User Defined Labels ⚠️\n" + (issuesWithoutUserLabels || "All issues contain at least one of user defined labels.") + "\n\n";
31285-
releaseNotes += "### Issues without Release Notes ⚠️\n" + (issuesWithoutReleaseNotes || "All issues have release notes.") + "\n\n";
31286-
releaseNotes += "### PRs without Linked Issue ⚠️\n" + (prsWithoutLinkedIssue || "All PRs are linked to issues.") + "\n\n";
31342+
releaseNotes += "### Closed Issues without Pull Request ⚠️\n" + (issuesWithoutPR || "All closed issues linked to a Pull Request.") + "\n\n";
31343+
releaseNotes += "### Closed Issues without User Defined Labels ⚠️\n" + (issuesWithoutUserLabels || "All closed issues contain at least one of user defined labels.") + "\n\n";
31344+
releaseNotes += "### Closed Issues without Release Notes ⚠️\n" + (issuesWithoutReleaseNotes || "All closed issues have release notes.") + "\n\n";
31345+
releaseNotes += "### Merged PRs without Linked Issue ⚠️\n" + (prsWithoutLinkedIssue || "All merged PRs are linked to issues.") + "\n\n";
31346+
releaseNotes += "### Merged PRs Linked to Open Issue ⚠️\n" + (prsLinkedToOpenIssue || "All merged PRs are linked to Closed issues.") + "\n\n";
3128731347
}
3128831348
releaseNotes += "#### Full Changelog\n" + changelogUrl;
3128931349

scripts/generate-release-notes.js

Lines changed: 65 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -175,14 +175,68 @@ async function getReleaseNotesFromComments(octokit, issueNumber, issueTitle, iss
175175
* @returns {Promise<boolean>} True if the pull request is linked to an issue, false otherwise.
176176
*/
177177
async function isPrLinkedToIssue(octokit, prNumber, repoOwner, repoName) {
178+
// Get the pull request details
178179
const pr = await octokit.rest.pulls.get({
179180
owner: repoOwner,
180181
repo: repoName,
181182
pull_number: prNumber
182183
});
183-
return /#\d+/.test(pr.data.body);
184+
185+
// Regex pattern to find references to issues
186+
const regexPattern = /([Cc]los(e|es|ed)|[Ff]ix(es|ed)?|[Rr]esolv(e|es|ed))\s*#\s*([0-9]+)/g;
187+
188+
// Test if the PR body contains any issue references
189+
return regexPattern.test(pr.data.body);
190+
}
191+
192+
193+
/**
194+
* Checks if a pull request is linked to any open issues.
195+
* @param {Octokit} octokit - The Octokit instance.
196+
* @param {number} prNumber - The pull request number.
197+
* @param {string} repoOwner - The owner of the repository.
198+
* @param {string} repoName - The name of the repository.
199+
* @returns {Promise<boolean>} True if the pull request is linked to any open issue, false otherwise.
200+
*/
201+
async function isPrLinkedToOpenIssue(octokit, prNumber, repoOwner, repoName) {
202+
// Get the pull request details
203+
const pr = await octokit.rest.pulls.get({
204+
owner: repoOwner,
205+
repo: repoName,
206+
pull_number: prNumber
207+
});
208+
209+
// Regex pattern to find references to issues
210+
const regexPattern = /([Cc]los(e|es|ed)|[Ff]ix(es|ed)?|[Rr]esolv(e|es|ed))\s*#\s*([0-9]+)/g;
211+
212+
// Extract all issue numbers from the PR body
213+
const issueMatches = pr.data.body.match(regexPattern);
214+
if (!issueMatches) {
215+
return false; // No issue references found in PR body
216+
}
217+
218+
// Check each linked issue
219+
for (const match of issueMatches) {
220+
const issueNumber = match.match(/#([0-9]+)/)[1];
221+
222+
// Get the issue details
223+
const issue = await octokit.rest.issues.get({
224+
owner: repoOwner,
225+
repo: repoName,
226+
issue_number: issueNumber
227+
});
228+
229+
// If any of the issues is open, return true
230+
if (issue.data.state === 'open') {
231+
return true;
232+
}
233+
}
234+
235+
// If none of the issues are open, return false
236+
return false;
184237
}
185238

239+
186240
/**
187241
* Parses the JSON string of chapters into a map.
188242
* @param {string} chaptersJson - The JSON string of chapters.
@@ -308,6 +362,7 @@ async function run() {
308362
const titlesToLabelsMap = parseChaptersJson(chaptersJson);
309363
const chapterContents = new Map(Array.from(titlesToLabelsMap.keys()).map(label => [label, '']));
310364
let issuesWithoutReleaseNotes = '', issuesWithoutUserLabels = '', issuesWithoutPR = '', prsWithoutLinkedIssue = '';
365+
let prsLinkedToOpenIssue = '';
311366

312367
// Categorize issues and PRs
313368
for (const issue of closedIssuesOnlyIssues) {
@@ -354,6 +409,10 @@ async function run() {
354409
for (const pr of sortedPRs) {
355410
if (!await isPrLinkedToIssue(octokit, pr.number, repoOwner, repoName)) {
356411
prsWithoutLinkedIssue += `#${pr.number} _${pr.title}_\n`;
412+
} else {
413+
if (await isPrLinkedToOpenIssue(octokit, pr.number, repoOwner, repoName)) {
414+
prsLinkedToOpenIssue += `#${pr.number} _${pr.title}_\n`;
415+
}
357416
}
358417
}
359418
}
@@ -377,10 +436,11 @@ async function run() {
377436
});
378437

379438
if (warnings) {
380-
releaseNotes += "### Issues without Pull Request ⚠️\n" + (issuesWithoutPR || "All issues linked to a Pull Request.") + "\n\n";
381-
releaseNotes += "### Issues without User Defined Labels ⚠️\n" + (issuesWithoutUserLabels || "All issues contain at least one of user defined labels.") + "\n\n";
382-
releaseNotes += "### Issues without Release Notes ⚠️\n" + (issuesWithoutReleaseNotes || "All issues have release notes.") + "\n\n";
383-
releaseNotes += "### PRs without Linked Issue ⚠️\n" + (prsWithoutLinkedIssue || "All PRs are linked to issues.") + "\n\n";
439+
releaseNotes += "### Closed Issues without Pull Request ⚠️\n" + (issuesWithoutPR || "All closed issues linked to a Pull Request.") + "\n\n";
440+
releaseNotes += "### Closed Issues without User Defined Labels ⚠️\n" + (issuesWithoutUserLabels || "All closed issues contain at least one of user defined labels.") + "\n\n";
441+
releaseNotes += "### Closed Issues without Release Notes ⚠️\n" + (issuesWithoutReleaseNotes || "All closed issues have release notes.") + "\n\n";
442+
releaseNotes += "### Merged PRs without Linked Issue ⚠️\n" + (prsWithoutLinkedIssue || "All merged PRs are linked to issues.") + "\n\n";
443+
releaseNotes += "### Merged PRs Linked to Open Issue ⚠️\n" + (prsLinkedToOpenIssue || "All merged PRs are linked to Closed issues.") + "\n\n";
384444
}
385445
releaseNotes += "#### Full Changelog\n" + changelogUrl;
386446

0 commit comments

Comments
 (0)