Merge pull request #1180 from mikepenz/fix/1176
Introduce `fetchViaCommits` configuration | Offers a new feature to solve an edge case resulting in old PRs not being included in changelog for squash merges
This commit is contained in:
@@ -333,6 +333,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 |
|
||||
| `fetchViaCommits` | Enables PRs to get fetched via the commits identified between from->to tag. This will do 1 API request per commit -> Best for scenarios with squash merges | Or shorter from->to diffs (< 10 commits) | Also effective for shorters diffs for very old PRs. Default: false |
|
||||
| `fetchReviewers` | Will enable fetching the users/reviewers who approved the PR. Default: false |
|
||||
| `fetchReleaseInformation` | Will enable fetching additional release information from tags. Default: false |
|
||||
| `fetchReviews` | Will enable fetching the reviews on of the PR. Default: false |
|
||||
|
||||
@@ -16,6 +16,7 @@ it('Should match generated changelog (unspecified fromTag)', async () => {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true, // enable to fetch via commits
|
||||
false, // enable to fetch reviewers
|
||||
false, // enable to fetch tag release information
|
||||
false, // enable to fetch reviews
|
||||
@@ -47,6 +48,7 @@ it('Should match generated changelog (unspecified tags)', async () => {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false, // enable to fetch via commits
|
||||
false, // enable to fetch reviewers
|
||||
false, // enable to fetch tag release information
|
||||
false, // enable to fetch reviews
|
||||
@@ -73,6 +75,7 @@ it('Should use empty placeholder', async () => {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true, // enable to fetch via commits
|
||||
false, // enable to fetch reviewers
|
||||
false, // enable to fetch tag release information
|
||||
false, // enable to fetch reviews
|
||||
@@ -99,6 +102,7 @@ it('Should fill empty placeholders', async () => {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true, // enable to fetch via commits
|
||||
false, // enable to fetch reviewers
|
||||
false, // enable to fetch tag release information
|
||||
false, // enable to fetch reviews
|
||||
@@ -127,6 +131,7 @@ it('Should fill `template` placeholders', async () => {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true, // enable to fetch via commits
|
||||
false, // enable to fetch reviewers
|
||||
false, // enable to fetch tag release information
|
||||
false, // enable to fetch reviews
|
||||
@@ -156,6 +161,7 @@ it('Should fill `template` placeholders, ignore', async () => {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false, // enable to fetch via commits
|
||||
false, // enable to fetch reviewers
|
||||
false, // enable to fetch tag release information
|
||||
false, // enable to fetch reviews
|
||||
@@ -184,6 +190,7 @@ it('Uncategorized category', async () => {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false, // enable to fetch via commits
|
||||
false, // enable to fetch reviewers
|
||||
false, // enable to fetch tag release information
|
||||
false, // enable to fetch reviews
|
||||
@@ -212,6 +219,7 @@ it('Verify commit based changelog', async () => {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true, // enable to fetch via commits
|
||||
false, // enable to fetch reviewers
|
||||
false, // enable to fetch tag release information
|
||||
false, // enable to fetch reviews
|
||||
@@ -240,6 +248,7 @@ it('Verify commit based changelog, with emoji categorisation', async () => {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false, // enable to fetch via commits
|
||||
false, // enable to fetch reviewers
|
||||
false, // enable to fetch tag release information
|
||||
false, // enable to fetch reviews
|
||||
@@ -268,6 +277,7 @@ it('Verify default inclusion of open PRs', async () => {
|
||||
true, // includeOpen
|
||||
false, // failOnError
|
||||
false, // ignorePrePrelease
|
||||
false, // enable to fetch via commits
|
||||
false, // enable to fetch reviewers
|
||||
false, // enable to fetch tag release information
|
||||
false, // enable to fetch reviews
|
||||
@@ -296,6 +306,7 @@ it('Verify custom categorisation of open PRs', async () => {
|
||||
true, // includeOpen
|
||||
false, // failOnError
|
||||
false, // ignorePrePrelease
|
||||
false, // enable to fetch via commits
|
||||
false, // enable to fetch reviewers
|
||||
false, // enable to fetch tag release information
|
||||
false, // enable to fetch reviews
|
||||
@@ -324,6 +335,7 @@ it('Verify reviewers who approved are fetched and also release information', asy
|
||||
true, // includeOpen
|
||||
false, // failOnError
|
||||
false, // ignorePrePrelease
|
||||
false, // enable to fetch via commits
|
||||
true, // enable to fetch reviewers
|
||||
true, // enable to fetch tag release information
|
||||
false, // enable to fetch reviews
|
||||
@@ -353,6 +365,7 @@ it('Fetch release information', async () => {
|
||||
true, // includeOpen
|
||||
false, // failOnError
|
||||
false, // ignorePrePrelease
|
||||
false, // enable to fetch via commits
|
||||
false, // enable to fetch reviewers
|
||||
true, // enable to fetch tag release information
|
||||
false, // enable to fetch reviews
|
||||
@@ -380,6 +393,7 @@ it('Fetch release information for non existing tag / release', async () => {
|
||||
true, // includeOpen
|
||||
false, // failOnError
|
||||
false, // ignorePrePrelease
|
||||
false, // enable to fetch via commits
|
||||
false, // enable to fetch reviewers
|
||||
true, // enable to fetch tag release information
|
||||
false, // enable to fetch reviews
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import {mergeConfiguration, resolveConfiguration} from '../src/utils'
|
||||
import {Octokit} from '@octokit/rest'
|
||||
import {buildChangelog} from '../src/transform'
|
||||
import { pullData } from 'github-pr-collector'
|
||||
import {pullData} from 'github-pr-collector'
|
||||
|
||||
jest.setTimeout(180000)
|
||||
|
||||
@@ -20,6 +20,7 @@ it('Should have empty changelog (tags)', async () => {
|
||||
toTag: {name: 'v0.0.2'},
|
||||
includeOpen: false,
|
||||
failOnError: false,
|
||||
fetchViaCommits: true,
|
||||
fetchReviewers: false,
|
||||
fetchReleaseInformation: false,
|
||||
fetchReviews: false,
|
||||
@@ -41,6 +42,7 @@ it('Should match generated changelog (tags)', async () => {
|
||||
toTag: {name: 'v0.0.3'},
|
||||
includeOpen: false,
|
||||
failOnError: false,
|
||||
fetchViaCommits: true,
|
||||
fetchReviewers: false,
|
||||
fetchReleaseInformation: false,
|
||||
fetchReviews: false,
|
||||
@@ -69,6 +71,7 @@ it('Should match generated changelog (refs)', async () => {
|
||||
toTag: {name: 'fa3788c8c4b3373ef8424ce3eb008a5cd07cc5aa'},
|
||||
includeOpen: false,
|
||||
failOnError: false,
|
||||
fetchViaCommits: true,
|
||||
fetchReviewers: false,
|
||||
fetchReleaseInformation: false,
|
||||
fetchReviews: false,
|
||||
@@ -104,6 +107,7 @@ it('Should match generated changelog and replace all occurrences (refs)', async
|
||||
toTag: {name: 'fa3788c8c4b3373ef8424ce3eb008a5cd07cc5aa'},
|
||||
includeOpen: false,
|
||||
failOnError: false,
|
||||
fetchViaCommits: true,
|
||||
fetchReviewers: false,
|
||||
fetchReleaseInformation: false,
|
||||
fetchReviews: false,
|
||||
@@ -141,6 +145,7 @@ it('Should match ordered ASC', async () => {
|
||||
toTag: {name: 'v0.5.0'},
|
||||
includeOpen: false,
|
||||
failOnError: false,
|
||||
fetchViaCommits: false,
|
||||
fetchReviewers: false,
|
||||
fetchReleaseInformation: false,
|
||||
fetchReviews: false,
|
||||
@@ -164,6 +169,7 @@ it('Should match ordered DESC', async () => {
|
||||
toTag: {name: 'v0.5.0'},
|
||||
includeOpen: false,
|
||||
failOnError: false,
|
||||
fetchViaCommits: false,
|
||||
fetchReviewers: false,
|
||||
fetchReleaseInformation: false,
|
||||
fetchReviews: false,
|
||||
@@ -186,6 +192,7 @@ it('Should match ordered by title ASC', async () => {
|
||||
toTag: {name: 'v0.5.0'},
|
||||
includeOpen: false,
|
||||
failOnError: false,
|
||||
fetchViaCommits: false,
|
||||
fetchReviewers: false,
|
||||
fetchReleaseInformation: false,
|
||||
fetchReviews: false,
|
||||
@@ -209,6 +216,7 @@ it('Should match ordered by title DESC', async () => {
|
||||
toTag: {name: 'v0.5.0'},
|
||||
includeOpen: false,
|
||||
failOnError: false,
|
||||
fetchViaCommits: false,
|
||||
fetchReviewers: false,
|
||||
fetchReleaseInformation: false,
|
||||
fetchReviews: false,
|
||||
@@ -233,6 +241,7 @@ it('Should ignore PRs not merged into develop branch', async () => {
|
||||
toTag: {name: 'v1.4.0'},
|
||||
includeOpen: false,
|
||||
failOnError: false,
|
||||
fetchViaCommits: true,
|
||||
fetchReviewers: false,
|
||||
fetchReleaseInformation: false,
|
||||
fetchReviews: false,
|
||||
@@ -254,6 +263,7 @@ it('Should ignore PRs not merged into main branch', async () => {
|
||||
toTag: {name: 'v1.4.0'},
|
||||
includeOpen: false,
|
||||
failOnError: false,
|
||||
fetchViaCommits: true,
|
||||
fetchReviewers: false,
|
||||
fetchReleaseInformation: false,
|
||||
fetchReviews: false,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { TagInfo, filterTags, prepareAndSortTags } from "github-pr-collector/lib/tags"
|
||||
import {TagInfo, filterTags, prepareAndSortTags} from 'github-pr-collector/lib/tags'
|
||||
|
||||
jest.setTimeout(180000)
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import {buildChangelog} from '../src/transform'
|
||||
import moment from 'moment'
|
||||
import {Configuration, DefaultConfiguration} from '../src/configuration'
|
||||
import { PullRequestInfo } from 'github-pr-collector/lib/pullRequests'
|
||||
import { DefaultDiffInfo } from 'github-pr-collector/lib/commits'
|
||||
import {PullRequestInfo} from 'github-pr-collector/lib/pullRequests'
|
||||
import {DefaultDiffInfo} from 'github-pr-collector/lib/commits'
|
||||
|
||||
jest.setTimeout(180000)
|
||||
|
||||
@@ -409,16 +409,14 @@ it('Reference PRs', async () => {
|
||||
labels: []
|
||||
}
|
||||
]
|
||||
customConfig.pr_template = "${{NUMBER}} -- ${{REFERENCED[*].number}}"
|
||||
customConfig.pr_template = '${{NUMBER}} -- ${{REFERENCED[*].number}}'
|
||||
customConfig.reference = {
|
||||
pattern: '.*\ \#(.).*', // matches the 1 from "abcdefg #1 adfasdf"
|
||||
pattern: '.* #(.).*', // matches the 1 from "abcdefg #1 adfasdf"
|
||||
on_property: 'body',
|
||||
method: 'replace',
|
||||
target: '$1'
|
||||
}
|
||||
expect(buildChangelogTest(customConfig, pullRequestsWithLabels)).toStrictEqual(
|
||||
`1 -- 2\n4 -- \n3 -- \n\n`
|
||||
)
|
||||
expect(buildChangelogTest(customConfig, pullRequestsWithLabels)).toStrictEqual(`1 -- 2\n4 -- \n3 -- \n\n`)
|
||||
})
|
||||
|
||||
it('Use empty_content for empty category', async () => {
|
||||
|
||||
@@ -28,6 +28,9 @@ inputs:
|
||||
failOnError:
|
||||
description: 'Defines if the action should result in a build failure, if an error was discovered'
|
||||
default: "false"
|
||||
fetchViaCommits:
|
||||
description: 'Defines if PRs are fetched via the commits identified. This will do 1 API request per commit -> Best for scenarios with squash merges | Or shorter from-to diffs (< 10 commits) | Also effective for shorters diffs for very old PRs'
|
||||
default: "false"
|
||||
fetchReviewers:
|
||||
description: 'Will enable fetching the users/reviewers who approved the PR'
|
||||
default: "false"
|
||||
|
||||
+92
-30
@@ -141,12 +141,13 @@ function run() {
|
||||
const includeOpen = core.getInput('includeOpen') === 'true';
|
||||
const ignorePreReleases = core.getInput('ignorePreReleases') === 'true';
|
||||
const failOnError = core.getInput('failOnError') === 'true';
|
||||
const fetchViaCommits = core.getInput('fetchViaCommits') === 'true';
|
||||
const fetchReviewers = core.getInput('fetchReviewers') === 'true';
|
||||
const fetchReleaseInformation = core.getInput('fetchReleaseInformation') === 'true';
|
||||
const fetchReviews = core.getInput('fetchReviews') === 'true';
|
||||
const commitMode = core.getInput('commitMode') === 'true';
|
||||
const exportOnly = core.getInput('exportOnly') === 'true';
|
||||
const result = yield new releaseNotesBuilder_1.ReleaseNotesBuilder(baseUrl, token, repositoryPath, owner, repo, fromTag, toTag, includeOpen, failOnError, ignorePreReleases, fetchReviewers, fetchReleaseInformation, fetchReviews, commitMode, exportOnly, configuration).build();
|
||||
const result = yield new releaseNotesBuilder_1.ReleaseNotesBuilder(baseUrl, token, repositoryPath, owner, repo, fromTag, toTag, includeOpen, failOnError, ignorePreReleases, fetchViaCommits, fetchReviewers, fetchReleaseInformation, fetchReviews, commitMode, exportOnly, configuration).build();
|
||||
core.setOutput('changelog', result);
|
||||
// write the result in changelog to file if possible
|
||||
const outputFile = core.getInput('outputFile');
|
||||
@@ -282,7 +283,7 @@ const transform_1 = __nccwpck_require__(1644);
|
||||
const github_pr_collector_1 = __nccwpck_require__(3196);
|
||||
const utils_2 = __nccwpck_require__(853);
|
||||
class ReleaseNotesBuilder {
|
||||
constructor(baseUrl, token, repositoryPath, owner, repo, fromTag, toTag, includeOpen = false, failOnError, ignorePreReleases, fetchReviewers = false, fetchReleaseInformation = false, fetchReviews = false, commitMode = false, exportOnly = false, configuration) {
|
||||
constructor(baseUrl, token, repositoryPath, owner, repo, fromTag, toTag, includeOpen = false, failOnError, ignorePreReleases, fetchViaCommits = false, fetchReviewers = false, fetchReleaseInformation = false, fetchReviews = false, commitMode = false, exportOnly = false, configuration) {
|
||||
this.baseUrl = baseUrl;
|
||||
this.token = token;
|
||||
this.repositoryPath = repositoryPath;
|
||||
@@ -293,6 +294,7 @@ class ReleaseNotesBuilder {
|
||||
this.includeOpen = includeOpen;
|
||||
this.failOnError = failOnError;
|
||||
this.ignorePreReleases = ignorePreReleases;
|
||||
this.fetchViaCommits = fetchViaCommits;
|
||||
this.fetchReviewers = fetchReviewers;
|
||||
this.fetchReleaseInformation = fetchReleaseInformation;
|
||||
this.fetchReviews = fetchReviews;
|
||||
@@ -319,7 +321,7 @@ class ReleaseNotesBuilder {
|
||||
core.debug(`Resolved 'repo' as ${this.repo}`);
|
||||
}
|
||||
core.endGroup();
|
||||
const prData = yield new github_pr_collector_1.PullRequestCollector(this.baseUrl, this.token, this.repositoryPath, this.owner, this.repo, this.fromTag, this.toTag, this.includeOpen, this.failOnError, this.ignorePreReleases, this.fetchReviewers, this.fetchReleaseInformation, this.fetchReviews, this.commitMode, this.configuration).build();
|
||||
const prData = yield new github_pr_collector_1.PullRequestCollector(this.baseUrl, this.token, this.repositoryPath, this.owner, this.repo, this.fromTag, this.toTag, this.includeOpen, this.failOnError, this.ignorePreReleases, this.fetchViaCommits, this.fetchReviewers, this.fetchReleaseInformation, this.fetchReviews, this.commitMode, this.configuration).build();
|
||||
if (prData == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -26272,13 +26274,15 @@ class Commits {
|
||||
commitInfo: commits
|
||||
.filter(commit => commit.sha)
|
||||
.map(commit => {
|
||||
var _a, _b;
|
||||
var _a, _b, _c, _d;
|
||||
return ({
|
||||
sha: commit.sha || '',
|
||||
summary: commit.commit.message.split('\n')[0],
|
||||
message: commit.commit.message,
|
||||
date: (0, moment_1.default)((_a = commit.commit.committer) === null || _a === void 0 ? void 0 : _a.date),
|
||||
author: ((_b = commit.commit.author) === null || _b === void 0 ? void 0 : _b.name) || '',
|
||||
author: ((_a = commit.commit.author) === null || _a === void 0 ? void 0 : _a.name) || '',
|
||||
authorDate: (0, moment_1.default)((_b = commit.commit.author) === null || _b === void 0 ? void 0 : _b.date),
|
||||
committer: ((_c = commit.commit.committer) === null || _c === void 0 ? void 0 : _c.name) || '',
|
||||
commitDate: (0, moment_1.default)((_d = commit.commit.committer) === null || _d === void 0 ? void 0 : _d.date),
|
||||
prNumber: undefined
|
||||
});
|
||||
})
|
||||
@@ -26296,10 +26300,10 @@ class Commits {
|
||||
commitsResult.push(commit);
|
||||
}
|
||||
commitsResult.sort((a, b) => {
|
||||
if (a.date.isBefore(b.date)) {
|
||||
if (a.commitDate.isBefore(b.commitDate)) {
|
||||
return -1;
|
||||
}
|
||||
else if (b.date.isBefore(a.date)) {
|
||||
else if (b.commitDate.isBefore(a.commitDate)) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@@ -26342,8 +26346,8 @@ class Commits {
|
||||
title: commit.summary,
|
||||
htmlURL: '',
|
||||
baseBranch: '',
|
||||
createdAt: commit.date,
|
||||
mergedAt: commit.date,
|
||||
createdAt: commit.commitDate,
|
||||
mergedAt: commit.commitDate,
|
||||
mergeCommitSha: commit.sha,
|
||||
author: commit.author || '',
|
||||
repoName: '',
|
||||
@@ -26555,7 +26559,7 @@ const https_proxy_agent_1 = __nccwpck_require__(7219);
|
||||
const pullRequests_1 = __nccwpck_require__(1948);
|
||||
const commits_1 = __nccwpck_require__(5789);
|
||||
class PullRequestCollector {
|
||||
constructor(baseUrl, token, repositoryPath, owner, repo, fromTag, toTag, includeOpen = false, failOnError, ignorePreReleases, fetchReviewers = false, fetchReleaseInformation = false, fetchReviews = false, commitMode = false, configuration) {
|
||||
constructor(baseUrl, token, repositoryPath, owner, repo, fromTag, toTag, includeOpen = false, failOnError, ignorePreReleases, fetchViaCommits = false, fetchReviewers = false, fetchReleaseInformation = false, fetchReviews = false, commitMode = false, configuration) {
|
||||
this.baseUrl = baseUrl;
|
||||
this.token = token;
|
||||
this.repositoryPath = repositoryPath;
|
||||
@@ -26566,6 +26570,7 @@ class PullRequestCollector {
|
||||
this.includeOpen = includeOpen;
|
||||
this.failOnError = failOnError;
|
||||
this.ignorePreReleases = ignorePreReleases;
|
||||
this.fetchViaCommits = fetchViaCommits;
|
||||
this.fetchReviewers = fetchReviewers;
|
||||
this.fetchReleaseInformation = fetchReleaseInformation;
|
||||
this.fetchReviews = fetchReviews;
|
||||
@@ -26630,6 +26635,7 @@ class PullRequestCollector {
|
||||
toTag: thisTag,
|
||||
includeOpen: this.includeOpen,
|
||||
failOnError: this.failOnError,
|
||||
fetchViaCommits: this.fetchViaCommits,
|
||||
fetchReviewers: this.fetchReviewers,
|
||||
fetchReleaseInformation: this.fetchReleaseInformation,
|
||||
fetchReviews: this.fetchReviews,
|
||||
@@ -26772,8 +26778,40 @@ class PullRequests {
|
||||
}
|
||||
});
|
||||
}
|
||||
getBetweenDates(owner, repo, fromDate, toDate, maxPullRequests) {
|
||||
getForCommitHash(owner, repo, commit_sha, maxPullRequests) {
|
||||
var _a, e_1, _b, _c;
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const mergedPRs = [];
|
||||
const options = this.octokit.repos.listPullRequestsAssociatedWithCommit.endpoint.merge({
|
||||
owner,
|
||||
repo,
|
||||
commit_sha,
|
||||
per_page: `${Math.min(10, maxPullRequests)}`,
|
||||
direction: 'desc'
|
||||
});
|
||||
try {
|
||||
for (var _d = true, _e = __asyncValues(this.octokit.paginate.iterator(options)), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) {
|
||||
_c = _f.value;
|
||||
_d = false;
|
||||
const response = _c;
|
||||
const prs = response.data;
|
||||
for (const pr of prs) {
|
||||
mergedPRs.push(mapPullRequest(pr, pr.merged_at ? 'merged' : 'open'));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
||||
finally {
|
||||
try {
|
||||
if (!_d && !_a && (_b = _e.return)) yield _b.call(_e);
|
||||
}
|
||||
finally { if (e_1) throw e_1.error; }
|
||||
}
|
||||
return sortPrs(mergedPRs);
|
||||
});
|
||||
}
|
||||
getBetweenDates(owner, repo, fromDate, toDate, maxPullRequests) {
|
||||
var _a, e_2, _b, _c;
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const mergedPRs = [];
|
||||
const options = this.octokit.pulls.list.endpoint.merge({
|
||||
@@ -26801,22 +26839,22 @@ class PullRequests {
|
||||
core.warning(`⚠️ Reached 'maxPullRequests' count ${maxPullRequests}`);
|
||||
}
|
||||
// bail out early to not keep iterating on PRs super old
|
||||
return sortPrs(mergedPRs);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
||||
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
||||
finally {
|
||||
try {
|
||||
if (!_d && !_a && (_b = _e.return)) yield _b.call(_e);
|
||||
}
|
||||
finally { if (e_1) throw e_1.error; }
|
||||
finally { if (e_2) throw e_2.error; }
|
||||
}
|
||||
return sortPrs(mergedPRs);
|
||||
});
|
||||
}
|
||||
getOpen(owner, repo, maxPullRequests) {
|
||||
var _a, e_2, _b, _c;
|
||||
var _a, e_3, _b, _c;
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const openPrs = [];
|
||||
const options = this.octokit.pulls.list.endpoint.merge({
|
||||
@@ -26842,22 +26880,22 @@ class PullRequests {
|
||||
core.warning(`⚠️ Reached 'maxPullRequests' count ${maxPullRequests}`);
|
||||
}
|
||||
// bail out early to not keep iterating on PRs super old
|
||||
return sortPrs(openPrs);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
||||
catch (e_3_1) { e_3 = { error: e_3_1 }; }
|
||||
finally {
|
||||
try {
|
||||
if (!_d && !_a && (_b = _e.return)) yield _b.call(_e);
|
||||
}
|
||||
finally { if (e_2) throw e_2.error; }
|
||||
finally { if (e_3) throw e_3.error; }
|
||||
}
|
||||
return sortPrs(openPrs);
|
||||
});
|
||||
}
|
||||
getReviews(owner, repo, pr) {
|
||||
var _a, e_3, _b, _c;
|
||||
var _a, e_4, _b, _c;
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const options = this.octokit.pulls.listReviews.endpoint.merge({
|
||||
owner,
|
||||
@@ -26878,12 +26916,12 @@ class PullRequests {
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (e_3_1) { e_3 = { error: e_3_1 }; }
|
||||
catch (e_4_1) { e_4 = { error: e_4_1 }; }
|
||||
finally {
|
||||
try {
|
||||
if (!_d && !_a && (_b = _e.return)) yield _b.call(_e);
|
||||
}
|
||||
finally { if (e_3) throw e_3.error; }
|
||||
finally { if (e_4) throw e_4.error; }
|
||||
}
|
||||
pr.reviews = prReviews;
|
||||
});
|
||||
@@ -26898,8 +26936,8 @@ class PullRequests {
|
||||
}
|
||||
const firstCommit = commits[0];
|
||||
const lastCommit = commits[commits.length - 1];
|
||||
let fromDate = firstCommit.date;
|
||||
const toDate = lastCommit.date;
|
||||
let fromDate = moment_1.default.min(firstCommit.authorDate, firstCommit.commitDate); // get the lower date (e.g. if commits are modified)
|
||||
const toDate = moment_1.default.max(lastCommit.authorDate, lastCommit.commitDate); // ensure we get the higher date (e.g. in case of rebases)
|
||||
const maxDays = configuration.max_back_track_time_days;
|
||||
const maxFromDate = toDate.clone().subtract(maxDays, 'days');
|
||||
if (maxFromDate.isAfter(fromDate)) {
|
||||
@@ -26907,16 +26945,38 @@ class PullRequests {
|
||||
fromDate = maxFromDate;
|
||||
}
|
||||
core.info(`ℹ️ Fetching PRs between dates ${fromDate.toISOString()} to ${toDate.toISOString()} for ${owner}/${repo}`);
|
||||
const pullRequests = yield this.getBetweenDates(owner, repo, fromDate, toDate, configuration.max_pull_requests);
|
||||
core.info(`ℹ️ Retrieved ${pullRequests.length} PRs for ${owner}/${repo} in date range from API`);
|
||||
const prCommits = (0, commits_1.filterCommits)(commits, configuration.exclude_merge_branches);
|
||||
core.info(`ℹ️ Retrieved ${prCommits.length} release commits for ${owner}/${repo}`);
|
||||
// create array of commits for this release
|
||||
const releaseCommitHashes = prCommits.map(commmit => {
|
||||
return commmit.sha;
|
||||
const releaseCommitHashes = prCommits.map(commit => {
|
||||
return commit.sha;
|
||||
});
|
||||
let pullRequests;
|
||||
if (options.fetchViaCommits) {
|
||||
// fetch PRs based on commits instead (will get associated PRs per commit found)
|
||||
const prsForReleaseCommits = new Map();
|
||||
for (const commit of prCommits) {
|
||||
const result = yield this.getForCommitHash(owner, repo, commit.sha, configuration.max_pull_requests);
|
||||
for (const pr of result) {
|
||||
prsForReleaseCommits.set(pr.number, pr);
|
||||
}
|
||||
}
|
||||
const dedupedPrsForReleaseCommits = Array.from(prsForReleaseCommits.values());
|
||||
if (!includeOpen) {
|
||||
pullRequests = dedupedPrsForReleaseCommits.filter(pr => pr.status !== 'open');
|
||||
core.info(`ℹ️ Retrieved ${pullRequests.length} PRs for ${owner}/${repo} based on the release commit hashes`);
|
||||
}
|
||||
else {
|
||||
pullRequests = dedupedPrsForReleaseCommits;
|
||||
core.info(`ℹ️ Retrieved ${pullRequests.length} PRs for ${owner}/${repo} based on the release commit hashes (including open)`);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// fetch PRs based on the date range identified
|
||||
const pullRequestsBetweenDate = yield this.getBetweenDates(owner, repo, fromDate, toDate, configuration.max_pull_requests);
|
||||
core.info(`ℹ️ Retrieved ${pullRequestsBetweenDate.length} PRs for ${owner}/${repo} in date range from API`);
|
||||
// filter out pull requests not associated with this release
|
||||
const mergedPullRequests = pullRequests.filter(pr => {
|
||||
const mergedPullRequests = pullRequestsBetweenDate.filter(pr => {
|
||||
return releaseCommitHashes.includes(pr.mergeCommitSha);
|
||||
});
|
||||
core.info(`ℹ️ Retrieved ${mergedPullRequests.length} merged PRs for ${owner}/${repo}`);
|
||||
@@ -26929,13 +26989,15 @@ class PullRequests {
|
||||
allPullRequests = allPullRequests.concat(openPullRequests);
|
||||
core.info(`ℹ️ Retrieved ${allPullRequests.length} total PRs for ${owner}/${repo}`);
|
||||
}
|
||||
pullRequests = allPullRequests;
|
||||
}
|
||||
// retrieve base branches we allow
|
||||
const baseBranches = configuration.base_branches;
|
||||
const baseBranchPatterns = baseBranches.map(baseBranch => {
|
||||
return new RegExp(baseBranch.replace('\\\\', '\\'), 'gu');
|
||||
});
|
||||
// return only prs if the baseBranch is matching the configuration
|
||||
const finalPrs = allPullRequests.filter(pr => {
|
||||
const finalPrs = pullRequests.filter(pr => {
|
||||
if (baseBranches.length !== 0) {
|
||||
return baseBranchPatterns.some(pattern => {
|
||||
return pr.baseBranch.match(pattern) !== null;
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
@@ -28,7 +28,9 @@ export interface CommitInfo {
|
||||
summary: string
|
||||
message: string
|
||||
author: string
|
||||
date: moment.Moment
|
||||
authorDate: moment.Moment
|
||||
committer: string
|
||||
commitDate: moment.Moment
|
||||
}
|
||||
|
||||
export class Commits {
|
||||
@@ -90,8 +92,10 @@ export class Commits {
|
||||
sha: commit.sha || '',
|
||||
summary: commit.commit.message.split('\n')[0],
|
||||
message: commit.commit.message,
|
||||
date: moment(commit.commit.committer?.date),
|
||||
author: commit.commit.author?.name || '',
|
||||
authorDate: moment(commit.commit.author?.date),
|
||||
committer: commit.commit.committer?.name || '',
|
||||
commitDate: moment(commit.commit.committer?.date),
|
||||
prNumber: undefined
|
||||
}))
|
||||
}
|
||||
@@ -110,9 +114,9 @@ export class Commits {
|
||||
}
|
||||
|
||||
commitsResult.sort((a, b) => {
|
||||
if (a.date.isBefore(b.date)) {
|
||||
if (a.commitDate.isBefore(b.commitDate)) {
|
||||
return -1
|
||||
} else if (b.date.isBefore(a.date)) {
|
||||
} else if (b.commitDate.isBefore(a.commitDate)) {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
@@ -160,8 +164,8 @@ export class Commits {
|
||||
title: commit.summary,
|
||||
htmlURL: '',
|
||||
baseBranch: '',
|
||||
createdAt: commit.date,
|
||||
mergedAt: commit.date,
|
||||
createdAt: commit.commitDate,
|
||||
mergedAt: commit.commitDate,
|
||||
mergeCommitSha: commit.sha,
|
||||
author: commit.author || '',
|
||||
repoName: '',
|
||||
|
||||
@@ -14,6 +14,7 @@ export interface Options {
|
||||
toTag: TagInfo // 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
|
||||
fetchViaCommits: boolean // defines if PRs are fetched via the commits identified. This will do 1 API request per commit -> Best for scenarios with squash merges | Or shorter from-to diffs (< 10 commits) | Also effective for shorters diffs for very old PRs
|
||||
fetchReviewers: boolean // defines if the action should fetch the reviewers for PRs - approved reviewers are not included in the default PR listing
|
||||
fetchReleaseInformation: boolean // defines if the action should fetch the release information for the from and to tag - e.g. the creation date for the associated release
|
||||
fetchReviews: boolean // defines if the action should fetch the reviews for the PR.
|
||||
@@ -40,6 +41,7 @@ export class PullRequestCollector {
|
||||
private includeOpen: boolean = false,
|
||||
private failOnError: boolean,
|
||||
private ignorePreReleases: boolean,
|
||||
private fetchViaCommits: boolean = false,
|
||||
private fetchReviewers: boolean = false,
|
||||
private fetchReleaseInformation: boolean = false,
|
||||
private fetchReviews: boolean = false,
|
||||
@@ -119,6 +121,7 @@ export class PullRequestCollector {
|
||||
toTag: thisTag,
|
||||
includeOpen: this.includeOpen,
|
||||
failOnError: this.failOnError,
|
||||
fetchViaCommits: this.fetchViaCommits,
|
||||
fetchReviewers: this.fetchReviewers,
|
||||
fetchReleaseInformation: this.fetchReleaseInformation,
|
||||
fetchReviews: this.fetchReviews,
|
||||
|
||||
@@ -91,6 +91,28 @@ export class PullRequests {
|
||||
}
|
||||
}
|
||||
|
||||
async getForCommitHash(owner: string, repo: string, commit_sha: string, maxPullRequests: number): Promise<PullRequestInfo[]> {
|
||||
const mergedPRs: PullRequestInfo[] = []
|
||||
|
||||
const options = this.octokit.repos.listPullRequestsAssociatedWithCommit.endpoint.merge({
|
||||
owner,
|
||||
repo,
|
||||
commit_sha,
|
||||
per_page: `${Math.min(10, maxPullRequests)}`,
|
||||
direction: 'desc'
|
||||
})
|
||||
|
||||
for await (const response of this.octokit.paginate.iterator(options)) {
|
||||
const prs: PullsListData = response.data as PullsListData
|
||||
|
||||
for (const pr of prs) {
|
||||
mergedPRs.push(mapPullRequest(pr, pr.merged_at ? 'merged' : 'open'))
|
||||
}
|
||||
}
|
||||
|
||||
return sortPrs(mergedPRs)
|
||||
}
|
||||
|
||||
async getBetweenDates(
|
||||
owner: string,
|
||||
repo: string,
|
||||
@@ -126,7 +148,7 @@ export class PullRequests {
|
||||
}
|
||||
|
||||
// bail out early to not keep iterating on PRs super old
|
||||
return sortPrs(mergedPRs)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,7 +180,7 @@ export class PullRequests {
|
||||
}
|
||||
|
||||
// bail out early to not keep iterating on PRs super old
|
||||
return sortPrs(openPrs)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,8 +217,8 @@ export class PullRequests {
|
||||
|
||||
const firstCommit = commits[0]
|
||||
const lastCommit = commits[commits.length - 1]
|
||||
let fromDate = firstCommit.date
|
||||
const toDate = lastCommit.date
|
||||
let fromDate = moment.min(firstCommit.authorDate, firstCommit.commitDate) // get the lower date (e.g. if commits are modified)
|
||||
const toDate = moment.max(lastCommit.authorDate, lastCommit.commitDate) // ensure we get the higher date (e.g. in case of rebases)
|
||||
|
||||
const maxDays = configuration.max_back_track_time_days
|
||||
const maxFromDate = toDate.clone().subtract(maxDays, 'days')
|
||||
@@ -207,21 +229,39 @@ export class PullRequests {
|
||||
|
||||
core.info(`ℹ️ Fetching PRs between dates ${fromDate.toISOString()} to ${toDate.toISOString()} for ${owner}/${repo}`)
|
||||
|
||||
const pullRequests = await this.getBetweenDates(owner, repo, fromDate, toDate, configuration.max_pull_requests)
|
||||
|
||||
core.info(`ℹ️ Retrieved ${pullRequests.length} PRs for ${owner}/${repo} in date range from API`)
|
||||
|
||||
const prCommits = filterCommits(commits, configuration.exclude_merge_branches)
|
||||
|
||||
core.info(`ℹ️ Retrieved ${prCommits.length} release commits for ${owner}/${repo}`)
|
||||
|
||||
// create array of commits for this release
|
||||
const releaseCommitHashes = prCommits.map(commmit => {
|
||||
return commmit.sha
|
||||
const releaseCommitHashes = prCommits.map(commit => {
|
||||
return commit.sha
|
||||
})
|
||||
|
||||
let pullRequests: PullRequestInfo[]
|
||||
if (options.fetchViaCommits) {
|
||||
// fetch PRs based on commits instead (will get associated PRs per commit found)
|
||||
const prsForReleaseCommits: Map<number, PullRequestInfo> = new Map()
|
||||
for (const commit of prCommits) {
|
||||
const result = await this.getForCommitHash(owner, repo, commit.sha, configuration.max_pull_requests)
|
||||
for (const pr of result) {
|
||||
prsForReleaseCommits.set(pr.number, pr)
|
||||
}
|
||||
}
|
||||
const dedupedPrsForReleaseCommits = Array.from(prsForReleaseCommits.values())
|
||||
if (!includeOpen) {
|
||||
pullRequests = dedupedPrsForReleaseCommits.filter(pr => pr.status !== 'open')
|
||||
core.info(`ℹ️ Retrieved ${pullRequests.length} PRs for ${owner}/${repo} based on the release commit hashes`)
|
||||
} else {
|
||||
pullRequests = dedupedPrsForReleaseCommits
|
||||
core.info(`ℹ️ Retrieved ${pullRequests.length} PRs for ${owner}/${repo} based on the release commit hashes (including open)`)
|
||||
}
|
||||
} else {
|
||||
// fetch PRs based on the date range identified
|
||||
const pullRequestsBetweenDate = await this.getBetweenDates(owner, repo, fromDate, toDate, configuration.max_pull_requests)
|
||||
core.info(`ℹ️ Retrieved ${pullRequestsBetweenDate.length} PRs for ${owner}/${repo} in date range from API`)
|
||||
|
||||
// filter out pull requests not associated with this release
|
||||
const mergedPullRequests = pullRequests.filter(pr => {
|
||||
const mergedPullRequests = pullRequestsBetweenDate.filter(pr => {
|
||||
return releaseCommitHashes.includes(pr.mergeCommitSha)
|
||||
})
|
||||
|
||||
@@ -239,6 +279,8 @@ export class PullRequests {
|
||||
|
||||
core.info(`ℹ️ Retrieved ${allPullRequests.length} total PRs for ${owner}/${repo}`)
|
||||
}
|
||||
pullRequests = allPullRequests
|
||||
}
|
||||
|
||||
// retrieve base branches we allow
|
||||
const baseBranches = configuration.base_branches
|
||||
@@ -247,7 +289,7 @@ export class PullRequests {
|
||||
})
|
||||
|
||||
// return only prs if the baseBranch is matching the configuration
|
||||
const finalPrs = allPullRequests.filter(pr => {
|
||||
const finalPrs = pullRequests.filter(pr => {
|
||||
if (baseBranches.length !== 0) {
|
||||
return baseBranchPatterns.some(pattern => {
|
||||
return pr.baseBranch.match(pattern) !== null
|
||||
|
||||
@@ -50,6 +50,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 fetchViaCommits = core.getInput('fetchViaCommits') === 'true'
|
||||
const fetchReviewers = core.getInput('fetchReviewers') === 'true'
|
||||
const fetchReleaseInformation = core.getInput('fetchReleaseInformation') === 'true'
|
||||
const fetchReviews = core.getInput('fetchReviews') === 'true'
|
||||
@@ -67,6 +68,7 @@ async function run(): Promise<void> {
|
||||
includeOpen,
|
||||
failOnError,
|
||||
ignorePreReleases,
|
||||
fetchViaCommits,
|
||||
fetchReviewers,
|
||||
fetchReleaseInformation,
|
||||
fetchReviews,
|
||||
|
||||
@@ -40,6 +40,7 @@ export class ReleaseNotesBuilder {
|
||||
private includeOpen: boolean = false,
|
||||
private failOnError: boolean,
|
||||
private ignorePreReleases: boolean,
|
||||
private fetchViaCommits: boolean = false,
|
||||
private fetchReviewers: boolean = false,
|
||||
private fetchReleaseInformation: boolean = false,
|
||||
private fetchReviews: boolean = false,
|
||||
@@ -77,6 +78,7 @@ export class ReleaseNotesBuilder {
|
||||
this.includeOpen,
|
||||
this.failOnError,
|
||||
this.ignorePreReleases,
|
||||
this.fetchViaCommits,
|
||||
this.fetchReviewers,
|
||||
this.fetchReleaseInformation,
|
||||
this.fetchReviews,
|
||||
|
||||
Reference in New Issue
Block a user