Merge pull request #1032 from mikepenz/develop

dev -> main
This commit is contained in:
Mike Penz
2023-02-26 13:54:56 +01:00
committed by GitHub
11 changed files with 275 additions and 256 deletions
+47 -16
View File
@@ -310,7 +310,7 @@ For advanced use cases additional settings can be provided to the action
> **Note**: All input values are optional. It is only required to provide the `token` either via the input, or as `env` variable. > **Note**: All input values are optional. It is only required to provide the `token` either via the input, or as `env` variable.
| **Input** | **Description** | | **Input** | **Description** |
|-------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| |---------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `configurationJson` | Provide the configuration directly via the build `yml` file. Please note that `${{}}` has to be written as `#{{}}` within the `yml` file. | | `configurationJson` | Provide the configuration directly via the build `yml` file. Please note that `${{}}` has to be written as `#{{}}` within the `yml` file. |
| `configuration` | Relative path, to the `configuration.json` file, providing additional configurations | | `configuration` | Relative path, to the `configuration.json` file, providing additional configurations |
| `outputFile` | Optional relative path to a file to store the resulting changelog in. | | `outputFile` | Optional relative path to a file to store the resulting changelog in. |
@@ -336,21 +336,52 @@ 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. Table of supported placeholders allowed to be used in the `pr_template` configuration, which will be included in the release notes / changelog.
| **Placeholder** | **Description** | | **Placeholder** | **Description** |
|-------------------|-------------------------------------------------------------------| |-------------------|----------------------------------------------------------------------------------------------------|
| `${{NUMBER}}` | The number referencing this pull request. E.g. 13 | | `${{NUMBER}}` | The number referencing this pull request. E.g. 13. |
| `${{TITLE}}` | Specified title of the merged pull request | | `${{TITLE}}` | Specified title of the merged pull request. |
| `${{URL}}` | Url linking to the pull request on GitHub | | `${{URL}}` | Url linking to the pull request on GitHub. |
| `${{STATUS}}` | Status of the PR. Usually always `merged`. Possibly `Open` if `includeOpen` is configured. | | `${{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 | | `${{CREATED_AT}}` | The ISO time, the pull request was created at. |
| `${{MERGED_AT}}` | The ISO time, the pull request was merged at | | `${{MERGED_AT}}` | The ISO time, the pull request was merged at. |
| `${{MERGE_SHA}}` | The commit SHA, the pull request was merged with | | `${{MERGE_SHA}}` | The commit SHA, the pull request was merged with. |
| `${{AUTHOR}}` | Author creating and opening the pull request | | `${{AUTHOR}}` | Author creating and opening the pull request. |
| `${{LABELS}}` | The labels associated with this pull request, joined by `,` | | `${{LABELS}}` | The labels associated with this pull request, joined by `,`. |
| `${{MILESTONE}}` | Milestone this PR was part of, as assigned on GitHub | | `${{MILESTONE}}` | Milestone this PR was part of, as assigned on GitHub. |
| `${{BODY}}` | Description/Body of the pull request as specified on GitHub | | `${{BODY}}` | Description/Body of the pull request as specified on GitHub. |
| `${{ASSIGNEES}}` | Login names of assigned GitHub users, joined by `,` | | `${{ASSIGNEES}}` | Login names of assigned GitHub users, joined by `,`. |
| `${{REVIEWERS}}` | GitHub Login names of specified reviewers, joined by `,`. Requires `fetchReviewers` to be enabled. | | `${{REVIEWERS}}` | GitHub Login names of specified reviewers, joined by `,`. Requires `fetchReviewers` to be enabled. |
| `${{APPROVERS}}` | GitHub Login names of users who approved the PR, joined by `,` | | `${{APPROVERS}}` | GitHub Login names of users who approved the PR, joined by `,`. |
<details><summary><b>Array Placeholders</b></summary>
<p>
Table of special array placeholders allowed to be used in the `pr_template` configuration.
Array placeholders follow the following format: `(KEY)[(*/index)]` for example: `ASSIGNEES[*]` or `ASSIGNEES[0]`.
When using `*` values are joined by `,`.
| **Placeholder** | **Description** |
|---------------------|-------------------------------------------------------------------------------------|
| `${{ASSIGNEES[*]}}` | Login names of assigned GitHub users. |
| `${{REVIEWERS[*]}}` | GitHub Login names of specified reviewers. Requires `fetchReviewers` to be enabled. |
| `${{APPROVERS[*]}}` | GitHub Login names of users who approved the PR. |
Additionally there is a special array placeholder `REVIEWS` which allows access to it's properties:
`(KEY)[(*/index)].(property)` for example: `REVIEWS[*].author` or `REVIEWS[*].body`
| **Placeholder** | **Description** |
|-------------------------------|--------------------------------------------|
| `${{REVIEWS[*].author}}` | GitHub Login names of specified reviewers. |
| `${{REVIEWS[*].body}}` | The body of the review. |
| `${{REVIEWS[*].htmlURL}}` | The URL to the given review. |
| `${{REVIEWS[*].submittedAt}}` | The date whent he review was submitted. |
| `${{REVIEWS[*].state}}` | The state of the given review. |
</p>
</details>
### Template placeholders ### Template placeholders
@@ -395,7 +426,7 @@ Table of descriptions for the `configuration.json` options to configure the resu
| category.rules | An array of `rules` used to match PRs against. Any match will include the PR. (See `exhaustive` to change this) | | category.rules | An array of `rules` used to match PRs against. Any match will include the PR. (See `exhaustive` to change this) |
| category.rules.pattern | A `regex` pattern to match the property value towards. Uses `RegExp.test("val")` | | category.rules.pattern | A `regex` pattern to match the property value towards. Uses `RegExp.test("val")` |
| category.rules.flags | Defines the regex flags specified for the pattern. Default: `gu`. | | category.rules.flags | Defines the regex flags specified for the pattern. Default: `gu`. |
| category.rules.on_property | The PR property to match against. [Possible values](https://github.com/mikepenz/release-changelog-builder-action/blob/feature/category_rules/src/configuration.ts#L33-L43). | | category.rules.on_property | The PR property to match against. [Possible values](https://github.com/mikepenz/release-changelog-builder-action/blob/develop/src/configuration.ts#L33-L43). |
| ignore_labels | An array of labels, to match pull request labels against. If any PR label overlaps, the pull request will be ignored from the changelog. This takes precedence over category labels | | ignore_labels | An array of labels, to match pull request labels against. If any PR label overlaps, the pull request will be ignored from the changelog. This takes precedence over category labels |
| sort | A `sort` specification, offering the ability to define sort order and property. | | sort | A `sort` specification, offering the ability to define sort order and property. |
| sort.order | The sort order. Allowed values: `ASC`, `DESC` | | sort.order | The sort order. Allowed values: `ASC`, `DESC` |
@@ -455,7 +486,7 @@ Custom placeholders can be defined via the `configuration.json` as `custom_place
This example will look for JIRA tickets in the EPIC project, and extract all of these tickets. The exciting part for that case is, that the ticket is PR bound, but can be used in the global TEMPLATE, but equally also in the PR template. This is unique for CUSTOM PLACEHOLDERS as standard palceholders do not offer this functionality. This example will look for JIRA tickets in the EPIC project, and extract all of these tickets. The exciting part for that case is, that the ticket is PR bound, but can be used in the global TEMPLATE, but equally also in the PR template. This is unique for CUSTOM PLACEHOLDERS as standard palceholders do not offer this functionality.
| **Input** | **Description** | | **Input** | **Description** |
|-----------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| |---------------------------------|------------------------------------------------------------------------------------------------------------------------------|
| custom_placeholders | An array of `Placeholder` specifications, offering a flexible API to extract custom placeholders from existing placeholders. | | custom_placeholders | An array of `Placeholder` specifications, offering a flexible API to extract custom placeholders from existing placeholders. |
| custom_placeholders.name | The name of the custom placeholder. Will be used within the template. | | custom_placeholders.name | The name of the custom placeholder. Will be used within the template. |
| custom_placeholders.source | The source PLACEHOLDER, requires to be one of the existing Template or PR Template placeholders. | | custom_placeholders.source | The source PLACEHOLDER, requires to be one of the existing Template or PR Template placeholders. |
Generated Vendored
+46 -70
View File
@@ -402,10 +402,19 @@ function run() {
}); });
if (configurationJson) { if (configurationJson) {
configJson = (0, utils_1.parseConfiguration)(configurationJson); configJson = (0, utils_1.parseConfiguration)(configurationJson);
if (configJson) {
core.info(`️ Retreived configuration via 'configurationJson'.`);
}
} }
// read in the configuration from the file if possible // read in the configuration from the file if possible
const configurationFile = core.getInput('configuration'); const configurationFile = core.getInput('configuration');
const configFile = (0, utils_1.resolveConfiguration)(repositoryPath, configurationFile); const configFile = (0, utils_1.resolveConfiguration)(repositoryPath, configurationFile);
if (configFile) {
core.info(`️ Retreived configuration via 'configuration' (via file).`);
}
if (!configurationFile && !configFile) {
core.info(`️ No configuration provided. Using Defaults.`);
}
// merge configs, use default values from DefaultConfig on missing definition // merge configs, use default values from DefaultConfig on missing definition
const configuration = (0, utils_1.mergeConfiguration)(configJson, configFile); const configuration = (0, utils_1.mergeConfiguration)(configJson, configFile);
// read in repository inputs // read in repository inputs
@@ -616,42 +625,8 @@ class PullRequests {
return sortPrs(openPrs); return sortPrs(openPrs);
}); });
} }
getReviewers(owner, repo, pr) {
var _a, e_3, _b, _c;
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 _d = true, _e = __asyncValues(this.octokit.paginate.iterator(options)), _f; _f = yield _e.next(), _a = _f.done, !_a;) {
_c = _f.value;
_d = false;
try {
const response = _c;
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);
}
finally {
_d = true;
}
}
}
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_3) throw e_3.error; }
}
});
}
getReviews(owner, repo, pr) { getReviews(owner, repo, pr) {
var _a, e_4, _b, _c; var _a, e_3, _b, _c;
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
const options = this.octokit.pulls.listReviews.endpoint.merge({ const options = this.octokit.pulls.listReviews.endpoint.merge({
owner, owner,
@@ -677,12 +652,12 @@ class PullRequests {
} }
} }
} }
catch (e_4_1) { e_4 = { error: e_4_1 }; } catch (e_3_1) { e_3 = { error: e_3_1 }; }
finally { finally {
try { try {
if (!_d && !_a && (_b = _e.return)) yield _b.call(_e); if (!_d && !_a && (_b = _e.return)) yield _b.call(_e);
} }
finally { if (e_4) throw e_4.error; } finally { if (e_3) throw e_3.error; }
} }
pr.reviews = prReviews; pr.reviews = prReviews;
}); });
@@ -858,7 +833,11 @@ function matches(pr, extractor, extractor_usecase) {
if (extractor.onProperty !== undefined && extractor.onProperty.length === 1) { if (extractor.onProperty !== undefined && extractor.onProperty.length === 1) {
const prop = extractor.onProperty[0]; const prop = extractor.onProperty[0];
const value = (0, pullRequests_1.retrieveProperty)(pr, prop, extractor_usecase); const value = (0, pullRequests_1.retrieveProperty)(pr, prop, extractor_usecase);
return extractor.pattern.test(value); const matched = extractor.pattern.test(value);
if (core.isDebug()) {
core.debug(` Pattern ${extractor.pattern} resulted in ${matched} for ${value} on PR ${pr.number} (usecase: ${extractor_usecase})`);
}
return matched;
} }
return false; return false;
} }
@@ -1030,7 +1009,6 @@ class ReleaseNotes {
}); });
} }
getMergedPullRequests(octokit) { getMergedPullRequests(octokit) {
var _a, _b;
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
const { owner, repo, includeOpen, fetchReviewers, fetchReviews, configuration } = this.options; const { owner, repo, includeOpen, fetchReviewers, fetchReviews, configuration } = this.options;
const diffInfo = yield this.getCommitHistory(octokit); const diffInfo = yield this.getCommitHistory(octokit);
@@ -1087,33 +1065,27 @@ class ReleaseNotes {
return true; return true;
}); });
if (baseBranches.length !== 0) { if (baseBranches.length !== 0) {
core.info(`️ Retrieved ${mergedPullRequests.length} PRs for ${owner}/${repo} filtered by the 'base_branches' configuration.`); core.info(`️ Retrieved ${finalPrs.length} PRs for ${owner}/${repo} filtered by the 'base_branches' configuration.`);
} }
if (fetchReviewers) { // fetch reviewers only if enabled (requires an additional API request per PR)
core.info(`️ Fetching reviewers was enabled`); if (fetchReviews || fetchReviewers) {
// update PR information with reviewers who approved core.info(`️ Fetching reviews (or reviewers) was enabled`);
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}`);
}
}
}
else {
core.debug(`️ Fetching reviewers was disabled`);
}
if (fetchReviews) {
core.info(`️ Fetching reviews was enabled`);
// update PR information with reviewers who approved // update PR information with reviewers who approved
for (const pr of finalPrs) { for (const pr of finalPrs) {
yield pullRequestsApi.getReviews(owner, repo, pr); yield pullRequestsApi.getReviews(owner, repo, pr);
if ((((_a = pr.reviews) === null || _a === void 0 ? void 0 : _a.length) || 0) > 0) { const reviews = pr.reviews;
core.info(`️ Retrieved ${((_b = pr.reviews) === null || _b === void 0 ? void 0 : _b.length) || 0} review(s) for PR ${owner}/${repo}/#${pr.number}`); if (reviews && ((reviews === null || reviews === void 0 ? void 0 : reviews.length) || 0) > 0) {
core.info(`️ Retrieved ${reviews.length || 0} review(s) for PR ${owner}/${repo}/#${pr.number}`);
// backwards compatiblity
pr.approvedReviewers = reviews.filter(r => r.state === 'APPROVED').map(r => r.author);
}
else {
core.debug(`No reviewer(s) for PR ${owner}/${repo}/#${pr.number}`);
} }
} }
} }
else { else {
core.debug(`️ Fetching reviews was disabled`); core.debug(`️ Fetching reviews (or reviewers) was disabled`);
} }
return [diffInfo, finalPrs]; return [diffInfo, finalPrs];
}); });
@@ -1753,6 +1725,9 @@ function buildChangelog(diffInfo, prs, options) {
for (const label of extracted) { for (const label of extracted) {
pr.labels.add(label); pr.labels.add(label);
} }
if (core.isDebug()) {
core.debug(` Extracted the following labels (${JSON.stringify(extracted)}) for PR ${pr.number}`);
}
} }
} }
} }
@@ -1797,10 +1772,8 @@ function buildChangelog(diffInfo, prs, options) {
if (category.exclude_labels !== undefined) { if (category.exclude_labels !== undefined) {
if ((0, utils_1.haveCommonElements)(category.exclude_labels.map(lbl => lbl.toLocaleLowerCase('en')), pr.labels)) { if ((0, utils_1.haveCommonElements)(category.exclude_labels.map(lbl => lbl.toLocaleLowerCase('en')), pr.labels)) {
if (core.isDebug()) { if (core.isDebug()) {
const prNum = pr.number;
const prLabels = pr.labels;
const excludeLabels = JSON.stringify(category.exclude_labels); const excludeLabels = JSON.stringify(category.exclude_labels);
core.debug(`PR ${prNum} with labels: ${prLabels} excluded from category via exclude label: ${excludeLabels}`); core.debug(` PR ${pr.number} with labels: ${pr.labels} excluded from category via exclude label: ${excludeLabels}`);
} }
continue; // one of the exclude labels matched, skip the PR for this category continue; // one of the exclude labels matched, skip the PR for this category
} }
@@ -1939,7 +1912,7 @@ function replaceEmptyTemplate(template, options) {
} }
const placeholderMap = new Map(); const placeholderMap = new Map();
fillAdditionalPlaceholders(options, placeholderMap); fillAdditionalPlaceholders(options, placeholderMap);
return replacePlaceholders(template, new Map(), placeholderMap, placeholders, undefined, options.configuration); return replacePlaceholders(template, EMPTY_MAP, placeholderMap, placeholders, undefined, options.configuration);
} }
exports.replaceEmptyTemplate = replaceEmptyTemplate; exports.replaceEmptyTemplate = replaceEmptyTemplate;
function fillAdditionalPlaceholders(options, placeholderMap /* placeholderKey and original value */) { function fillAdditionalPlaceholders(options, placeholderMap /* placeholderKey and original value */) {
@@ -2027,18 +2000,18 @@ function handlePlaceholder(template, key, value, placeholders /* placeholders to
} }
function fillArrayPlaceholders(placeholderMap /* placeholderKey and original value */, key, values) { function fillArrayPlaceholders(placeholderMap /* placeholderKey and original value */, key, values) {
for (let i = 0; i < values.length; i++) { for (let i = 0; i < values.length; i++) {
placeholderMap.set(`\${{${key}[${i}]}}`, values[i]); placeholderMap.set(`${key}[${i}]`, values[i]);
} }
placeholderMap.set(`\${{${key}[*]}}`, values.join(', ')); placeholderMap.set(`${key}[*]`, values.join(', '));
} }
function fillReviewPlaceholders(placeholderMap /* placeholderKey and original value */, parentKey, values) { function fillReviewPlaceholders(placeholderMap /* placeholderKey and original value */, parentKey, values) {
var _a; var _a;
// retrieve the keys from the CommentInfo object // retrieve the keys from the CommentInfo object
for (const childKey of Object.keys(pullRequests_1.EMPTY_COMMENT_INFO)) { for (const childKey of Object.keys(pullRequests_1.EMPTY_COMMENT_INFO)) {
for (let i = 0; i < values.length; i++) { for (let i = 0; i < values.length; i++) {
placeholderMap.set(`\${{${parentKey}[${i}].${childKey}}}`, ((_a = values[i][childKey]) === null || _a === void 0 ? void 0 : _a.toLocaleString('en')) || ''); placeholderMap.set(`${parentKey}[${i}].${childKey}`, ((_a = values[i][childKey]) === null || _a === void 0 ? void 0 : _a.toLocaleString('en')) || '');
} }
placeholderMap.set(`\${{${parentKey}[*].${childKey}}}`, values.map(value => { var _a; return ((_a = value[childKey]) === null || _a === void 0 ? void 0 : _a.toLocaleString('en')) || ''; }).join(', ')); placeholderMap.set(`${parentKey}[*].${childKey}`, values.map(value => { var _a; return ((_a = value[childKey]) === null || _a === void 0 ? void 0 : _a.toLocaleString('en')) || ''; }).join(', '));
} }
} }
function replacePrPlaceholders(template, placeholderPrMap /* map with all pr related custom placeholder values */, configuration) { function replacePrPlaceholders(template, placeholderPrMap /* map with all pr related custom placeholder values */, configuration) {
@@ -2198,23 +2171,26 @@ exports.failOrError = failOrError;
* Retrieves the configuration given the file path, if not found it will fallback to the `DefaultConfiguration` * Retrieves the configuration given the file path, if not found it will fallback to the `DefaultConfiguration`
*/ */
function resolveConfiguration(githubWorkspacePath, configurationFile) { function resolveConfiguration(githubWorkspacePath, configurationFile) {
let configuration = configuration_1.DefaultConfiguration;
if (configurationFile) { if (configurationFile) {
const configurationPath = path.resolve(githubWorkspacePath, configurationFile); const configurationPath = path.resolve(githubWorkspacePath, configurationFile);
core.debug(`configurationPath = '${configurationPath}'`); core.debug(`configurationPath = '${configurationPath}'`);
const providedConfiguration = readConfiguration(configurationPath); const providedConfiguration = readConfiguration(configurationPath);
if (providedConfiguration) { if (providedConfiguration) {
configuration = providedConfiguration; const configuration = providedConfiguration;
core.info(`️ Configuration successfully loaded.`); core.info(`️ Configuration successfully loaded.`);
if (core.isDebug()) { if (core.isDebug()) {
core.debug(`configuration = ${JSON.stringify(configuration)}`); core.debug(`configuration = ${JSON.stringify(configuration)}`);
} }
return configuration;
}
else {
core.debug(`Configuration file could not be read.`);
} }
} }
else { else {
core.info(`Configuration not provided. Using Defaults.`); core.debug(`Configuration file not provided.`);
} }
return configuration; return undefined;
} }
exports.resolveConfiguration = resolveConfiguration; exports.resolveConfiguration = resolveConfiguration;
/** /**
Generated Vendored
+1 -1
View File
File diff suppressed because one or more lines are too long
+100 -83
View File
@@ -21,11 +21,11 @@
}, },
"devDependencies": { "devDependencies": {
"@types/jest": "^29.4.0", "@types/jest": "^29.4.0",
"@types/node": "^18.14.0", "@types/node": "^18.14.1",
"@types/semver": "^7.3.13", "@types/semver": "^7.3.13",
"@typescript-eslint/parser": "^5.52.0", "@typescript-eslint/parser": "^5.53.0",
"@vercel/ncc": "^0.36.1", "@vercel/ncc": "^0.36.1",
"eslint": "^8.34.0", "eslint": "^8.35.0",
"eslint-plugin-github": "^4.6.1", "eslint-plugin-github": "^4.6.1",
"eslint-plugin-jest": "^27.2.1", "eslint-plugin-jest": "^27.2.1",
"jest": "^29.4.3", "jest": "^29.4.3",
@@ -695,9 +695,9 @@
"dev": true "dev": true
}, },
"node_modules/@eslint/eslintrc": { "node_modules/@eslint/eslintrc": {
"version": "1.4.1", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.1.tgz", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.0.tgz",
"integrity": "sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==", "integrity": "sha512-fluIaaV+GyV24CCu/ggiHdV+j4RNh85yQnAYS/G2mZODZgGmmlrgCydjUcV3YvxCm9x8nMAfThsqTni4KiXT4A==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"ajv": "^6.12.4", "ajv": "^6.12.4",
@@ -717,6 +717,15 @@
"url": "https://opencollective.com/eslint" "url": "https://opencollective.com/eslint"
} }
}, },
"node_modules/@eslint/js": {
"version": "8.35.0",
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.35.0.tgz",
"integrity": "sha512-JXdzbRiWclLVoD8sNUjR443VVlYqiYmDVT6rGUEIEHU5YJW0gaVZwV2xgM7D4arkvASqD0IlLUVjHiFuxaftRw==",
"dev": true,
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
}
},
"node_modules/@github/browserslist-config": { "node_modules/@github/browserslist-config": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/@github/browserslist-config/-/browserslist-config-1.0.0.tgz", "resolved": "https://registry.npmjs.org/@github/browserslist-config/-/browserslist-config-1.0.0.tgz",
@@ -1639,9 +1648,9 @@
"dev": true "dev": true
}, },
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "18.14.0", "version": "18.14.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.14.0.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.14.1.tgz",
"integrity": "sha512-5EWrvLmglK+imbCJY0+INViFWUHg1AHel1sq4ZVSfdcNqGy9Edv3UB9IIzzg+xPaUcAgZYcfVs2fBcwDeZzU0A==" "integrity": "sha512-QH+37Qds3E0eDlReeboBxfHbX9omAcBCXEzswCu6jySP642jiM3cYSIkU/REqwhCUqXdonHFuBfJDiAJxMNhaQ=="
}, },
"node_modules/@types/prettier": { "node_modules/@types/prettier": {
"version": "2.7.2", "version": "2.7.2",
@@ -1710,14 +1719,14 @@
} }
}, },
"node_modules/@typescript-eslint/parser": { "node_modules/@typescript-eslint/parser": {
"version": "5.52.0", "version": "5.53.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.52.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.53.0.tgz",
"integrity": "sha512-e2KiLQOZRo4Y0D/b+3y08i3jsekoSkOYStROYmPUnGMEoA0h+k2qOH5H6tcjIc68WDvGwH+PaOrP1XRzLJ6QlA==", "integrity": "sha512-MKBw9i0DLYlmdOb3Oq/526+al20AJZpANdT6Ct9ffxcV8nKCHz63t/S0IhlTFNsBIHJv+GY5SFJ0XfqVeydQrQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@typescript-eslint/scope-manager": "5.52.0", "@typescript-eslint/scope-manager": "5.53.0",
"@typescript-eslint/types": "5.52.0", "@typescript-eslint/types": "5.53.0",
"@typescript-eslint/typescript-estree": "5.52.0", "@typescript-eslint/typescript-estree": "5.53.0",
"debug": "^4.3.4" "debug": "^4.3.4"
}, },
"engines": { "engines": {
@@ -1737,13 +1746,13 @@
} }
}, },
"node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": {
"version": "5.52.0", "version": "5.53.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.52.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.53.0.tgz",
"integrity": "sha512-AR7sxxfBKiNV0FWBSARxM8DmNxrwgnYMPwmpkC1Pl1n+eT8/I2NAUPuwDy/FmDcC6F8pBfmOcaxcxRHspgOBMw==", "integrity": "sha512-Opy3dqNsp/9kBBeCPhkCNR7fmdSQqA+47r21hr9a14Bx0xnkElEQmhoHga+VoaoQ6uDHjDKmQPIYcUcKJifS7w==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@typescript-eslint/types": "5.52.0", "@typescript-eslint/types": "5.53.0",
"@typescript-eslint/visitor-keys": "5.52.0" "@typescript-eslint/visitor-keys": "5.53.0"
}, },
"engines": { "engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0" "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -1754,9 +1763,9 @@
} }
}, },
"node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": {
"version": "5.52.0", "version": "5.53.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.52.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.53.0.tgz",
"integrity": "sha512-oV7XU4CHYfBhk78fS7tkum+/Dpgsfi91IIDy7fjCyq2k6KB63M6gMC0YIvy+iABzmXThCRI6xpCEyVObBdWSDQ==", "integrity": "sha512-5kcDL9ZUIP756K6+QOAfPkigJmCPHcLN7Zjdz76lQWWDdzfOhZDTj1irs6gPBKiXx5/6O3L0+AvupAut3z7D2A==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0" "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -1767,13 +1776,13 @@
} }
}, },
"node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": {
"version": "5.52.0", "version": "5.53.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.52.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.53.0.tgz",
"integrity": "sha512-WeWnjanyEwt6+fVrSR0MYgEpUAuROxuAH516WPjUblIrClzYJj0kBbjdnbQXLpgAN8qbEuGywiQsXUVDiAoEuQ==", "integrity": "sha512-eKmipH7QyScpHSkhbptBBYh9v8FxtngLquq292YTEQ1pxVs39yFBlLC1xeIZcPPz1RWGqb7YgERJRGkjw8ZV7w==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@typescript-eslint/types": "5.52.0", "@typescript-eslint/types": "5.53.0",
"@typescript-eslint/visitor-keys": "5.52.0", "@typescript-eslint/visitor-keys": "5.53.0",
"debug": "^4.3.4", "debug": "^4.3.4",
"globby": "^11.1.0", "globby": "^11.1.0",
"is-glob": "^4.0.3", "is-glob": "^4.0.3",
@@ -1794,12 +1803,12 @@
} }
}, },
"node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": {
"version": "5.52.0", "version": "5.53.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.52.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.53.0.tgz",
"integrity": "sha512-qMwpw6SU5VHCPr99y274xhbm+PRViK/NATY6qzt+Et7+mThGuFSl/ompj2/hrBlRP/kq+BFdgagnOSgw9TB0eA==", "integrity": "sha512-JqNLnX3leaHFZEN0gCh81sIvgrp/2GOACZNgO4+Tkf64u51kTpAyWFOY8XHx8XuXr3N2C9zgPPHtcpMg6z1g0w==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@typescript-eslint/types": "5.52.0", "@typescript-eslint/types": "5.53.0",
"eslint-visitor-keys": "^3.3.0" "eslint-visitor-keys": "^3.3.0"
}, },
"engines": { "engines": {
@@ -3005,12 +3014,13 @@
} }
}, },
"node_modules/eslint": { "node_modules/eslint": {
"version": "8.34.0", "version": "8.35.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.34.0.tgz", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.35.0.tgz",
"integrity": "sha512-1Z8iFsucw+7kSqXNZVslXS8Ioa4u2KM7GPwuKtkTFAqZ/cHMcEaR+1+Br0wLlot49cNxIiZk5wp8EAbPcYZxTg==", "integrity": "sha512-BxAf1fVL7w+JLRQhWl2pzGeSiGqbWumV4WNvc9Rhp6tiCtm4oHnyPBSEtMGZwrQgudFQ+otqzWoPB7x+hxoWsw==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@eslint/eslintrc": "^1.4.1", "@eslint/eslintrc": "^2.0.0",
"@eslint/js": "8.35.0",
"@humanwhocodes/config-array": "^0.11.8", "@humanwhocodes/config-array": "^0.11.8",
"@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/module-importer": "^1.0.1",
"@nodelib/fs.walk": "^1.2.8", "@nodelib/fs.walk": "^1.2.8",
@@ -3024,7 +3034,7 @@
"eslint-utils": "^3.0.0", "eslint-utils": "^3.0.0",
"eslint-visitor-keys": "^3.3.0", "eslint-visitor-keys": "^3.3.0",
"espree": "^9.4.0", "espree": "^9.4.0",
"esquery": "^1.4.0", "esquery": "^1.4.2",
"esutils": "^2.0.2", "esutils": "^2.0.2",
"fast-deep-equal": "^3.1.3", "fast-deep-equal": "^3.1.3",
"file-entry-cache": "^6.0.1", "file-entry-cache": "^6.0.1",
@@ -3448,9 +3458,9 @@
} }
}, },
"node_modules/esquery": { "node_modules/esquery": {
"version": "1.4.0", "version": "1.4.2",
"resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.2.tgz",
"integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", "integrity": "sha512-JVSoLdTlTDkmjFmab7H/9SL9qGSyjElT3myyKp7krqjVFQCDLmj1QFaCLRFBszBKI0XVZaiiXvuPIX3ZwHe1Ng==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"estraverse": "^5.1.0" "estraverse": "^5.1.0"
@@ -3845,9 +3855,9 @@
"integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw=="
}, },
"node_modules/globals": { "node_modules/globals": {
"version": "13.19.0", "version": "13.20.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-13.19.0.tgz", "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz",
"integrity": "sha512-dkQ957uSRWHw7CFXLUtUHQI3g3aWApYhfNR2O6jn/907riyTYKVBmxYVROkBcY614FSSeSJh7Xm7SrUWCxvJMQ==", "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"type-fest": "^0.20.2" "type-fest": "^0.20.2"
@@ -7545,9 +7555,9 @@
"dev": true "dev": true
}, },
"@eslint/eslintrc": { "@eslint/eslintrc": {
"version": "1.4.1", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.1.tgz", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.0.tgz",
"integrity": "sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==", "integrity": "sha512-fluIaaV+GyV24CCu/ggiHdV+j4RNh85yQnAYS/G2mZODZgGmmlrgCydjUcV3YvxCm9x8nMAfThsqTni4KiXT4A==",
"dev": true, "dev": true,
"requires": { "requires": {
"ajv": "^6.12.4", "ajv": "^6.12.4",
@@ -7561,6 +7571,12 @@
"strip-json-comments": "^3.1.1" "strip-json-comments": "^3.1.1"
} }
}, },
"@eslint/js": {
"version": "8.35.0",
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.35.0.tgz",
"integrity": "sha512-JXdzbRiWclLVoD8sNUjR443VVlYqiYmDVT6rGUEIEHU5YJW0gaVZwV2xgM7D4arkvASqD0IlLUVjHiFuxaftRw==",
"dev": true
},
"@github/browserslist-config": { "@github/browserslist-config": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/@github/browserslist-config/-/browserslist-config-1.0.0.tgz", "resolved": "https://registry.npmjs.org/@github/browserslist-config/-/browserslist-config-1.0.0.tgz",
@@ -8334,9 +8350,9 @@
"dev": true "dev": true
}, },
"@types/node": { "@types/node": {
"version": "18.14.0", "version": "18.14.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.14.0.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.14.1.tgz",
"integrity": "sha512-5EWrvLmglK+imbCJY0+INViFWUHg1AHel1sq4ZVSfdcNqGy9Edv3UB9IIzzg+xPaUcAgZYcfVs2fBcwDeZzU0A==" "integrity": "sha512-QH+37Qds3E0eDlReeboBxfHbX9omAcBCXEzswCu6jySP642jiM3cYSIkU/REqwhCUqXdonHFuBfJDiAJxMNhaQ=="
}, },
"@types/prettier": { "@types/prettier": {
"version": "2.7.2", "version": "2.7.2",
@@ -8389,41 +8405,41 @@
} }
}, },
"@typescript-eslint/parser": { "@typescript-eslint/parser": {
"version": "5.52.0", "version": "5.53.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.52.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.53.0.tgz",
"integrity": "sha512-e2KiLQOZRo4Y0D/b+3y08i3jsekoSkOYStROYmPUnGMEoA0h+k2qOH5H6tcjIc68WDvGwH+PaOrP1XRzLJ6QlA==", "integrity": "sha512-MKBw9i0DLYlmdOb3Oq/526+al20AJZpANdT6Ct9ffxcV8nKCHz63t/S0IhlTFNsBIHJv+GY5SFJ0XfqVeydQrQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"@typescript-eslint/scope-manager": "5.52.0", "@typescript-eslint/scope-manager": "5.53.0",
"@typescript-eslint/types": "5.52.0", "@typescript-eslint/types": "5.53.0",
"@typescript-eslint/typescript-estree": "5.52.0", "@typescript-eslint/typescript-estree": "5.53.0",
"debug": "^4.3.4" "debug": "^4.3.4"
}, },
"dependencies": { "dependencies": {
"@typescript-eslint/scope-manager": { "@typescript-eslint/scope-manager": {
"version": "5.52.0", "version": "5.53.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.52.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.53.0.tgz",
"integrity": "sha512-AR7sxxfBKiNV0FWBSARxM8DmNxrwgnYMPwmpkC1Pl1n+eT8/I2NAUPuwDy/FmDcC6F8pBfmOcaxcxRHspgOBMw==", "integrity": "sha512-Opy3dqNsp/9kBBeCPhkCNR7fmdSQqA+47r21hr9a14Bx0xnkElEQmhoHga+VoaoQ6uDHjDKmQPIYcUcKJifS7w==",
"dev": true, "dev": true,
"requires": { "requires": {
"@typescript-eslint/types": "5.52.0", "@typescript-eslint/types": "5.53.0",
"@typescript-eslint/visitor-keys": "5.52.0" "@typescript-eslint/visitor-keys": "5.53.0"
} }
}, },
"@typescript-eslint/types": { "@typescript-eslint/types": {
"version": "5.52.0", "version": "5.53.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.52.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.53.0.tgz",
"integrity": "sha512-oV7XU4CHYfBhk78fS7tkum+/Dpgsfi91IIDy7fjCyq2k6KB63M6gMC0YIvy+iABzmXThCRI6xpCEyVObBdWSDQ==", "integrity": "sha512-5kcDL9ZUIP756K6+QOAfPkigJmCPHcLN7Zjdz76lQWWDdzfOhZDTj1irs6gPBKiXx5/6O3L0+AvupAut3z7D2A==",
"dev": true "dev": true
}, },
"@typescript-eslint/typescript-estree": { "@typescript-eslint/typescript-estree": {
"version": "5.52.0", "version": "5.53.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.52.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.53.0.tgz",
"integrity": "sha512-WeWnjanyEwt6+fVrSR0MYgEpUAuROxuAH516WPjUblIrClzYJj0kBbjdnbQXLpgAN8qbEuGywiQsXUVDiAoEuQ==", "integrity": "sha512-eKmipH7QyScpHSkhbptBBYh9v8FxtngLquq292YTEQ1pxVs39yFBlLC1xeIZcPPz1RWGqb7YgERJRGkjw8ZV7w==",
"dev": true, "dev": true,
"requires": { "requires": {
"@typescript-eslint/types": "5.52.0", "@typescript-eslint/types": "5.53.0",
"@typescript-eslint/visitor-keys": "5.52.0", "@typescript-eslint/visitor-keys": "5.53.0",
"debug": "^4.3.4", "debug": "^4.3.4",
"globby": "^11.1.0", "globby": "^11.1.0",
"is-glob": "^4.0.3", "is-glob": "^4.0.3",
@@ -8432,12 +8448,12 @@
} }
}, },
"@typescript-eslint/visitor-keys": { "@typescript-eslint/visitor-keys": {
"version": "5.52.0", "version": "5.53.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.52.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.53.0.tgz",
"integrity": "sha512-qMwpw6SU5VHCPr99y274xhbm+PRViK/NATY6qzt+Et7+mThGuFSl/ompj2/hrBlRP/kq+BFdgagnOSgw9TB0eA==", "integrity": "sha512-JqNLnX3leaHFZEN0gCh81sIvgrp/2GOACZNgO4+Tkf64u51kTpAyWFOY8XHx8XuXr3N2C9zgPPHtcpMg6z1g0w==",
"dev": true, "dev": true,
"requires": { "requires": {
"@typescript-eslint/types": "5.52.0", "@typescript-eslint/types": "5.53.0",
"eslint-visitor-keys": "^3.3.0" "eslint-visitor-keys": "^3.3.0"
} }
} }
@@ -9347,12 +9363,13 @@
"dev": true "dev": true
}, },
"eslint": { "eslint": {
"version": "8.34.0", "version": "8.35.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.34.0.tgz", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.35.0.tgz",
"integrity": "sha512-1Z8iFsucw+7kSqXNZVslXS8Ioa4u2KM7GPwuKtkTFAqZ/cHMcEaR+1+Br0wLlot49cNxIiZk5wp8EAbPcYZxTg==", "integrity": "sha512-BxAf1fVL7w+JLRQhWl2pzGeSiGqbWumV4WNvc9Rhp6tiCtm4oHnyPBSEtMGZwrQgudFQ+otqzWoPB7x+hxoWsw==",
"dev": true, "dev": true,
"requires": { "requires": {
"@eslint/eslintrc": "^1.4.1", "@eslint/eslintrc": "^2.0.0",
"@eslint/js": "8.35.0",
"@humanwhocodes/config-array": "^0.11.8", "@humanwhocodes/config-array": "^0.11.8",
"@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/module-importer": "^1.0.1",
"@nodelib/fs.walk": "^1.2.8", "@nodelib/fs.walk": "^1.2.8",
@@ -9366,7 +9383,7 @@
"eslint-utils": "^3.0.0", "eslint-utils": "^3.0.0",
"eslint-visitor-keys": "^3.3.0", "eslint-visitor-keys": "^3.3.0",
"espree": "^9.4.0", "espree": "^9.4.0",
"esquery": "^1.4.0", "esquery": "^1.4.2",
"esutils": "^2.0.2", "esutils": "^2.0.2",
"fast-deep-equal": "^3.1.3", "fast-deep-equal": "^3.1.3",
"file-entry-cache": "^6.0.1", "file-entry-cache": "^6.0.1",
@@ -9672,9 +9689,9 @@
"dev": true "dev": true
}, },
"esquery": { "esquery": {
"version": "1.4.0", "version": "1.4.2",
"resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.2.tgz",
"integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", "integrity": "sha512-JVSoLdTlTDkmjFmab7H/9SL9qGSyjElT3myyKp7krqjVFQCDLmj1QFaCLRFBszBKI0XVZaiiXvuPIX3ZwHe1Ng==",
"dev": true, "dev": true,
"requires": { "requires": {
"estraverse": "^5.1.0" "estraverse": "^5.1.0"
@@ -9974,9 +9991,9 @@
"integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw=="
}, },
"globals": { "globals": {
"version": "13.19.0", "version": "13.20.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-13.19.0.tgz", "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz",
"integrity": "sha512-dkQ957uSRWHw7CFXLUtUHQI3g3aWApYhfNR2O6jn/907riyTYKVBmxYVROkBcY614FSSeSJh7Xm7SrUWCxvJMQ==", "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"type-fest": "^0.20.2" "type-fest": "^0.20.2"
+3 -3
View File
@@ -44,11 +44,11 @@
}, },
"devDependencies": { "devDependencies": {
"@types/jest": "^29.4.0", "@types/jest": "^29.4.0",
"@types/node": "^18.14.0", "@types/node": "^18.14.1",
"@types/semver": "^7.3.13", "@types/semver": "^7.3.13",
"@typescript-eslint/parser": "^5.52.0", "@typescript-eslint/parser": "^5.53.0",
"@vercel/ncc": "^0.36.1", "@vercel/ncc": "^0.36.1",
"eslint": "^8.34.0", "eslint": "^8.35.0",
"eslint-plugin-github": "^4.6.1", "eslint-plugin-github": "^4.6.1",
"eslint-plugin-jest": "^27.2.1", "eslint-plugin-jest": "^27.2.1",
"jest": "^29.4.3", "jest": "^29.4.3",
+10
View File
@@ -20,10 +20,20 @@ async function run(): Promise<void> {
}) })
if (configurationJson) { if (configurationJson) {
configJson = parseConfiguration(configurationJson) configJson = parseConfiguration(configurationJson)
if (configJson) {
core.info(`️ Retreived configuration via 'configurationJson'.`)
}
} }
// read in the configuration from the file if possible // read in the configuration from the file if possible
const configurationFile: string = core.getInput('configuration') const configurationFile: string = core.getInput('configuration')
const configFile = resolveConfiguration(repositoryPath, configurationFile) const configFile = resolveConfiguration(repositoryPath, configurationFile)
if (configFile) {
core.info(`️ Retreived configuration via 'configuration' (via file).`)
}
if (!configurationFile && !configFile) {
core.info(`️ No configuration provided. Using Defaults.`)
}
// merge configs, use default values from DefaultConfig on missing definition // merge configs, use default values from DefaultConfig on missing definition
const configuration = mergeConfiguration(configJson, configFile) const configuration = mergeConfiguration(configJson, configFile)
-18
View File
@@ -47,8 +47,6 @@ type PullData = RestEndpointMethodTypes['pulls']['get']['response']['data']
type PullsListData = RestEndpointMethodTypes['pulls']['list']['response']['data'] type PullsListData = RestEndpointMethodTypes['pulls']['list']['response']['data']
type PullReviewData = RestEndpointMethodTypes['pulls']['listReviews']['response']['data']
type PullReviewsData = RestEndpointMethodTypes['pulls']['listReviews']['response']['data'] type PullReviewsData = RestEndpointMethodTypes['pulls']['listReviews']['response']['data']
export class PullRequests { export class PullRequests {
@@ -143,22 +141,6 @@ export class PullRequests {
return sortPrs(openPrs) return sortPrs(openPrs)
} }
async getReviewers(owner: string, repo: string, pr: PullRequestInfo): Promise<void> {
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[]
}
}
async getReviews(owner: string, repo: string, pr: PullRequestInfo): Promise<void> { async getReviews(owner: string, repo: string, pr: PullRequestInfo): Promise<void> {
const options = this.octokit.pulls.listReviews.endpoint.merge({ const options = this.octokit.pulls.listReviews.endpoint.merge({
owner, owner,
+5 -1
View File
@@ -29,7 +29,11 @@ function matches(pr: PullRequestInfo, extractor: RegexTransformer, extractor_use
if (extractor.onProperty !== undefined && extractor.onProperty.length === 1) { if (extractor.onProperty !== undefined && extractor.onProperty.length === 1) {
const prop = extractor.onProperty[0] const prop = extractor.onProperty[0]
const value = retrieveProperty(pr, prop, extractor_usecase) const value = retrieveProperty(pr, prop, extractor_usecase)
return extractor.pattern.test(value) const matched = extractor.pattern.test(value)
if (core.isDebug()) {
core.debug(` Pattern ${extractor.pattern} resulted in ${matched} for ${value} on PR ${pr.number} (usecase: ${extractor_usecase})`)
}
return matched
} }
return false return false
} }
+14 -19
View File
@@ -165,33 +165,28 @@ export class ReleaseNotes {
}) })
if (baseBranches.length !== 0) { if (baseBranches.length !== 0) {
core.info(`️ Retrieved ${mergedPullRequests.length} PRs for ${owner}/${repo} filtered by the 'base_branches' configuration.`) core.info(`️ Retrieved ${finalPrs.length} PRs for ${owner}/${repo} filtered by the 'base_branches' configuration.`)
} }
if (fetchReviewers) { // fetch reviewers only if enabled (requires an additional API request per PR)
core.info(`️ Fetching reviewers was enabled`) if (fetchReviews || fetchReviewers) {
// update PR information with reviewers who approved core.info(`️ Fetching reviews (or reviewers) was enabled`)
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}`)
}
}
} else {
core.debug(`️ Fetching reviewers was disabled`)
}
if (fetchReviews) {
core.info(`️ Fetching reviews was enabled`)
// update PR information with reviewers who approved // update PR information with reviewers who approved
for (const pr of finalPrs) { for (const pr of finalPrs) {
await pullRequestsApi.getReviews(owner, repo, pr) await pullRequestsApi.getReviews(owner, repo, pr)
if ((pr.reviews?.length || 0) > 0) {
core.info(`️ Retrieved ${pr.reviews?.length || 0} review(s) for PR ${owner}/${repo}/#${pr.number}`) const reviews = pr.reviews
if (reviews && (reviews?.length || 0) > 0) {
core.info(`️ Retrieved ${reviews.length || 0} review(s) for PR ${owner}/${repo}/#${pr.number}`)
// backwards compatiblity
pr.approvedReviewers = reviews.filter(r => r.state === 'APPROVED').map(r => r.author)
} else {
core.debug(`No reviewer(s) for PR ${owner}/${repo}/#${pr.number}`)
} }
} }
} else { } else {
core.debug(`️ Fetching reviews was disabled`) core.debug(`️ Fetching reviews (or reviewers) was disabled`)
} }
return [diffInfo, finalPrs] return [diffInfo, finalPrs]
+10 -8
View File
@@ -51,6 +51,10 @@ export function buildChangelog(diffInfo: DiffInfo, prs: PullRequestInfo[], optio
for (const label of extracted) { for (const label of extracted) {
pr.labels.add(label) pr.labels.add(label)
} }
if (core.isDebug()) {
core.debug(` Extracted the following labels (${JSON.stringify(extracted)}) for PR ${pr.number}`)
}
} }
} }
} }
@@ -113,10 +117,8 @@ export function buildChangelog(diffInfo: DiffInfo, prs: PullRequestInfo[], optio
) )
) { ) {
if (core.isDebug()) { if (core.isDebug()) {
const prNum = pr.number
const prLabels = pr.labels
const excludeLabels = JSON.stringify(category.exclude_labels) const excludeLabels = JSON.stringify(category.exclude_labels)
core.debug(`PR ${prNum} with labels: ${prLabels} excluded from category via exclude label: ${excludeLabels}`) core.debug(` PR ${pr.number} with labels: ${pr.labels} excluded from category via exclude label: ${excludeLabels}`)
} }
continue // one of the exclude labels matched, skip the PR for this category continue // one of the exclude labels matched, skip the PR for this category
} }
@@ -267,7 +269,7 @@ export function replaceEmptyTemplate(template: string, options: ReleaseNotesOpti
} }
const placeholderMap = new Map<string, string>() const placeholderMap = new Map<string, string>()
fillAdditionalPlaceholders(options, placeholderMap) fillAdditionalPlaceholders(options, placeholderMap)
return replacePlaceholders(template, new Map<string, string>(), placeholderMap, placeholders, undefined, options.configuration) return replacePlaceholders(template, EMPTY_MAP, placeholderMap, placeholders, undefined, options.configuration)
} }
function fillAdditionalPlaceholders( function fillAdditionalPlaceholders(
@@ -392,9 +394,9 @@ function fillArrayPlaceholders(
values: string[] values: string[]
): void { ): void {
for (let i = 0; i < values.length; i++) { for (let i = 0; i < values.length; i++) {
placeholderMap.set(`\${{${key}[${i}]}}`, values[i]) placeholderMap.set(`${key}[${i}]`, values[i])
} }
placeholderMap.set(`\${{${key}[*]}}`, values.join(', ')) placeholderMap.set(`${key}[*]`, values.join(', '))
} }
function fillReviewPlaceholders( function fillReviewPlaceholders(
@@ -405,10 +407,10 @@ function fillReviewPlaceholders(
// retrieve the keys from the CommentInfo object // retrieve the keys from the CommentInfo object
for (const childKey of Object.keys(EMPTY_COMMENT_INFO)) { for (const childKey of Object.keys(EMPTY_COMMENT_INFO)) {
for (let i = 0; i < values.length; i++) { for (let i = 0; i < values.length; i++) {
placeholderMap.set(`\${{${parentKey}[${i}].${childKey}}}`, values[i][childKey as keyof CommentInfo]?.toLocaleString('en') || '') placeholderMap.set(`${parentKey}[${i}].${childKey}`, values[i][childKey as keyof CommentInfo]?.toLocaleString('en') || '')
} }
placeholderMap.set( placeholderMap.set(
`\${{${parentKey}[*].${childKey}}}`, `${parentKey}[*].${childKey}`,
values.map(value => value[childKey as keyof CommentInfo]?.toLocaleString('en') || '').join(', ') values.map(value => value[childKey as keyof CommentInfo]?.toLocaleString('en') || '').join(', ')
) )
} }
+7 -5
View File
@@ -35,23 +35,25 @@ export function failOrError(message: string | Error, failOnError: boolean): void
/** /**
* Retrieves the configuration given the file path, if not found it will fallback to the `DefaultConfiguration` * Retrieves the configuration given the file path, if not found it will fallback to the `DefaultConfiguration`
*/ */
export function resolveConfiguration(githubWorkspacePath: string, configurationFile: string): Configuration { export function resolveConfiguration(githubWorkspacePath: string, configurationFile: string): Configuration | undefined {
let configuration = DefaultConfiguration
if (configurationFile) { if (configurationFile) {
const configurationPath = path.resolve(githubWorkspacePath, configurationFile) const configurationPath = path.resolve(githubWorkspacePath, configurationFile)
core.debug(`configurationPath = '${configurationPath}'`) core.debug(`configurationPath = '${configurationPath}'`)
const providedConfiguration = readConfiguration(configurationPath) const providedConfiguration = readConfiguration(configurationPath)
if (providedConfiguration) { if (providedConfiguration) {
configuration = providedConfiguration const configuration = providedConfiguration
core.info(`️ Configuration successfully loaded.`) core.info(`️ Configuration successfully loaded.`)
if (core.isDebug()) { if (core.isDebug()) {
core.debug(`configuration = ${JSON.stringify(configuration)}`) core.debug(`configuration = ${JSON.stringify(configuration)}`)
} }
return configuration
} else {
core.debug(`Configuration file could not be read.`)
} }
} else { } else {
core.info(`Configuration not provided. Using Defaults.`) core.debug(`Configuration file not provided.`)
} }
return configuration return undefined
} }
/** /**