@@ -168,7 +168,8 @@ This configuration is a `.json` file in the following format.
|
|||||||
"label_extractor": [
|
"label_extractor": [
|
||||||
{
|
{
|
||||||
"pattern": "(.) (.+)",
|
"pattern": "(.) (.+)",
|
||||||
"target": "$1"
|
"target": "$1",
|
||||||
|
"flags": "gu"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"pattern": "(.) (.+)",
|
"pattern": "(.) (.+)",
|
||||||
@@ -295,6 +296,7 @@ Table of descriptions for the `configuration.json` options to configure the resu
|
|||||||
| label_extractor.pattern | A `regex` pattern, extracting values of the change message. |
|
| label_extractor.pattern | A `regex` pattern, extracting values of the change message. |
|
||||||
| label_extractor.target | The result pattern. The result text will be used as label. If empty, no label is created. |
|
| label_extractor.target | The result pattern. The result text will be used as label. If empty, no label is created. |
|
||||||
| label_extractor.on_property | The property to retrieve the text from. This is optional. Defaults to: `body`. Alternative values: `title`, `author`, `milestone`. |
|
| label_extractor.on_property | The property to retrieve the text from. This is optional. Defaults to: `body`. Alternative values: `title`, `author`, `milestone`. |
|
||||||
|
| label_extractor.flags | Defines the regex flags specified for the pattern. Default: `gu` |
|
||||||
| transformers | An array of `transform` specifications, offering a flexible API to modify the text per pull request. This is applied on the change text created with `pr_template`. `transformers` are executed per change, in the order specified |
|
| transformers | An array of `transform` specifications, offering a flexible API to modify the text per pull request. This is applied on the change text created with `pr_template`. `transformers` are executed per change, in the order specified |
|
||||||
| transformer.pattern | A `regex` pattern, extracting values of the change message. |
|
| transformer.pattern | A `regex` pattern, extracting values of the change message. |
|
||||||
| transformer.target | The result pattern, the regex groups will be filled into. Allows for full transformation of a pull request message. Including potentially specified texts |
|
| transformer.target | The result pattern, the regex groups will be filled into. Allows for full transformation of a pull request message. Including potentially specified texts |
|
||||||
|
|||||||
+37
-60
@@ -425,35 +425,14 @@ class PullRequests {
|
|||||||
this.octokit = octokit;
|
this.octokit = octokit;
|
||||||
}
|
}
|
||||||
getSingle(owner, repo, prNumber) {
|
getSingle(owner, repo, prNumber) {
|
||||||
var _a, _b, _c, _d, _e;
|
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
try {
|
try {
|
||||||
const pr = yield this.octokit.pulls.get({
|
const { data } = yield this.octokit.pulls.get({
|
||||||
owner,
|
owner,
|
||||||
repo,
|
repo,
|
||||||
pull_number: prNumber
|
pull_number: prNumber
|
||||||
});
|
});
|
||||||
return {
|
return mapPullRequest(data);
|
||||||
number: pr.data.number,
|
|
||||||
title: pr.data.title,
|
|
||||||
htmlURL: pr.data.html_url,
|
|
||||||
baseBranch: pr.data.base.ref,
|
|
||||||
mergedAt: moment_1.default(pr.data.merged_at),
|
|
||||||
mergeCommitSha: pr.data.merge_commit_sha || '',
|
|
||||||
author: ((_a = pr.data.user) === null || _a === void 0 ? void 0 : _a.login) || '',
|
|
||||||
repoName: pr.data.base.repo.full_name,
|
|
||||||
labels: ((_b = pr.data.labels) === null || _b === void 0 ? void 0 : _b.map(function (label) {
|
|
||||||
return label.name || '';
|
|
||||||
})) || [],
|
|
||||||
milestone: ((_c = pr.data.milestone) === null || _c === void 0 ? void 0 : _c.title) || '',
|
|
||||||
body: pr.data.body || '',
|
|
||||||
assignees: ((_d = pr.data.assignees) === null || _d === void 0 ? void 0 : _d.map(function (asignee) {
|
|
||||||
return (asignee === null || asignee === void 0 ? void 0 : asignee.login) || '';
|
|
||||||
})) || [],
|
|
||||||
requestedReviewers: ((_e = pr.data.requested_reviewers) === null || _e === void 0 ? void 0 : _e.map(function (reviewer) {
|
|
||||||
return (reviewer === null || reviewer === void 0 ? void 0 : reviewer.login) || '';
|
|
||||||
})) || []
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
core.warning(`⚠️ Cannot find PR ${owner}/${repo}#${prNumber} - ${e.message}`);
|
core.warning(`⚠️ Cannot find PR ${owner}/${repo}#${prNumber} - ${e.message}`);
|
||||||
@@ -463,7 +442,6 @@ class PullRequests {
|
|||||||
}
|
}
|
||||||
getBetweenDates(owner, repo, fromDate, toDate, maxPullRequests) {
|
getBetweenDates(owner, repo, fromDate, toDate, maxPullRequests) {
|
||||||
var e_1, _a;
|
var e_1, _a;
|
||||||
var _b, _c, _d, _e, _f;
|
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
const mergedPRs = [];
|
const mergedPRs = [];
|
||||||
const options = this.octokit.pulls.list.endpoint.merge({
|
const options = this.octokit.pulls.list.endpoint.merge({
|
||||||
@@ -475,31 +453,11 @@ class PullRequests {
|
|||||||
direction: 'desc'
|
direction: 'desc'
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
for (var _g = __asyncValues(this.octokit.paginate.iterator(options)), _h; _h = yield _g.next(), !_h.done;) {
|
for (var _b = __asyncValues(this.octokit.paginate.iterator(options)), _c; _c = yield _b.next(), !_c.done;) {
|
||||||
const response = _h.value;
|
const response = _c.value;
|
||||||
const prs = response.data;
|
const prs = response.data;
|
||||||
for (const pr of prs.filter(p => !!p.merged_at)) {
|
for (const pr of prs.filter(p => !!p.merged_at)) {
|
||||||
mergedPRs.push({
|
mergedPRs.push(mapPullRequest(pr));
|
||||||
number: pr.number,
|
|
||||||
title: pr.title,
|
|
||||||
htmlURL: pr.html_url,
|
|
||||||
baseBranch: pr.base.ref,
|
|
||||||
mergedAt: moment_1.default(pr.merged_at),
|
|
||||||
mergeCommitSha: pr.merge_commit_sha || '',
|
|
||||||
author: ((_b = pr.user) === null || _b === void 0 ? void 0 : _b.login) || '',
|
|
||||||
repoName: pr.base.repo.full_name,
|
|
||||||
labels: ((_c = pr.labels) === null || _c === void 0 ? void 0 : _c.map(function (label) {
|
|
||||||
return label.name || '';
|
|
||||||
})) || [],
|
|
||||||
milestone: ((_d = pr.milestone) === null || _d === void 0 ? void 0 : _d.title) || '',
|
|
||||||
body: pr.body || '',
|
|
||||||
assignees: ((_e = pr.assignees) === null || _e === void 0 ? void 0 : _e.map(function (asignee) {
|
|
||||||
return (asignee === null || asignee === void 0 ? void 0 : asignee.login) || '';
|
|
||||||
})) || [],
|
|
||||||
requestedReviewers: ((_f = pr.requested_reviewers) === null || _f === void 0 ? void 0 : _f.map(function (reviewer) {
|
|
||||||
return (reviewer === null || reviewer === void 0 ? void 0 : reviewer.login) || '';
|
|
||||||
})) || []
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
const firstPR = prs[0];
|
const firstPR = prs[0];
|
||||||
if (firstPR === undefined ||
|
if (firstPR === undefined ||
|
||||||
@@ -516,7 +474,7 @@ class PullRequests {
|
|||||||
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
||||||
finally {
|
finally {
|
||||||
try {
|
try {
|
||||||
if (_h && !_h.done && (_a = _g.return)) yield _a.call(_g);
|
if (_c && !_c.done && (_a = _b.return)) yield _a.call(_b);
|
||||||
}
|
}
|
||||||
finally { if (e_1) throw e_1.error; }
|
finally { if (e_1) throw e_1.error; }
|
||||||
}
|
}
|
||||||
@@ -551,6 +509,24 @@ function sortPullRequests(pullRequests, ascending) {
|
|||||||
return pullRequests;
|
return pullRequests;
|
||||||
}
|
}
|
||||||
exports.sortPullRequests = sortPullRequests;
|
exports.sortPullRequests = sortPullRequests;
|
||||||
|
const mapPullRequest = (pr) => {
|
||||||
|
var _a, _b, _c, _d, _e;
|
||||||
|
return ({
|
||||||
|
number: pr.number,
|
||||||
|
title: pr.title,
|
||||||
|
htmlURL: pr.html_url,
|
||||||
|
baseBranch: pr.base.ref,
|
||||||
|
mergedAt: moment_1.default(pr.merged_at),
|
||||||
|
mergeCommitSha: pr.merge_commit_sha || '',
|
||||||
|
author: ((_a = pr.user) === null || _a === void 0 ? void 0 : _a.login) || '',
|
||||||
|
repoName: pr.base.repo.full_name,
|
||||||
|
labels: new Set(((_b = pr.labels) === null || _b === void 0 ? void 0 : _b.map(lbl => { var _a; return ((_a = lbl.name) === null || _a === void 0 ? void 0 : _a.toLocaleLowerCase()) || ''; })) || []),
|
||||||
|
milestone: ((_c = pr.milestone) === null || _c === void 0 ? void 0 : _c.title) || '',
|
||||||
|
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) || '')) || []
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/***/ }),
|
/***/ }),
|
||||||
@@ -713,7 +689,7 @@ class ReleaseNotes {
|
|||||||
mergeCommitSha: '',
|
mergeCommitSha: '',
|
||||||
author: commit.author || '',
|
author: commit.author || '',
|
||||||
repoName: '',
|
repoName: '',
|
||||||
labels: [],
|
labels: new Set(),
|
||||||
milestone: '',
|
milestone: '',
|
||||||
body: commit.message || '',
|
body: commit.message || '',
|
||||||
assignees: [],
|
assignees: [],
|
||||||
@@ -959,7 +935,7 @@ class Tags {
|
|||||||
try {
|
try {
|
||||||
const length = tags.length;
|
const length = tags.length;
|
||||||
for (let i = 0; i < length; i++) {
|
for (let i = 0; i < length; i++) {
|
||||||
if (tags[i].name.toLowerCase() === tag.toLowerCase()) {
|
if (tags[i].name.toLocaleLowerCase() === tag.toLocaleLowerCase()) {
|
||||||
if (ignorePreReleases) {
|
if (ignorePreReleases) {
|
||||||
core.info(`ℹ️ Enabled 'ignorePreReleases', searching for the closest release`);
|
core.info(`ℹ️ Enabled 'ignorePreReleases', searching for the closest release`);
|
||||||
for (let ii = i + 1; ii < length; ii++) {
|
for (let ii = i + 1; ii < length; ii++) {
|
||||||
@@ -1091,7 +1067,7 @@ function buildChangelog(prs, config, options) {
|
|||||||
prs = pullRequests_1.sortPullRequests(prs, sortAsc);
|
prs = pullRequests_1.sortPullRequests(prs, sortAsc);
|
||||||
core.info(`ℹ️ Sorted all pull requests ascending: ${sort}`);
|
core.info(`ℹ️ Sorted all pull requests ascending: ${sort}`);
|
||||||
// extract additional labels from the commit message
|
// extract additional labels from the commit message
|
||||||
const labelExtractors = validateTransfomers(config.label_extractor);
|
const labelExtractors = validateTransformers(config.label_extractor);
|
||||||
for (const extractor of labelExtractors) {
|
for (const extractor of labelExtractors) {
|
||||||
if (extractor.pattern != null) {
|
if (extractor.pattern != null) {
|
||||||
for (const pr of prs) {
|
for (const pr of prs) {
|
||||||
@@ -1108,18 +1084,18 @@ function buildChangelog(prs, config, options) {
|
|||||||
label = pr.body.replace(extractor.pattern, extractor.target);
|
label = pr.body.replace(extractor.pattern, extractor.target);
|
||||||
}
|
}
|
||||||
if (label !== '') {
|
if (label !== '') {
|
||||||
pr.labels.push(label);
|
pr.labels.add(label.toLocaleLowerCase());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const validatedTransformers = validateTransfomers(config.transformers);
|
const validatedTransformers = validateTransformers(config.transformers);
|
||||||
const transformedMap = new Map();
|
const transformedMap = new Map();
|
||||||
// convert PRs to their text representation
|
// convert PRs to their text representation
|
||||||
for (const pr of prs) {
|
for (const pr of prs) {
|
||||||
transformedMap.set(pr, transform(fillTemplate(pr, config.pr_template || configuration_1.DefaultConfiguration.pr_template), validatedTransformers));
|
transformedMap.set(pr, transform(fillTemplate(pr, config.pr_template || configuration_1.DefaultConfiguration.pr_template), validatedTransformers));
|
||||||
}
|
}
|
||||||
core.info(`ℹ️ Used ${validateTransfomers.length} transformers to adjust message`);
|
core.info(`ℹ️ Used ${validatedTransformers.length} transformers to adjust message`);
|
||||||
core.info(`✒️ Wrote messages for ${prs.length} pull requests`);
|
core.info(`✒️ Wrote messages for ${prs.length} pull requests`);
|
||||||
// bring PRs into the order of categories
|
// bring PRs into the order of categories
|
||||||
const categorized = new Map();
|
const categorized = new Map();
|
||||||
@@ -1133,13 +1109,13 @@ function buildChangelog(prs, config, options) {
|
|||||||
const uncategorizedPrs = [];
|
const uncategorizedPrs = [];
|
||||||
// bring elements in order
|
// bring elements in order
|
||||||
for (const [pr, body] of transformedMap) {
|
for (const [pr, body] of transformedMap) {
|
||||||
if (haveCommonElements(ignoredLabels, pr.labels)) {
|
if (haveCommonElements(ignoredLabels.map(lbl => lbl.toLocaleLowerCase()), pr.labels)) {
|
||||||
ignoredPrs.push(body);
|
ignoredPrs.push(body);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let matched = false;
|
let matched = false;
|
||||||
for (const [category, pullRequests] of categorized) {
|
for (const [category, pullRequests] of categorized) {
|
||||||
if (haveCommonElements(category.labels, pr.labels)) {
|
if (haveCommonElements(category.labels.map(lbl => lbl.toLocaleLowerCase()), pr.labels)) {
|
||||||
pullRequests.push(body);
|
pullRequests.push(body);
|
||||||
matched = true;
|
matched = true;
|
||||||
}
|
}
|
||||||
@@ -1206,7 +1182,7 @@ function fillAdditionalPlaceholders(text, options) {
|
|||||||
}
|
}
|
||||||
exports.fillAdditionalPlaceholders = fillAdditionalPlaceholders;
|
exports.fillAdditionalPlaceholders = fillAdditionalPlaceholders;
|
||||||
function haveCommonElements(arr1, arr2) {
|
function haveCommonElements(arr1, arr2) {
|
||||||
return arr1.some(item => arr2.includes(item));
|
return arr1.some(item => arr2.has(item));
|
||||||
}
|
}
|
||||||
function fillTemplate(pr, template) {
|
function fillTemplate(pr, template) {
|
||||||
var _a, _b, _c;
|
var _a, _b, _c;
|
||||||
@@ -1216,7 +1192,7 @@ function fillTemplate(pr, template) {
|
|||||||
transformed = transformed.replace(/\${{URL}}/g, pr.htmlURL);
|
transformed = transformed.replace(/\${{URL}}/g, pr.htmlURL);
|
||||||
transformed = transformed.replace(/\${{MERGED_AT}}/g, pr.mergedAt.toISOString());
|
transformed = transformed.replace(/\${{MERGED_AT}}/g, pr.mergedAt.toISOString());
|
||||||
transformed = transformed.replace(/\${{AUTHOR}}/g, pr.author);
|
transformed = transformed.replace(/\${{AUTHOR}}/g, pr.author);
|
||||||
transformed = transformed.replace(/\${{LABELS}}/g, ((_a = pr.labels) === null || _a === void 0 ? void 0 : _a.join(', ')) || '');
|
transformed = transformed.replace(/\${{LABELS}}/g, ((_a = [...pr.labels]) === null || _a === void 0 ? void 0 : _a.join(', ')) || '');
|
||||||
transformed = transformed.replace(/\${{MILESTONE}}/g, pr.milestone || '');
|
transformed = transformed.replace(/\${{MILESTONE}}/g, pr.milestone || '');
|
||||||
transformed = transformed.replace(/\${{BODY}}/g, pr.body);
|
transformed = transformed.replace(/\${{BODY}}/g, pr.body);
|
||||||
transformed = transformed.replace(/\${{ASSIGNEES}}/g, ((_b = pr.assignees) === null || _b === void 0 ? void 0 : _b.join(', ')) || '');
|
transformed = transformed.replace(/\${{ASSIGNEES}}/g, ((_b = pr.assignees) === null || _b === void 0 ? void 0 : _b.join(', ')) || '');
|
||||||
@@ -1235,17 +1211,18 @@ function transform(filled, transformers) {
|
|||||||
}
|
}
|
||||||
return transformed;
|
return transformed;
|
||||||
}
|
}
|
||||||
function validateTransfomers(specifiedTransformers) {
|
function validateTransformers(specifiedTransformers) {
|
||||||
const transformers = specifiedTransformers || configuration_1.DefaultConfiguration.transformers;
|
const transformers = specifiedTransformers || configuration_1.DefaultConfiguration.transformers;
|
||||||
return transformers
|
return transformers
|
||||||
.map(transformer => {
|
.map(transformer => {
|
||||||
|
var _a;
|
||||||
try {
|
try {
|
||||||
let onProperty = undefined;
|
let onProperty = undefined;
|
||||||
if (transformer.hasOwnProperty('on_property')) {
|
if (transformer.hasOwnProperty('on_property')) {
|
||||||
onProperty = transformer.on_property;
|
onProperty = transformer.on_property;
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
pattern: new RegExp(transformer.pattern.replace('\\\\', '\\'), 'gu'),
|
pattern: new RegExp(transformer.pattern.replace('\\\\', '\\'), (_a = transformer.flags) !== null && _a !== void 0 ? _a : 'gu'),
|
||||||
target: transformer.target,
|
target: transformer.target,
|
||||||
onProperty
|
onProperty
|
||||||
};
|
};
|
||||||
|
|||||||
+1
-1
File diff suppressed because one or more lines are too long
Generated
+381
-383
File diff suppressed because it is too large
Load Diff
+4
-4
@@ -39,18 +39,18 @@
|
|||||||
"@types/semver": "^7.3.6",
|
"@types/semver": "^7.3.6",
|
||||||
"moment": "^2.29.1",
|
"moment": "^2.29.1",
|
||||||
"semver": "^7.3.5",
|
"semver": "^7.3.5",
|
||||||
"webpack": "^5.39.1"
|
"webpack": "^5.40.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/jest": "^26.0.23",
|
"@types/jest": "^26.0.23",
|
||||||
"@types/node": "^15.12.4",
|
"@types/node": "^15.12.4",
|
||||||
"@typescript-eslint/parser": "^4.27.0",
|
"@typescript-eslint/parser": "^4.28.0",
|
||||||
"@vercel/ncc": "^0.28.6",
|
"@vercel/ncc": "^0.28.6",
|
||||||
"eslint": "^7.29.0",
|
"eslint": "^7.29.0",
|
||||||
"eslint-plugin-github": "^4.1.3",
|
"eslint-plugin-github": "^4.1.3",
|
||||||
"eslint-plugin-jest": "^24.3.6",
|
"eslint-plugin-jest": "^24.3.6",
|
||||||
"jest": "^27.0.4",
|
"jest": "^27.0.5",
|
||||||
"jest-circus": "^27.0.4",
|
"jest-circus": "^27.0.5",
|
||||||
"js-yaml": "^4.1.0",
|
"js-yaml": "^4.1.0",
|
||||||
"prettier": "2.3.1",
|
"prettier": "2.3.1",
|
||||||
"ts-jest": "^27.0.3",
|
"ts-jest": "^27.0.3",
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ export interface Category {
|
|||||||
export interface Transformer {
|
export interface Transformer {
|
||||||
pattern: string
|
pattern: string
|
||||||
target: string
|
target: string
|
||||||
|
flags?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Extractor extends Transformer {
|
export interface Extractor extends Transformer {
|
||||||
|
|||||||
+31
-52
@@ -2,6 +2,7 @@ import {Octokit, RestEndpointMethodTypes} from '@octokit/rest'
|
|||||||
import moment from 'moment'
|
import moment from 'moment'
|
||||||
|
|
||||||
import * as core from '@actions/core'
|
import * as core from '@actions/core'
|
||||||
|
import {Unpacked} from './utils'
|
||||||
|
|
||||||
export interface PullRequestInfo {
|
export interface PullRequestInfo {
|
||||||
number: number
|
number: number
|
||||||
@@ -12,13 +13,18 @@ export interface PullRequestInfo {
|
|||||||
mergeCommitSha: string
|
mergeCommitSha: string
|
||||||
author: string
|
author: string
|
||||||
repoName: string
|
repoName: string
|
||||||
labels: string[]
|
labels: Set<string>
|
||||||
milestone: string
|
milestone: string
|
||||||
body: string
|
body: string
|
||||||
assignees: string[]
|
assignees: string[]
|
||||||
requestedReviewers: string[]
|
requestedReviewers: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PullData = RestEndpointMethodTypes['pulls']['get']['response']['data']
|
||||||
|
|
||||||
|
type PullsListData =
|
||||||
|
RestEndpointMethodTypes['pulls']['list']['response']['data']
|
||||||
|
|
||||||
export class PullRequests {
|
export class PullRequests {
|
||||||
constructor(private octokit: Octokit) {}
|
constructor(private octokit: Octokit) {}
|
||||||
|
|
||||||
@@ -28,36 +34,13 @@ export class PullRequests {
|
|||||||
prNumber: number
|
prNumber: number
|
||||||
): Promise<PullRequestInfo | null> {
|
): Promise<PullRequestInfo | null> {
|
||||||
try {
|
try {
|
||||||
const pr = await this.octokit.pulls.get({
|
const {data} = await this.octokit.pulls.get({
|
||||||
owner,
|
owner,
|
||||||
repo,
|
repo,
|
||||||
pull_number: prNumber
|
pull_number: prNumber
|
||||||
})
|
})
|
||||||
|
|
||||||
return {
|
return mapPullRequest(data)
|
||||||
number: pr.data.number,
|
|
||||||
title: pr.data.title,
|
|
||||||
htmlURL: pr.data.html_url,
|
|
||||||
baseBranch: pr.data.base.ref,
|
|
||||||
mergedAt: moment(pr.data.merged_at),
|
|
||||||
mergeCommitSha: pr.data.merge_commit_sha || '',
|
|
||||||
author: pr.data.user?.login || '',
|
|
||||||
repoName: pr.data.base.repo.full_name,
|
|
||||||
labels:
|
|
||||||
pr.data.labels?.map(function (label) {
|
|
||||||
return label.name || ''
|
|
||||||
}) || [],
|
|
||||||
milestone: pr.data.milestone?.title || '',
|
|
||||||
body: pr.data.body || '',
|
|
||||||
assignees:
|
|
||||||
pr.data.assignees?.map(function (asignee) {
|
|
||||||
return asignee?.login || ''
|
|
||||||
}) || [],
|
|
||||||
requestedReviewers:
|
|
||||||
pr.data.requested_reviewers?.map(function (reviewer) {
|
|
||||||
return reviewer?.login || ''
|
|
||||||
}) || []
|
|
||||||
}
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
core.warning(
|
core.warning(
|
||||||
`⚠️ Cannot find PR ${owner}/${repo}#${prNumber} - ${e.message}`
|
`⚠️ Cannot find PR ${owner}/${repo}#${prNumber} - ${e.message}`
|
||||||
@@ -84,35 +67,10 @@ export class PullRequests {
|
|||||||
})
|
})
|
||||||
|
|
||||||
for await (const response of this.octokit.paginate.iterator(options)) {
|
for await (const response of this.octokit.paginate.iterator(options)) {
|
||||||
type PullsListData =
|
|
||||||
RestEndpointMethodTypes['pulls']['list']['response']['data']
|
|
||||||
const prs: PullsListData = response.data as PullsListData
|
const prs: PullsListData = response.data as PullsListData
|
||||||
|
|
||||||
for (const pr of prs.filter(p => !!p.merged_at)) {
|
for (const pr of prs.filter(p => !!p.merged_at)) {
|
||||||
mergedPRs.push({
|
mergedPRs.push(mapPullRequest(pr))
|
||||||
number: pr.number,
|
|
||||||
title: pr.title,
|
|
||||||
htmlURL: pr.html_url,
|
|
||||||
baseBranch: pr.base.ref,
|
|
||||||
mergedAt: moment(pr.merged_at),
|
|
||||||
mergeCommitSha: pr.merge_commit_sha || '',
|
|
||||||
author: pr.user?.login || '',
|
|
||||||
repoName: pr.base.repo.full_name,
|
|
||||||
labels:
|
|
||||||
pr.labels?.map(function (label) {
|
|
||||||
return label.name || ''
|
|
||||||
}) || [],
|
|
||||||
milestone: pr.milestone?.title || '',
|
|
||||||
body: pr.body || '',
|
|
||||||
assignees:
|
|
||||||
pr.assignees?.map(function (asignee) {
|
|
||||||
return asignee?.login || ''
|
|
||||||
}) || [],
|
|
||||||
requestedReviewers:
|
|
||||||
pr.requested_reviewers?.map(function (reviewer) {
|
|
||||||
return reviewer?.login || ''
|
|
||||||
}) || []
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const firstPR = prs[0]
|
const firstPR = prs[0]
|
||||||
@@ -159,3 +117,24 @@ export function sortPullRequests(
|
|||||||
}
|
}
|
||||||
return pullRequests
|
return pullRequests
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const mapPullRequest = (
|
||||||
|
pr: PullData | Unpacked<PullsListData>
|
||||||
|
): PullRequestInfo => ({
|
||||||
|
number: pr.number,
|
||||||
|
title: pr.title,
|
||||||
|
htmlURL: pr.html_url,
|
||||||
|
baseBranch: pr.base.ref,
|
||||||
|
mergedAt: moment(pr.merged_at),
|
||||||
|
mergeCommitSha: pr.merge_commit_sha || '',
|
||||||
|
author: pr.user?.login || '',
|
||||||
|
repoName: pr.base.repo.full_name,
|
||||||
|
labels: new Set(
|
||||||
|
pr.labels?.map(lbl => lbl.name?.toLocaleLowerCase() || '') || []
|
||||||
|
),
|
||||||
|
milestone: pr.milestone?.title || '',
|
||||||
|
body: pr.body || '',
|
||||||
|
assignees: pr.assignees?.map(asignee => asignee?.login || '') || [],
|
||||||
|
requestedReviewers:
|
||||||
|
pr.requested_reviewers?.map(reviewer => reviewer?.login || '') || []
|
||||||
|
})
|
||||||
|
|||||||
+1
-1
@@ -176,7 +176,7 @@ export class ReleaseNotes {
|
|||||||
mergeCommitSha: '',
|
mergeCommitSha: '',
|
||||||
author: commit.author || '',
|
author: commit.author || '',
|
||||||
repoName: '',
|
repoName: '',
|
||||||
labels: [],
|
labels: new Set(),
|
||||||
milestone: '',
|
milestone: '',
|
||||||
body: commit.message || '',
|
body: commit.message || '',
|
||||||
assignees: [],
|
assignees: [],
|
||||||
|
|||||||
+1
-1
@@ -65,7 +65,7 @@ export class Tags {
|
|||||||
try {
|
try {
|
||||||
const length = tags.length
|
const length = tags.length
|
||||||
for (let i = 0; i < length; i++) {
|
for (let i = 0; i < length; i++) {
|
||||||
if (tags[i].name.toLowerCase() === tag.toLowerCase()) {
|
if (tags[i].name.toLocaleLowerCase() === tag.toLocaleLowerCase()) {
|
||||||
if (ignorePreReleases) {
|
if (ignorePreReleases) {
|
||||||
core.info(
|
core.info(
|
||||||
`ℹ️ Enabled 'ignorePreReleases', searching for the closest release`
|
`ℹ️ Enabled 'ignorePreReleases', searching for the closest release`
|
||||||
|
|||||||
+24
-11
@@ -21,7 +21,7 @@ export function buildChangelog(
|
|||||||
core.info(`ℹ️ Sorted all pull requests ascending: ${sort}`)
|
core.info(`ℹ️ Sorted all pull requests ascending: ${sort}`)
|
||||||
|
|
||||||
// extract additional labels from the commit message
|
// extract additional labels from the commit message
|
||||||
const labelExtractors = validateTransfomers(config.label_extractor)
|
const labelExtractors = validateTransformers(config.label_extractor)
|
||||||
for (const extractor of labelExtractors) {
|
for (const extractor of labelExtractors) {
|
||||||
if (extractor.pattern != null) {
|
if (extractor.pattern != null) {
|
||||||
for (const pr of prs) {
|
for (const pr of prs) {
|
||||||
@@ -39,13 +39,13 @@ export function buildChangelog(
|
|||||||
label = pr.body.replace(extractor.pattern, extractor.target)
|
label = pr.body.replace(extractor.pattern, extractor.target)
|
||||||
}
|
}
|
||||||
if (label !== '') {
|
if (label !== '') {
|
||||||
pr.labels.push(label)
|
pr.labels.add(label.toLocaleLowerCase())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const validatedTransformers = validateTransfomers(config.transformers)
|
const validatedTransformers = validateTransformers(config.transformers)
|
||||||
const transformedMap = new Map<PullRequestInfo, string>()
|
const transformedMap = new Map<PullRequestInfo, string>()
|
||||||
// convert PRs to their text representation
|
// convert PRs to their text representation
|
||||||
for (const pr of prs) {
|
for (const pr of prs) {
|
||||||
@@ -61,7 +61,7 @@ export function buildChangelog(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
core.info(
|
core.info(
|
||||||
`ℹ️ Used ${validateTransfomers.length} transformers to adjust message`
|
`ℹ️ Used ${validatedTransformers.length} transformers to adjust message`
|
||||||
)
|
)
|
||||||
core.info(`✒️ Wrote messages for ${prs.length} pull requests`)
|
core.info(`✒️ Wrote messages for ${prs.length} pull requests`)
|
||||||
|
|
||||||
@@ -81,14 +81,24 @@ export function buildChangelog(
|
|||||||
|
|
||||||
// bring elements in order
|
// bring elements in order
|
||||||
for (const [pr, body] of transformedMap) {
|
for (const [pr, body] of transformedMap) {
|
||||||
if (haveCommonElements(ignoredLabels, pr.labels)) {
|
if (
|
||||||
|
haveCommonElements(
|
||||||
|
ignoredLabels.map(lbl => lbl.toLocaleLowerCase()),
|
||||||
|
pr.labels
|
||||||
|
)
|
||||||
|
) {
|
||||||
ignoredPrs.push(body)
|
ignoredPrs.push(body)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
let matched = false
|
let matched = false
|
||||||
for (const [category, pullRequests] of categorized) {
|
for (const [category, pullRequests] of categorized) {
|
||||||
if (haveCommonElements(category.labels, pr.labels)) {
|
if (
|
||||||
|
haveCommonElements(
|
||||||
|
category.labels.map(lbl => lbl.toLocaleLowerCase()),
|
||||||
|
pr.labels
|
||||||
|
)
|
||||||
|
) {
|
||||||
pullRequests.push(body)
|
pullRequests.push(body)
|
||||||
matched = true
|
matched = true
|
||||||
}
|
}
|
||||||
@@ -189,8 +199,8 @@ export function fillAdditionalPlaceholders(
|
|||||||
return transformed
|
return transformed
|
||||||
}
|
}
|
||||||
|
|
||||||
function haveCommonElements(arr1: string[], arr2: string[]): Boolean {
|
function haveCommonElements(arr1: string[], arr2: Set<string>): Boolean {
|
||||||
return arr1.some(item => arr2.includes(item))
|
return arr1.some(item => arr2.has(item))
|
||||||
}
|
}
|
||||||
|
|
||||||
function fillTemplate(pr: PullRequestInfo, template: string): string {
|
function fillTemplate(pr: PullRequestInfo, template: string): string {
|
||||||
@@ -205,7 +215,7 @@ function fillTemplate(pr: PullRequestInfo, template: string): string {
|
|||||||
transformed = transformed.replace(/\${{AUTHOR}}/g, pr.author)
|
transformed = transformed.replace(/\${{AUTHOR}}/g, pr.author)
|
||||||
transformed = transformed.replace(
|
transformed = transformed.replace(
|
||||||
/\${{LABELS}}/g,
|
/\${{LABELS}}/g,
|
||||||
pr.labels?.join(', ') || ''
|
[...pr.labels]?.join(', ') || ''
|
||||||
)
|
)
|
||||||
transformed = transformed.replace(/\${{MILESTONE}}/g, pr.milestone || '')
|
transformed = transformed.replace(/\${{MILESTONE}}/g, pr.milestone || '')
|
||||||
transformed = transformed.replace(/\${{BODY}}/g, pr.body)
|
transformed = transformed.replace(/\${{BODY}}/g, pr.body)
|
||||||
@@ -233,7 +243,7 @@ function transform(filled: string, transformers: RegexTransformer[]): string {
|
|||||||
return transformed
|
return transformed
|
||||||
}
|
}
|
||||||
|
|
||||||
function validateTransfomers(
|
function validateTransformers(
|
||||||
specifiedTransformers: Transformer[]
|
specifiedTransformers: Transformer[]
|
||||||
): RegexTransformer[] {
|
): RegexTransformer[] {
|
||||||
const transformers =
|
const transformers =
|
||||||
@@ -247,7 +257,10 @@ function validateTransfomers(
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
pattern: new RegExp(transformer.pattern.replace('\\\\', '\\'), 'gu'),
|
pattern: new RegExp(
|
||||||
|
transformer.pattern.replace('\\\\', '\\'),
|
||||||
|
transformer.flags ?? 'gu'
|
||||||
|
),
|
||||||
target: transformer.target,
|
target: transformer.target,
|
||||||
onProperty
|
onProperty
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -137,3 +137,5 @@ export function writeOutput(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type Unpacked<T> = T extends (infer U)[] ? U : T
|
||||||
|
|||||||
Reference in New Issue
Block a user