Merge pull request #728 from mikepenz/feature/720

Introduce new API offering the ability to fetch reviewers who approved PRs
This commit is contained in:
Mike Penz
2022-04-15 10:33:05 +02:00
committed by GitHub
15 changed files with 200 additions and 25 deletions
+16 -14
View File
@@ -268,6 +268,7 @@ For advanced use cases additional settings can be provided to the action
| `includeOpen` | Enables to also fetch currently open PRs. Default: false |
| `ignorePreReleases` | Allows to ignore pre-releases for changelog generation (E.g. for 1.0.1... 1.0.0-rc02 <- ignore, 1.0.0 <- pick). Only used if `fromTag` was not specified. Default: false |
| `failOnError` | Defines if the action will result in a build failure if problems occurred. Default: false |
| `fetchReviewers` | Will enable fetching the users/reviewers who approved the PR. Default: false |
| `commitMode` | Special configuration for projects which work without PRs. Uses commit messages as changelog. This mode looses access to information only available for PRs. Default: false |
💡 `${{ secrets.GITHUB_TOKEN }}` only grants rights to the current repository, for other repositories please use a PAT (Personal Access Token).
@@ -276,21 +277,22 @@ For advanced use cases additional settings can be provided to the action
Table of supported placeholders allowed to be used in the `pr_template` configuration, which will be included in the release notes / changelog.
| **Placeholder** | **Description** |
|-------------------|-------------------------------------------------------------|
| `${{NUMBER}}` | The number referencing this pull request. E.g. 13 |
| `${{TITLE}}` | Specified title of the merged pull request |
| `${{URL}}` | Url linking to the pull request on GitHub |
| **Placeholder** | **Description** |
|-------------------|-------------------------------------------------------------------|
| `${{NUMBER}}` | The number referencing this pull request. E.g. 13 |
| `${{TITLE}}` | Specified title of the merged pull request |
| `${{URL}}` | Url linking to the pull request on GitHub |
| `${{STATUS}}` | Status of the PR. Usually always `merged`. Possibly `Open` if `includeOpen` is configured. |
| `${{CREATED_AT}}` | The ISO time, the pull request was created at |
| `${{MERGED_AT}}` | The ISO time, the pull request was merged at |
| `${{MERGE_SHA}}` | The commit SHA, the pull request was merged with |
| `${{AUTHOR}}` | Author creating and opening the pull request |
| `${{LABELS}}` | The labels associated with this pull request, joined by `,` |
| `${{MILESTONE}}` | Milestone this PR was part of, as assigned on GitHub |
| `${{BODY}}` | Description/Body of the pull request as specified on GitHub |
| `${{ASSIGNEES}}` | Login names of assigned GitHub users, joined by `,` |
| `${{REVIEWERS}}` | GitHub Login names of specified reviewers, joined by `,` |
| `${{CREATED_AT}}` | The ISO time, the pull request was created at |
| `${{MERGED_AT}}` | The ISO time, the pull request was merged at |
| `${{MERGE_SHA}}` | The commit SHA, the pull request was merged with |
| `${{AUTHOR}}` | Author creating and opening the pull request |
| `${{LABELS}}` | The labels associated with this pull request, joined by `,` |
| `${{MILESTONE}}` | Milestone this PR was part of, as assigned on GitHub |
| `${{BODY}}` | Description/Body of the pull request as specified on GitHub |
| `${{ASSIGNEES}}` | Login names of assigned GitHub users, joined by `,` |
| `${{REVIEWERS}}` | GitHub Login names of specified reviewers, joined by `,` |
| `${{APPROVERS}}` | GitHub Login names of users who approved the PR, joined by `,` |
### Template placeholders
+8
View File
@@ -18,6 +18,7 @@ it('Should have empty changelog (tags)', async () => {
toTag: 'v0.0.2',
includeOpen: false,
failOnError: false,
fetchReviewers: false,
commitMode: false,
configuration
})
@@ -36,6 +37,7 @@ it('Should match generated changelog (tags)', async () => {
toTag: 'v0.0.3',
includeOpen: false,
failOnError: false,
fetchReviewers: false,
commitMode: false,
configuration
})
@@ -62,6 +64,7 @@ it('Should match generated changelog (refs)', async () => {
toTag: 'fa3788c8c4b3373ef8424ce3eb008a5cd07cc5aa',
includeOpen: false,
failOnError: false,
fetchReviewers: false,
commitMode: false,
configuration
})
@@ -96,6 +99,7 @@ it('Should match generated changelog and replace all occurrences (refs)', async
toTag: 'fa3788c8c4b3373ef8424ce3eb008a5cd07cc5aa',
includeOpen: false,
failOnError: false,
fetchReviewers: false,
commitMode: false,
configuration
})
@@ -132,6 +136,7 @@ it('Should match ordered ASC', async () => {
toTag: 'v0.5.0',
includeOpen: false,
failOnError: false,
fetchReviewers: false,
commitMode: false,
configuration
})
@@ -155,6 +160,7 @@ it('Should match ordered DESC', async () => {
toTag: 'v0.5.0',
includeOpen: false,
failOnError: false,
fetchReviewers: false,
commitMode: false,
configuration
})
@@ -178,6 +184,7 @@ it('Should ignore PRs not merged into develop branch', async () => {
toTag: 'v1.4.0',
includeOpen: false,
failOnError: false,
fetchReviewers: false,
commitMode: false,
configuration
})
@@ -199,6 +206,7 @@ it('Should ignore PRs not merged into main branch', async () => {
toTag: 'v1.4.0',
includeOpen: false,
failOnError: false,
fetchReviewers: false,
commitMode: false,
configuration
})
+39
View File
@@ -16,6 +16,7 @@ it('Should match generated changelog (unspecified fromTag)', async () => {
false,
false,
false,
false, // enable to fetch reviewers
false,
configuration
)
@@ -43,6 +44,7 @@ it('Should match generated changelog (unspecified tags)', async () => {
false,
false,
false,
false, // enable to fetch reviewers
false,
configuration
)
@@ -67,6 +69,7 @@ it('Should use empty placeholder', async () => {
false,
false,
false,
false, // enable to fetch reviewers
false,
configuration
)
@@ -92,6 +95,7 @@ it('Should fill empty placeholders', async () => {
false,
false,
false,
false, // enable to fetch reviewers
false,
configuration
)
@@ -119,6 +123,7 @@ it('Should fill `template` placeholders', async () => {
false,
false,
false,
false, // enable to fetch reviewers
false,
configuration
)
@@ -146,6 +151,7 @@ it('Should fill `template` placeholders, ignore', async () => {
false,
false,
false,
false, // enable to fetch reviewers
false,
configuration
)
@@ -173,6 +179,7 @@ it('Uncategorized category', async () => {
false,
false,
false,
false, // enable to fetch reviewers
false,
configuration
)
@@ -200,6 +207,7 @@ it('Verify commit based changelog', async () => {
false,
false,
false,
false, // enable to fetch reviewers
true,
configuration
)
@@ -227,6 +235,7 @@ it('Verify commit based changelog, with emoji categorisation', async () => {
false,
false,
false,
false, // enable to fetch reviewers
true,
configuration
)
@@ -254,6 +263,7 @@ it('Verify default inclusion of open PRs', async () => {
true, // includeOpen
false, // failOnError
false, // ignorePrePrelease
false, // enable to fetch reviewers
false, // commitMode
configuration // configuration
)
@@ -281,6 +291,7 @@ it('Verify custom categorisation of open PRs', async () => {
true, // includeOpen
false, // failOnError
false, // ignorePrePrelease
false, // enable to fetch reviewers
false, // commitMode
configuration // configuration
)
@@ -291,3 +302,31 @@ it('Verify custom categorisation of open PRs', async () => {
`## 🚀 Features Merged\n\n- A feature to be going to v2 (nr3) -- (#3) [merged] {feature}\n\n## 🚀 Features Open\n\n- New feature to keep open (nr5) -- (#7) [open] {feature}\n\n`
)
})
it('Verify reviewers who approved are fetched', async () => {
const configuration = resolveConfiguration(
'',
'configs_test/configuration_approvers.json'
)
const releaseNotesBuilder = new ReleaseNotesBuilder(
null, // baseUrl
null, // token
'.', // repoPath
'mikepenz', // user
'release-changelog-builder-action-playground', // repo
'1.5.0', // fromTag
'2.0.0', // toTag
true, // includeOpen
false, // failOnError
false, // ignorePrePrelease
true, // enable to fetch reviewers
false, // commitMode
configuration // configuration
)
const changeLog = await releaseNotesBuilder.build()
console.log(changeLog)
expect(changeLog).toStrictEqual(
`## 🚀 Features\n\n- A feature to be going to v2 (nr3) -- (#3) [merged] --- \n- New feature to keep open (nr5) -- (#7) [open] --- gabrielpopa\n\n`
)
})
+21
View File
@@ -43,6 +43,7 @@ mergedPullRequests.push(
body: 'no magic body for this matter',
assignees: [],
requestedReviewers: [],
approvedReviewers: [],
status: "merged"
},
{
@@ -60,6 +61,7 @@ mergedPullRequests.push(
body: 'no magic body for this matter',
assignees: [],
requestedReviewers: [],
approvedReviewers: [],
status: "merged"
},
{
@@ -77,6 +79,7 @@ mergedPullRequests.push(
body: 'no magic body for this matter',
assignees: [],
requestedReviewers: [],
approvedReviewers: [],
status: "merged"
},
{
@@ -94,6 +97,7 @@ mergedPullRequests.push(
body: 'no magic body for this matter',
assignees: [],
requestedReviewers: [],
approvedReviewers: [],
status: "merged"
}
)
@@ -113,6 +117,7 @@ const pullRequestWithLabelInBody: PullRequestInfo = {
body: '[Issue][Feature][AB-1234321] - no magic body for this matter',
assignees: [],
requestedReviewers: [],
approvedReviewers: [],
status: "merged"
}
@@ -132,6 +137,7 @@ it('Extract label from title, combined regex', async () => {
toTag: '2.0.0',
includeOpen: false,
failOnError: false,
fetchReviewers: false,
commitMode: false,
configuration
})
@@ -160,6 +166,7 @@ it('Extract label from title and body, combined regex', async () => {
toTag: '2.0.0',
includeOpen: false,
failOnError: false,
fetchReviewers: false,
commitMode: false,
configuration
})
@@ -190,6 +197,7 @@ it('Extract label from title, split regex', async () => {
toTag: '2.0.0',
includeOpen: false,
failOnError: false,
fetchReviewers: false,
commitMode: false,
configuration
})
@@ -220,6 +228,7 @@ it('Extract label from title, match', async () => {
toTag: '2.0.0',
includeOpen: false,
failOnError: false,
fetchReviewers: false,
commitMode: false,
configuration
})
@@ -245,6 +254,7 @@ it('Extract label from title, match multiple', async () => {
toTag: '2.0.0',
includeOpen: false,
failOnError: false,
fetchReviewers: false,
commitMode: false,
configuration
})
@@ -271,6 +281,7 @@ it('Extract label from title, match multiple, custon non matching label', async
toTag: '2.0.0',
includeOpen: false,
failOnError: false,
fetchReviewers: false,
commitMode: false,
configuration
})
@@ -298,6 +309,7 @@ pullRequestsWithLabels.push(
body: 'no magic body for this matter',
assignees: [],
requestedReviewers: [],
approvedReviewers: [],
status: "merged"
},
{
@@ -315,6 +327,7 @@ pullRequestsWithLabels.push(
body: 'no magic body for this matter',
assignees: [],
requestedReviewers: [],
approvedReviewers: [],
status: "merged"
},
{
@@ -332,6 +345,7 @@ pullRequestsWithLabels.push(
body: 'no magic body for this matter',
assignees: [],
requestedReviewers: [],
approvedReviewers: [],
status: "merged"
},
{
@@ -349,6 +363,7 @@ pullRequestsWithLabels.push(
body: 'no magic body for this matter',
assignees: [],
requestedReviewers: [],
approvedReviewers: [],
status: "merged"
}
)
@@ -380,6 +395,7 @@ it('Match multiple labels exhaustive for category', async () => {
toTag: '2.0.0',
includeOpen: false,
failOnError: false,
fetchReviewers: false,
commitMode: false,
configuration: customConfig
})
@@ -404,6 +420,7 @@ it('Deduplicate duplicated PRs', async () => {
toTag: '2.0.0',
includeOpen: false,
failOnError: false,
fetchReviewers: false,
commitMode: false,
configuration: customConfig
})
@@ -429,6 +446,7 @@ it('Deduplicate duplicated PRs DESC', async () => {
toTag: '2.0.0',
includeOpen: false,
failOnError: false,
fetchReviewers: false,
commitMode: false,
configuration: customConfig
})
@@ -450,6 +468,7 @@ it('Commit SHA-1 in commitMode', async () => {
toTag: '2.0.0',
includeOpen: false,
failOnError: false,
fetchReviewers: false,
commitMode: true,
configuration: customConfig
})
@@ -470,6 +489,7 @@ it('Release Diff', async () => {
toTag: 'v2.8.1',
includeOpen: false,
failOnError: false,
fetchReviewers: false,
commitMode: true,
configuration: customConfig
})
@@ -508,6 +528,7 @@ it('Use exclude labels to not include a PR within a category.', async () => {
toTag: '2.0.0',
includeOpen: false,
failOnError: false,
fetchReviewers: false,
commitMode: false,
configuration: customConfig
})
+3
View File
@@ -26,6 +26,9 @@ inputs:
failOnError:
description: 'Defines if the action should result in a build failure, if an error was discovered'
default: "false"
fetchReviewers:
description: 'Will enable fetching the users/reviewers who approved the PR'
default: "false"
commitMode:
description: 'Enables a `light` commit based mode. This mode generates changelogs based on the commits. Please note that this is not officially supported, and lacks a lot of features only possible with PRs.'
default: "false"
@@ -0,0 +1,4 @@
{
"template": "${{CHANGELOG}}",
"pr_template": "- ${{TITLE}} -- (#${{NUMBER}}) [${{STATUS}}] ${{REVIEWERS}} --- ${{APPROVERS}}"
}
@@ -12,5 +12,5 @@
}
],
"template": "${{CHANGELOG}}",
"pr_template": "- ${{TITLE}} -- (#${{NUMBER}}) [${{STATUS}}] {${{LABELS}}}"
"pr_template": "- ${{TITLE}} -- (#${{NUMBER}}) [${{STATUS}}] {${{LABELS}}}${{APPROVERS}}"
}
@@ -6,5 +6,5 @@
}
],
"template": "${{CHANGELOG}}\n\n\nUncategorized\n${{UNCATEGORIZED}}\n\n\nOpen\n${{OPEN}}",
"pr_template": "- ${{TITLE}} (#${{NUMBER}}) ${{STATUS}}"
"pr_template": "- ${{TITLE}} (#${{NUMBER}}) ${{STATUS}}${{APPROVERS}}"
}
Generated Vendored
+50 -5
View File
@@ -380,8 +380,9 @@ function run() {
const includeOpen = core.getInput('includeOpen') === 'true';
const ignorePreReleases = core.getInput('ignorePreReleases') === 'true';
const failOnError = core.getInput('failOnError') === 'true';
const fetchReviewers = core.getInput('fetchReviewers') === 'true';
const commitMode = core.getInput('commitMode') === 'true';
const result = yield new releaseNotesBuilder_1.ReleaseNotesBuilder(baseUrl, token, repositoryPath, owner, repo, fromTag, toTag, includeOpen, failOnError, ignorePreReleases, commitMode, configuration).build();
const result = yield new releaseNotesBuilder_1.ReleaseNotesBuilder(baseUrl, token, repositoryPath, owner, repo, fromTag, toTag, includeOpen, failOnError, ignorePreReleases, fetchReviewers, commitMode, configuration).build();
core.setOutput('changelog', result);
// write the result in changelog to file if possible
const outputFile = core.getInput('outputFile');
@@ -551,6 +552,34 @@ class PullRequests {
return sortPullRequests(openPrs, true);
});
}
getReviewers(owner, repo, pr) {
var e_3, _a;
return __awaiter(this, void 0, void 0, function* () {
const options = this.octokit.pulls.listReviews.endpoint.merge({
owner,
repo,
pull_number: pr.number
});
try {
for (var _b = __asyncValues(this.octokit.paginate.iterator(options)), _c; _c = yield _b.next(), !_c.done;) {
const response = _c.value;
const reviews = response.data;
pr.approvedReviewers = reviews
.filter(r => r.state === 'APPROVED')
.map(r => { var _a; return (_a = r.user) === null || _a === void 0 ? void 0 : _a.login; })
.filter(r => !!r);
}
}
catch (e_3_1) { e_3 = { error: e_3_1 }; }
finally {
try {
if (_c && !_c.done && (_a = _b.return)) yield _a.call(_b);
}
finally { if (e_3) throw e_3.error; }
}
return [];
});
}
}
exports.PullRequests = PullRequests;
function sortPullRequests(pullRequests, ascending) {
@@ -605,6 +634,7 @@ const mapPullRequest = (pr, status = 'open') => {
body: pr.body || '',
assignees: ((_d = pr.assignees) === null || _d === void 0 ? void 0 : _d.map(asignee => (asignee === null || asignee === void 0 ? void 0 : asignee.login) || '')) || [],
requestedReviewers: ((_e = pr.requested_reviewers) === null || _e === void 0 ? void 0 : _e.map(reviewer => (reviewer === null || reviewer === void 0 ? void 0 : reviewer.login) || '')) || [],
approvedReviewers: [],
status
});
};
@@ -714,7 +744,7 @@ class ReleaseNotes {
}
getMergedPullRequests(octokit) {
return __awaiter(this, void 0, void 0, function* () {
const { owner, repo, includeOpen, configuration } = this.options;
const { owner, repo, includeOpen, fetchReviewers, configuration } = this.options;
const commits = yield this.getCommitHistory(octokit);
if (commits.length === 0) {
return [];
@@ -761,7 +791,7 @@ class ReleaseNotes {
return new RegExp(baseBranch.replace('\\\\', '\\'), 'gu');
});
// return only prs if the baseBranch is matching the configuration
return allPullRequests.filter(pr => {
const finalPrs = allPullRequests.filter(pr => {
if (baseBranches.length !== 0) {
return baseBranchPatterns.some(pattern => {
return pr.baseBranch.match(pattern) !== null;
@@ -769,6 +799,17 @@ class ReleaseNotes {
}
return true;
});
if (fetchReviewers) {
core.info(`️ Fetching reviewers was enabled`);
// update PR information with reviewers who approved
for (const pr of finalPrs) {
yield pullRequestsApi.getReviewers(owner, repo, pr);
if (pr.approvedReviewers.length > 0) {
core.info(`️ Retrieved ${pr.approvedReviewers.length} reviewer(s) for PR ${owner}/${repo}/#${pr.number}`);
}
}
}
return finalPrs;
});
}
generateCommitPRs(octokit) {
@@ -797,6 +838,7 @@ class ReleaseNotes {
body: commit.message || '',
assignees: [],
requestedReviewers: [],
approvedReviewers: [],
status: 'merged'
};
});
@@ -855,7 +897,7 @@ const tags_1 = __nccwpck_require__(7532);
const utils_1 = __nccwpck_require__(918);
const transform_1 = __nccwpck_require__(1644);
class ReleaseNotesBuilder {
constructor(baseUrl, token, repositoryPath, owner, repo, fromTag, toTag, includeOpen, failOnError, ignorePreReleases, commitMode, configuration) {
constructor(baseUrl, token, repositoryPath, owner, repo, fromTag, toTag, includeOpen = false, failOnError, ignorePreReleases, fetchReviewers = false, commitMode, configuration) {
this.baseUrl = baseUrl;
this.token = token;
this.repositoryPath = repositoryPath;
@@ -866,6 +908,7 @@ class ReleaseNotesBuilder {
this.includeOpen = includeOpen;
this.failOnError = failOnError;
this.ignorePreReleases = ignorePreReleases;
this.fetchReviewers = fetchReviewers;
this.commitMode = commitMode;
this.configuration = configuration;
}
@@ -925,6 +968,7 @@ class ReleaseNotesBuilder {
toTag: this.toTag,
includeOpen: this.includeOpen,
failOnError: this.failOnError,
fetchReviewers: this.fetchReviewers,
commitMode: this.commitMode,
configuration: this.configuration
};
@@ -1499,7 +1543,7 @@ function haveEveryElements(arr1, arr2) {
return arr1.every(item => arr2.has(item));
}
function fillTemplate(pr, template) {
var _a, _b, _c, _d, _e;
var _a, _b, _c, _d, _e, _f;
let transformed = template;
transformed = transformed.replace(/\${{NUMBER}}/g, pr.number.toString());
transformed = transformed.replace(/\${{TITLE}}/g, pr.title);
@@ -1514,6 +1558,7 @@ function fillTemplate(pr, template) {
transformed = transformed.replace(/\${{BODY}}/g, pr.body);
transformed = transformed.replace(/\${{ASSIGNEES}}/g, ((_d = pr.assignees) === null || _d === void 0 ? void 0 : _d.join(', ')) || '');
transformed = transformed.replace(/\${{REVIEWERS}}/g, ((_e = pr.requestedReviewers) === null || _e === void 0 ? void 0 : _e.join(', ')) || '');
transformed = transformed.replace(/\${{APPROVERS}}/g, ((_f = pr.approvedReviewers) === null || _f === void 0 ? void 0 : _f.join(', ')) || '');
return transformed;
}
function transform(filled, transformers) {
Generated Vendored
+1 -1
View File
File diff suppressed because one or more lines are too long
+2
View File
@@ -35,6 +35,7 @@ async function run(): Promise<void> {
const includeOpen = core.getInput('includeOpen') === 'true'
const ignorePreReleases = core.getInput('ignorePreReleases') === 'true'
const failOnError = core.getInput('failOnError') === 'true'
const fetchReviewers = core.getInput('fetchReviewers') === 'true'
const commitMode = core.getInput('commitMode') === 'true'
const result = await new ReleaseNotesBuilder(
@@ -48,6 +49,7 @@ async function run(): Promise<void> {
includeOpen,
failOnError,
ignorePreReleases,
fetchReviewers,
commitMode,
configuration
).build()
+27
View File
@@ -18,6 +18,7 @@ export interface PullRequestInfo {
body: string
assignees: string[]
requestedReviewers: string[]
approvedReviewers: string[]
status: 'open' | 'merged'
}
@@ -26,6 +27,9 @@ type PullData = RestEndpointMethodTypes['pulls']['get']['response']['data']
type PullsListData =
RestEndpointMethodTypes['pulls']['list']['response']['data']
type PullReviewData =
RestEndpointMethodTypes['pulls']['listReviews']['response']['data']
export class PullRequests {
constructor(private octokit: Octokit) {}
@@ -127,6 +131,28 @@ export class PullRequests {
return sortPullRequests(openPrs, true)
}
async getReviewers(
owner: string,
repo: string,
pr: PullRequestInfo
): Promise<PullReviewData[]> {
const options = this.octokit.pulls.listReviews.endpoint.merge({
owner,
repo,
pull_number: pr.number
})
for await (const response of this.octokit.paginate.iterator(options)) {
const reviews: PullReviewData = response.data as PullReviewData
pr.approvedReviewers = reviews
.filter(r => r.state === 'APPROVED')
.map(r => r.user?.login)
.filter(r => !!r) as string[]
}
return []
}
}
export function sortPullRequests(
@@ -192,5 +218,6 @@ const mapPullRequest = (
assignees: pr.assignees?.map(asignee => asignee?.login || '') || [],
requestedReviewers:
pr.requested_reviewers?.map(reviewer => reviewer?.login || '') || [],
approvedReviewers: [],
status
})
+20 -2
View File
@@ -13,6 +13,7 @@ export interface ReleaseNotesOptions {
toTag: string // the tag/ref up to
includeOpen: boolean // defines if we should also fetch open pull requests
failOnError: boolean // defines if we should fail the action in case of an error
fetchReviewers: boolean // defines if the action should fetch the reviewers for PRs - approved reviewers are not included in the default PR listing
commitMode: boolean // defines if we use the alternative commit based mode. note: this is only partially supported
configuration: Configuration // the configuration as defined in `configuration.ts`
}
@@ -81,7 +82,8 @@ export class ReleaseNotes {
private async getMergedPullRequests(
octokit: Octokit
): Promise<PullRequestInfo[]> {
const {owner, repo, includeOpen, configuration} = this.options
const {owner, repo, includeOpen, fetchReviewers, configuration} =
this.options
const commits = await this.getCommitHistory(octokit)
if (commits.length === 0) {
@@ -169,7 +171,7 @@ export class ReleaseNotes {
})
// return only prs if the baseBranch is matching the configuration
return allPullRequests.filter(pr => {
const finalPrs = allPullRequests.filter(pr => {
if (baseBranches.length !== 0) {
return baseBranchPatterns.some(pattern => {
return pr.baseBranch.match(pattern) !== null
@@ -177,6 +179,21 @@ export class ReleaseNotes {
}
return true
})
if (fetchReviewers) {
core.info(`️ Fetching reviewers was enabled`)
// update PR information with reviewers who approved
for (const pr of finalPrs) {
await pullRequestsApi.getReviewers(owner, repo, pr)
if (pr.approvedReviewers.length > 0) {
core.info(
`️ Retrieved ${pr.approvedReviewers.length} reviewer(s) for PR ${owner}/${repo}/#${pr.number}`
)
}
}
}
return finalPrs
}
private async generateCommitPRs(
@@ -213,6 +230,7 @@ export class ReleaseNotes {
body: commit.message || '',
assignees: [],
requestedReviewers: [],
approvedReviewers: [],
status: 'merged'
}
})
+3 -1
View File
@@ -15,9 +15,10 @@ export class ReleaseNotesBuilder {
private repo: string | null,
private fromTag: string | null,
private toTag: string | null,
private includeOpen: boolean,
private includeOpen: boolean = false,
private failOnError: boolean,
private ignorePreReleases: boolean,
private fetchReviewers: boolean = false,
private commitMode: boolean,
private configuration: Configuration
) {}
@@ -91,6 +92,7 @@ export class ReleaseNotesBuilder {
toTag: this.toTag,
includeOpen: this.includeOpen,
failOnError: this.failOnError,
fetchReviewers: this.fetchReviewers,
commitMode: this.commitMode,
configuration: this.configuration
}
+4
View File
@@ -335,6 +335,10 @@ function fillTemplate(pr: PullRequestInfo, template: string): string {
/\${{REVIEWERS}}/g,
pr.requestedReviewers?.join(', ') || ''
)
transformed = transformed.replace(
/\${{APPROVERS}}/g,
pr.approvedReviewers?.join(', ') || ''
)
return transformed
}