From 97e2c287ec913630371ae660a0e2a3c4599443ff Mon Sep 17 00:00:00 2001 From: Geoffrey Testelin Date: Mon, 3 May 2021 15:20:07 +0200 Subject: [PATCH 1/3] feat(logs): add a new log when an issue consumed at least one operation (#386) * docs(only-labels): enhance the docs and fix duplicate (#341) * docs(only-labels): remove duplicated option and improve descriptions a bad rebase happend * docs(readme): use a multi-line array and remove the optional column the option column was not helpful since each value is optional the multi-line array will allow to have a better UI in small devices and basically in GitHub too due to the max-width * style(readme): break line for the statistics * docs(readme): add a better description for the ascending option * docs(action): add missing punctuation * build(deps-dev): bump @typescript-eslint/eslint-plugin (#342) Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 4.15.2 to 4.16.1. - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v4.16.1/packages/eslint-plugin) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps): bump @octokit/rest from 18.3.0 to 18.3.2 (#350) Bumps [@octokit/rest](https://github.com/octokit/rest.js) from 18.3.0 to 18.3.2. - [Release notes](https://github.com/octokit/rest.js/releases) - [Commits](https://github.com/octokit/rest.js/compare/v18.3.0...v18.3.2) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * test: add more coverage for the stale label behaviour (#352) (#15) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * test: add more coverage for the stale label behaviour (#352) (#17) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * test: add more coverage for the stale label behaviour (#352) (#18) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * docs(operations-per-run): improve the doc for this option * feat(logs): add a new log when an issue consumed at least one operation the log will be visible as the last row of the processing of the given issue closes #348 * chore(readme): improve the operations per run Co-authored-by: HonkingGoose <34918129+HonkingGoose@users.noreply.github.com> * chore(readme): improve the operations per run Co-authored-by: HonkingGoose <34918129+HonkingGoose@users.noreply.github.com> * chore(readme): improve the operations per run Co-authored-by: HonkingGoose <34918129+HonkingGoose@users.noreply.github.com> * chore(readme): improve the operations per run Co-authored-by: HonkingGoose <34918129+HonkingGoose@users.noreply.github.com> * chore(readme): improve the operations per run Co-authored-by: HonkingGoose <34918129+HonkingGoose@users.noreply.github.com> * chore(readme): improve the operations per run Co-authored-by: HonkingGoose <34918129+HonkingGoose@users.noreply.github.com> * Typo in how to perform check for specific labels (#357) Not tests but feels like a typo. Or if we keep the title it `exempt` feels more approriate: exempt-issue-labels: 'roadmap' exempt-pr-labels: 'roadmap' * feat(any-of-labels): add 2 new options to customize for issues/PRs (#380) * docs(only-labels): enhance the docs and fix duplicate (#341) * docs(only-labels): remove duplicated option and improve descriptions a bad rebase happend * docs(readme): use a multi-line array and remove the optional column the option column was not helpful since each value is optional the multi-line array will allow to have a better UI in small devices and basically in GitHub too due to the max-width * style(readme): break line for the statistics * docs(readme): add a better description for the ascending option * docs(action): add missing punctuation * build(deps-dev): bump @typescript-eslint/eslint-plugin (#342) Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 4.15.2 to 4.16.1. - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v4.16.1/packages/eslint-plugin) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps): bump @octokit/rest from 18.3.0 to 18.3.2 (#350) Bumps [@octokit/rest](https://github.com/octokit/rest.js) from 18.3.0 to 18.3.2. - [Release notes](https://github.com/octokit/rest.js/releases) - [Commits](https://github.com/octokit/rest.js/compare/v18.3.0...v18.3.2) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * test: add more coverage for the stale label behaviour (#352) (#15) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * test: add more coverage for the stale label behaviour (#352) (#17) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * test: add more coverage for the stale label behaviour (#352) (#18) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * feat(any-of-labels): add 2 new options to customize for issues/PRs closes #371 change this option and only-labels to have tree-logs * chore(index): update it Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * feat(logs): enhance the logs for assignees and milestones (#382) * docs(only-labels): enhance the docs and fix duplicate (#341) * docs(only-labels): remove duplicated option and improve descriptions a bad rebase happend * docs(readme): use a multi-line array and remove the optional column the option column was not helpful since each value is optional the multi-line array will allow to have a better UI in small devices and basically in GitHub too due to the max-width * style(readme): break line for the statistics * docs(readme): add a better description for the ascending option * docs(action): add missing punctuation * build(deps-dev): bump @typescript-eslint/eslint-plugin (#342) Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 4.15.2 to 4.16.1. - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v4.16.1/packages/eslint-plugin) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps): bump @octokit/rest from 18.3.0 to 18.3.2 (#350) Bumps [@octokit/rest](https://github.com/octokit/rest.js) from 18.3.0 to 18.3.2. - [Release notes](https://github.com/octokit/rest.js/releases) - [Commits](https://github.com/octokit/rest.js/compare/v18.3.0...v18.3.2) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * test: add more coverage for the stale label behaviour (#352) (#15) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * test: add more coverage for the stale label behaviour (#352) (#17) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * test: add more coverage for the stale label behaviour (#352) (#18) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * feat(logs): enhance the logs for assignees and milestones closes #381 Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * style(typo): fix typo plural issue * style(naming): rename two methods * chore(error): remove a potential useless throw of error * style(naming): rename one method * refactor(issue): change the way to count the operations * refactor(operations): create a method to reduce code duplication Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: HonkingGoose <34918129+HonkingGoose@users.noreply.github.com> Co-authored-by: Romain Rigaux --- README.md | 19 +++- dist/index.js | 132 +++++++++++++++++--------- jest.config.js | 3 +- jest/test.ts | 11 +++ src/classes/issue.ts | 26 +++--- src/classes/issues-processor.ts | 93 +++++++++++++------ src/classes/operations.spec.ts | 49 ++++++++++ src/classes/operations.ts | 24 +---- src/classes/stale-operations.spec.ts | 134 +++++++++++++++++++++++++++ src/classes/stale-operations.ts | 19 ++++ src/classes/statistics.ts | 4 +- src/main.ts | 16 ++-- 12 files changed, 410 insertions(+), 120 deletions(-) create mode 100644 jest/test.ts create mode 100644 src/classes/operations.spec.ts create mode 100644 src/classes/stale-operations.spec.ts create mode 100644 src/classes/stale-operations.ts diff --git a/README.md b/README.md index 6fd4b20ac..ca26ac713 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Every argument is optional. | Input | Description | | --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `repo-token` | PAT(Personal Access Token) for authorizing repository.
_Defaults to **${{ github.token }}**_. | +| `repo-token` | PAT (Personal Access Token) for authorizing the repository.
_Defaults to **${{ github.token }}**_. | | `days-before-stale` | Idle number of days before marking an issue/PR as stale.
_Defaults to **60**_. | | `days-before-issue-stale` | Idle number of days before marking an issue as stale.
_Override `days-before-stale`_. | | `days-before-pr-stale` | Idle number of days before marking an PR as stale.
_Override `days-before-stale`_. | @@ -37,6 +37,8 @@ Every argument is optional. | `remove-stale-when-updated` | Remove stale label from issue/PR on updates or comments.
_Defaults to **true**_. | | `remove-issue-stale-when-updated` | Remove stale label from issue on updates or comments.
_Defaults to **true**_.
_Override `remove-stale-when-updated`_. | | `remove-pr-stale-when-updated` | Remove stale label from PR on updates or comments.
_Defaults to **true**_.
_Override `remove-stale-when-updated`_. | +| `remove-issue-stale-when-updated` | Remove stale label from issue on updates or comments.
_Defaults to **true**_.
_Override `remove-stale-when-updated`_. | +| `remove-pr-stale-when-updated` | Remove stale label from PR on updates or comments.
_Defaults to **true**_.
_Override `remove-stale-when-updated`_. | | `debug-only` | Dry-run on action.
_Defaults to **false**_. | | `ascending` | Order to get issues/PR.
`true` is ascending, `false` is descending.
_Defaults to **false**_. | | `skip-stale-issue-message` | Skip adding stale message on stale issue.
_Defaults to **false**_. | @@ -61,11 +63,22 @@ Every argument is optional. #### operations-per-run -Used to limit the number of operations made with the GitHub API to avoid reaching the [rate limit](https://docs.github.com/en/rest/overview/resources-in-the-rest-api#rate-limiting). +_Context:_ +This action performs some API calls to GitHub to fetch or close issues and pull requests, set or update labels, add comments, delete branches, etc. +These operations are made in a very short period of time - because the action is very fast to run - and can be numerous based on your project action configuration and the quantity of issues and pull requests within it. +GitHub has a [rate limit](https://docs.github.com/en/rest/overview/resources-in-the-rest-api#rate-limiting) and if reached will block all of these API calls for one hour (or API calls from other actions using the same user (a.k.a: the github-token from the [repo-token](#repo-token) option)). +This option helps you to stay within the GitHub rate limits, as you can use this option to limit the number of operations for a single run. + +_Purpose:_ +This option aims to limit the number of operations made with the GitHub API to avoid reaching the [rate limit](https://docs.github.com/en/rest/overview/resources-in-the-rest-api#rate-limiting). + Based on your project, your GitHub business plan and the date of the cron job you set for this action, you can increase this limit to a higher number. +If you are not sure which is the right value for you or if the default value is good enough, you could enable the logs and look at the end of the stale action. +If you reached the limit, you will see a warning message in the logs, telling you that you should increase the number of operations. +If you choose not to increase the limit, you might end up with un-processed issues or pull requests after a stale action run. When [debugging](#Debugging), you can set it to a much higher number like `1000` since there will be fewer operations made with the GitHub API. -Only the actor and the batch of issues (100 per batch) will consume the operations. +Only the [actor](#repo-token) and the batch of issues (100 per batch) will consume the operations. Default value: `30` diff --git a/dist/index.js b/dist/index.js index 6367819d1..86cccf8b6 100644 --- a/dist/index.js +++ b/dist/index.js @@ -153,8 +153,10 @@ Object.defineProperty(exports, "__esModule", ({ value: true })); exports.Issue = void 0; const is_labeled_1 = __nccwpck_require__(6792); const is_pull_request_1 = __nccwpck_require__(5400); +const operations_1 = __nccwpck_require__(7957); class Issue { constructor(options, issue) { + this.operations = new operations_1.Operations(); this._options = options; this.title = issue.title; this.number = issue.number; @@ -242,7 +244,7 @@ const issue_1 = __nccwpck_require__(4783); const issue_logger_1 = __nccwpck_require__(2984); const logger_1 = __nccwpck_require__(6212); const milestones_1 = __nccwpck_require__(4601); -const operations_1 = __nccwpck_require__(7957); +const stale_operations_1 = __nccwpck_require__(5080); const statistics_1 = __nccwpck_require__(3334); /*** * Handle processing of issues for staleness/closure. @@ -256,7 +258,7 @@ class IssuesProcessor { this.removedLabelIssues = []; this.options = options; this.client = github_1.getOctokit(this.options.repoToken); - this._operations = new operations_1.Operations(this.options); + this._operations = new stale_operations_1.StaleOperations(this.options); this._logger.info(chalk_1.default.yellow('Starting the stale action process...')); if (this.options.debugOnly) { this._logger.warning(chalk_1.default.yellowBright('Executing in debug mode!')); @@ -271,6 +273,13 @@ class IssuesProcessor { const millisSinceLastUpdated = new Date().getTime() - new Date(timestamp).getTime(); return millisSinceLastUpdated <= daysInMillis; } + static _endIssueProcessing(issue) { + const consumedOperationsCount = issue.operations.getConsumedOperationsCount(); + if (consumedOperationsCount > 0) { + const issueLogger = new issue_logger_1.IssueLogger(issue); + issueLogger.info(chalk_1.default.cyan(consumedOperationsCount), `operation${consumedOperationsCount > 1 ? 's' : ''} consumed for this $$type`); + } + } processIssues(page = 1) { var _a, _b; return __awaiter(this, void 0, void 0, function* () { @@ -279,8 +288,8 @@ class IssuesProcessor { const actor = yield this.getActor(); if (issues.length <= 0) { this._logger.info(chalk_1.default.green('No more issues found to process. Exiting...')); - (_a = this._statistics) === null || _a === void 0 ? void 0 : _a.setOperationsLeft(this._operations.getUnconsumedOperationsCount()).logStats(); - return this._operations.getOperationsLeftCount(); + (_a = this._statistics) === null || _a === void 0 ? void 0 : _a.setRemainingOperations(this._operations.getRemainingOperationsCount()).logStats(); + return this._operations.getRemainingOperationsCount(); } else { this._logger.info(chalk_1.default.yellow(`Processing the batch of issues ${chalk_1.default.cyan(`#${page}`)} containing ${chalk_1.default.cyan(issues.length)} issue${issues.length > 1 ? 's' : ''}...`)); @@ -316,6 +325,7 @@ class IssuesProcessor { }); if (!hasAllWhitelistedLabels) { issueLogger.info(chalk_1.default.white('└──'), `Skipping this $$type because it doesn't have all the required labels`); + IssuesProcessor._endIssueProcessing(issue); continue; // Don't process issues without all of the required labels } else { @@ -331,15 +341,18 @@ class IssuesProcessor { const shouldMarkAsStale = should_mark_when_stale_1.shouldMarkWhenStale(daysBeforeStale); if (!staleMessage && shouldMarkAsStale) { issueLogger.info(`Skipping $$type due to empty stale message`); + IssuesProcessor._endIssueProcessing(issue); continue; } if (issue.state === 'closed') { issueLogger.info(`Skipping $$type because it is closed`); - continue; // don't process closed issues + IssuesProcessor._endIssueProcessing(issue); + continue; // Don't process closed issues } if (issue.locked) { issueLogger.info(`Skipping $$type because it is locked`); - continue; // don't process locked issues + IssuesProcessor._endIssueProcessing(issue); + continue; // Don't process locked issues } // Try to remove the close label when not close/locked issue or PR yield this._removeCloseLabel(issue, closeLabel); @@ -350,12 +363,14 @@ class IssuesProcessor { // Expecting that GitHub will always set a creation date on the issues and PRs // But you never know! if (!is_valid_date_1.isValidDate(createdAt)) { + IssuesProcessor._endIssueProcessing(issue); core.setFailed(new Error(`Invalid issue field: "created_at". Expected a valid date`)); } issueLogger.info(`$$type created the ${get_humanized_date_1.getHumanizedDate(createdAt)} (${issue.created_at})`); if (!is_date_more_recent_than_1.isDateMoreRecentThan(createdAt, startDate)) { issueLogger.info(`Skipping $$type because it was created before the specified start date`); - continue; // don't process issues which were created before the start date + IssuesProcessor._endIssueProcessing(issue); + continue; // Don't process issues which were created before the start date } } if (issue.isStale) { @@ -373,7 +388,8 @@ class IssuesProcessor { yield this._removeStaleLabel(issue, staleLabel); } issueLogger.info(`Skipping $$type because it has an exempt label`); - continue; // don't process exempt issues + IssuesProcessor._endIssueProcessing(issue); + continue; // Don't process exempt issues } const anyOfLabels = words_to_list_1.wordsToList(this._getAnyOfLabels(issue)); if (anyOfLabels.length > 0) { @@ -383,6 +399,7 @@ class IssuesProcessor { }); if (!hasOneOfWhitelistedLabels) { issueLogger.info(chalk_1.default.white('└──'), `Skipping this $$type because it doesn't have one of the required labels`); + IssuesProcessor._endIssueProcessing(issue); continue; // Don't process issues without any of the required labels } else { @@ -396,44 +413,47 @@ class IssuesProcessor { } const milestones = new milestones_1.Milestones(this.options, issue); if (milestones.shouldExemptMilestones()) { - continue; // don't process exempt milestones + IssuesProcessor._endIssueProcessing(issue); + continue; // Don't process exempt milestones } const assignees = new assignees_1.Assignees(this.options, issue); if (assignees.shouldExemptAssignees()) { - continue; // don't process exempt assignees + IssuesProcessor._endIssueProcessing(issue); + continue; // Don't process exempt assignees } - // should this issue be marked stale? + // Should this issue be marked stale? const shouldBeStale = !IssuesProcessor._updatedSince(issue.updated_at, daysBeforeStale); - // determine if this issue needs to be marked stale first + // Determine if this issue needs to be marked stale first if (!issue.isStale && shouldBeStale && shouldMarkAsStale) { issueLogger.info(`Marking $$type stale because it was last updated on ${issue.updated_at} and it does not have a stale label`); yield this._markStale(issue, staleMessage, staleLabel, skipMessage); - issue.isStale = true; // this issue is now considered stale + issue.isStale = true; // This issue is now considered stale } else if (!issue.isStale) { issueLogger.info(`Not marking as stale: shouldBeStale=${shouldBeStale}, shouldMarkAsStale=${shouldMarkAsStale}`); } - // process the issue if it was marked stale + // Process the issue if it was marked stale if (issue.isStale) { issueLogger.info(`Found a stale $$type`); yield this._processStaleIssue(issue, staleLabel, actor, closeMessage, closeLabel); } + IssuesProcessor._endIssueProcessing(issue); } - if (this._operations.hasOperationsLeft()) { + if (!this._operations.hasRemainingOperations()) { this._logger.warning(chalk_1.default.yellowBright('No more operations left! Exiting...')); this._logger.warning(chalk_1.default.yellowBright(`If you think that not enough issues were processed you could try to increase the quantity related to the ${this._logger.createOptionLink(option_1.Option.OperationsPerRun)} option which is currently set to ${chalk_1.default.cyan(this.options.operationsPerRun)}`)); return 0; } this._logger.info(chalk_1.default.green(`Batch ${chalk_1.default.cyan(`#${page}`)} processed.`)); - // do the next batch + // Do the next batch return this.processIssues(page + 1); }); } - // grab comments for an issue since a given date + // Grab comments for an issue since a given date listIssueComments(issueNumber, sinceDate) { var _a; return __awaiter(this, void 0, void 0, function* () { - // find any comments since date on the given issue + // Find any comments since date on the given issue try { this._operations.consumeOperation(); (_a = this._statistics) === null || _a === void 0 ? void 0 : _a.incrementFetchedItemsCommentsCount(); @@ -497,7 +517,7 @@ class IssuesProcessor { return __awaiter(this, void 0, void 0, function* () { const issueLogger = new issue_logger_1.IssueLogger(issue); issueLogger.info(`Checking for label on $$type`); - this._operations.consumeOperation(); + this._consumeIssueOperation(issue); (_a = this._statistics) === null || _a === void 0 ? void 0 : _a.incrementFetchedItemsEventsCount(); const options = this.client.issues.listEvents.endpoint.merge({ owner: github_1.context.repo.owner, @@ -585,7 +605,7 @@ class IssuesProcessor { } if (!skipMessage) { try { - this._operations.consumeOperation(); + this._consumeIssueOperation(issue); (_a = this._statistics) === null || _a === void 0 ? void 0 : _a.incrementAddedItemsComment(issue); yield this.client.issues.createComment({ owner: github_1.context.repo.owner, @@ -599,7 +619,7 @@ class IssuesProcessor { } } try { - this._operations.consumeOperation(); + this._consumeIssueOperation(issue); (_b = this._statistics) === null || _b === void 0 ? void 0 : _b.incrementAddedItemsLabel(issue); (_c = this._statistics) === null || _c === void 0 ? void 0 : _c.incrementStaleItemsCount(issue); yield this.client.issues.addLabels({ @@ -626,7 +646,7 @@ class IssuesProcessor { } if (closeMessage) { try { - this._operations.consumeOperation(); + this._consumeIssueOperation(issue); (_a = this._statistics) === null || _a === void 0 ? void 0 : _a.incrementAddedItemsComment(issue); yield this.client.issues.createComment({ owner: github_1.context.repo.owner, @@ -641,7 +661,7 @@ class IssuesProcessor { } if (closeLabel) { try { - this._operations.consumeOperation(); + this._consumeIssueOperation(issue); (_b = this._statistics) === null || _b === void 0 ? void 0 : _b.incrementAddedItemsLabel(issue); yield this.client.issues.addLabels({ owner: github_1.context.repo.owner, @@ -655,7 +675,7 @@ class IssuesProcessor { } } try { - this._operations.consumeOperation(); + this._consumeIssueOperation(issue); (_c = this._statistics) === null || _c === void 0 ? void 0 : _c.incrementClosedItemsCount(issue); yield this.client.issues.update({ owner: github_1.context.repo.owner, @@ -677,7 +697,7 @@ class IssuesProcessor { return; } try { - this._operations.consumeOperation(); + this._consumeIssueOperation(issue); (_a = this._statistics) === null || _a === void 0 ? void 0 : _a.incrementFetchedPullRequestsCount(); const pullRequest = yield this.client.pulls.get({ owner: github_1.context.repo.owner, @@ -708,7 +728,7 @@ class IssuesProcessor { const branch = pullRequest.head.ref; issueLogger.info(`Deleting the branch "${chalk_1.default.cyan(branch)}" from closed $$type`); try { - this._operations.consumeOperation(); + this._consumeIssueOperation(issue); (_a = this._statistics) === null || _a === void 0 ? void 0 : _a.incrementDeletedBranchesCount(); yield this.client.git.deleteRef({ owner: github_1.context.repo.owner, @@ -732,7 +752,7 @@ class IssuesProcessor { return; } try { - this._operations.consumeOperation(); + this._consumeIssueOperation(issue); (_a = this._statistics) === null || _a === void 0 ? void 0 : _a.incrementDeletedItemsLabelsCount(issue); yield this.client.issues.removeLabel({ owner: github_1.context.repo.owner, @@ -830,6 +850,10 @@ class IssuesProcessor { } }); } + _consumeIssueOperation(issue) { + this._operations.consumeOperation(); + issue.operations.consumeOperation(); + } } exports.IssuesProcessor = IssuesProcessor; @@ -1118,28 +1142,46 @@ exports.Milestones = Milestones; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.Operations = void 0; class Operations { - constructor(options) { - this._options = options; - this._operationsLeft = this._options.operationsPerRun; + constructor() { + this._operationsConsumed = 0; } consumeOperation() { return this.consumeOperations(1); } consumeOperations(quantity) { - this._operationsLeft -= quantity; + this._operationsConsumed += quantity; return this; } - getUnconsumedOperationsCount() { - return this._options.operationsPerRun - this._operationsLeft; + getConsumedOperationsCount() { + return this._operationsConsumed; } - hasOperationsLeft() { - return this._operationsLeft <= 0; +} +exports.Operations = Operations; + + +/***/ }), + +/***/ 5080: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.StaleOperations = void 0; +const operations_1 = __nccwpck_require__(7957); +class StaleOperations extends operations_1.Operations { + constructor(options) { + super(); + this._options = options; } - getOperationsLeftCount() { - return this._operationsLeft; + hasRemainingOperations() { + return this._operationsConsumed < this._options.operationsPerRun; + } + getRemainingOperationsCount() { + return this._options.operationsPerRun - this._operationsConsumed; } } -exports.Operations = Operations; +exports.StaleOperations = StaleOperations; /***/ }), @@ -1200,8 +1242,8 @@ class Statistics { } return this._incrementUndoStaleIssuesCount(increment); } - setOperationsLeft(operationsLeft) { - this._operationsCount = operationsLeft; + setRemainingOperations(remainingOperations) { + this._operationsCount = remainingOperations; return this; } incrementClosedItemsCount(issue, increment = 1) { @@ -1784,8 +1826,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }; Object.defineProperty(exports, "__esModule", ({ value: true })); const core = __importStar(__nccwpck_require__(2186)); -const is_valid_date_1 = __nccwpck_require__(891); const issues_processor_1 = __nccwpck_require__(3292); +const is_valid_date_1 = __nccwpck_require__(891); function _run() { return __awaiter(this, void 0, void 0, function* () { try { @@ -1855,14 +1897,18 @@ function _getAndValidateArgs() { 'operations-per-run' ]) { if (isNaN(parseInt(core.getInput(numberInput)))) { - core.setFailed(new Error(`Option "${numberInput}" did not parse to a valid integer`)); + const errorMessage = `Option "${numberInput}" did not parse to a valid integer`; + core.setFailed(errorMessage); + throw new Error(errorMessage); } } for (const optionalDateInput of ['start-date']) { // Ignore empty dates because it is considered as the right type for a default value (so a valid one) if (core.getInput(optionalDateInput) !== '') { if (!is_valid_date_1.isValidDate(new Date(core.getInput(optionalDateInput)))) { - core.setFailed(new Error(`Option "${optionalDateInput}" did not parse to a valid date`)); + const errorMessage = `Option "${optionalDateInput}" did not parse to a valid date`; + core.setFailed(errorMessage); + throw new Error(errorMessage); } } } diff --git a/jest.config.js b/jest.config.js index a27374193..6eaa59da9 100644 --- a/jest.config.js +++ b/jest.config.js @@ -7,5 +7,6 @@ module.exports = { transform: { '^.+\\.ts$': 'ts-jest' }, - verbose: true + verbose: true, + setupFilesAfterEnv: [`./jest/test.ts`] }; diff --git a/jest/test.ts b/jest/test.ts new file mode 100644 index 000000000..f8eaa1bdf --- /dev/null +++ b/jest/test.ts @@ -0,0 +1,11 @@ +import chalk from 'chalk'; + +// Disabled the colors to: +// - improve the performances +// - avoid to mock chalk +// - avoid to have failing tests when testing the logs due to the extra text the log message will contains +// +// Note: +// If you need to debug the log colours you can remove this line temporarily +// But some tests will fail +chalk.level = 0; diff --git a/src/classes/issue.ts b/src/classes/issue.ts index d48add6b8..932bdbc17 100644 --- a/src/classes/issue.ts +++ b/src/classes/issue.ts @@ -6,6 +6,7 @@ import {IIssuesProcessorOptions} from '../interfaces/issues-processor-options'; import {ILabel} from '../interfaces/label'; import {IMilestone} from '../interfaces/milestone'; import {IsoDateString} from '../types/iso-date-string'; +import {Operations} from './operations'; export class Issue implements IIssue { private readonly _options: IIssuesProcessorOptions; @@ -20,6 +21,19 @@ export class Issue implements IIssue { readonly milestone: IMilestone | undefined; readonly assignees: IAssignee[]; isStale: boolean; + operations = new Operations(); + + get isPullRequest(): boolean { + return isPullRequest(this); + } + + get staleLabel(): string { + return this._getStaleLabel(); + } + + get hasAssignees(): boolean { + return this.assignees.length > 0; + } constructor( options: Readonly, @@ -40,18 +54,6 @@ export class Issue implements IIssue { this.isStale = isLabeled(this, this.staleLabel); } - get isPullRequest(): boolean { - return isPullRequest(this); - } - - get staleLabel(): string { - return this._getStaleLabel(); - } - - get hasAssignees(): boolean { - return this.assignees.length > 0; - } - private _getStaleLabel(): string { return this.isPullRequest ? this._options.stalePrLabel diff --git a/src/classes/issues-processor.ts b/src/classes/issues-processor.ts index 9d3d4356e..108034248 100644 --- a/src/classes/issues-processor.ts +++ b/src/classes/issues-processor.ts @@ -21,7 +21,7 @@ import {Issue} from './issue'; import {IssueLogger} from './loggers/issue-logger'; import {Logger} from './loggers/logger'; import {Milestones} from './milestones'; -import {Operations} from './operations'; +import {StaleOperations} from './stale-operations'; import {Statistics} from './statistics'; /*** @@ -36,8 +36,23 @@ export class IssuesProcessor { return millisSinceLastUpdated <= daysInMillis; } + private static _endIssueProcessing(issue: Issue): void { + const consumedOperationsCount: number = issue.operations.getConsumedOperationsCount(); + + if (consumedOperationsCount > 0) { + const issueLogger: IssueLogger = new IssueLogger(issue); + + issueLogger.info( + chalk.cyan(consumedOperationsCount), + `operation${ + consumedOperationsCount > 1 ? 's' : '' + } consumed for this $$type` + ); + } + } + private readonly _logger: Logger = new Logger(); - private readonly _operations: Operations; + private readonly _operations: StaleOperations; private readonly _statistics: Statistics | undefined; readonly client: InstanceType; readonly options: IIssuesProcessorOptions; @@ -49,7 +64,7 @@ export class IssuesProcessor { constructor(options: IIssuesProcessorOptions) { this.options = options; this.client = getOctokit(this.options.repoToken); - this._operations = new Operations(this.options); + this._operations = new StaleOperations(this.options); this._logger.info(chalk.yellow('Starting the stale action process...')); @@ -77,10 +92,10 @@ export class IssuesProcessor { chalk.green('No more issues found to process. Exiting...') ); this._statistics - ?.setOperationsLeft(this._operations.getUnconsumedOperationsCount()) + ?.setRemainingOperations(this._operations.getRemainingOperationsCount()) .logStats(); - return this._operations.getOperationsLeftCount(); + return this._operations.getRemainingOperationsCount(); } else { this._logger.info( chalk.yellow( @@ -136,6 +151,8 @@ export class IssuesProcessor { chalk.white('└──'), `Skipping this $$type because it doesn't have all the required labels` ); + + IssuesProcessor._endIssueProcessing(issue); continue; // Don't process issues without all of the required labels } else { issueLogger.info( @@ -161,17 +178,20 @@ export class IssuesProcessor { if (!staleMessage && shouldMarkAsStale) { issueLogger.info(`Skipping $$type due to empty stale message`); + IssuesProcessor._endIssueProcessing(issue); continue; } if (issue.state === 'closed') { issueLogger.info(`Skipping $$type because it is closed`); - continue; // don't process closed issues + IssuesProcessor._endIssueProcessing(issue); + continue; // Don't process closed issues } if (issue.locked) { issueLogger.info(`Skipping $$type because it is locked`); - continue; // don't process locked issues + IssuesProcessor._endIssueProcessing(issue); + continue; // Don't process locked issues } // Try to remove the close label when not close/locked issue or PR @@ -190,6 +210,7 @@ export class IssuesProcessor { // Expecting that GitHub will always set a creation date on the issues and PRs // But you never know! if (!isValidDate(createdAt)) { + IssuesProcessor._endIssueProcessing(issue); core.setFailed( new Error( `Invalid issue field: "created_at". Expected a valid date` @@ -208,7 +229,8 @@ export class IssuesProcessor { `Skipping $$type because it was created before the specified start date` ); - continue; // don't process issues which were created before the start date + IssuesProcessor._endIssueProcessing(issue); + continue; // Don't process issues which were created before the start date } } @@ -235,7 +257,8 @@ export class IssuesProcessor { } issueLogger.info(`Skipping $$type because it has an exempt label`); - continue; // don't process exempt issues + IssuesProcessor._endIssueProcessing(issue); + continue; // Don't process exempt issues } const anyOfLabels: string[] = wordsToList(this._getAnyOfLabels(issue)); @@ -256,6 +279,7 @@ export class IssuesProcessor { chalk.white('└──'), `Skipping this $$type because it doesn't have one of the required labels` ); + IssuesProcessor._endIssueProcessing(issue); continue; // Don't process issues without any of the required labels } else { issueLogger.info( @@ -278,35 +302,37 @@ export class IssuesProcessor { const milestones: Milestones = new Milestones(this.options, issue); if (milestones.shouldExemptMilestones()) { - continue; // don't process exempt milestones + IssuesProcessor._endIssueProcessing(issue); + continue; // Don't process exempt milestones } const assignees: Assignees = new Assignees(this.options, issue); if (assignees.shouldExemptAssignees()) { - continue; // don't process exempt assignees + IssuesProcessor._endIssueProcessing(issue); + continue; // Don't process exempt assignees } - // should this issue be marked stale? + // Should this issue be marked stale? const shouldBeStale = !IssuesProcessor._updatedSince( issue.updated_at, daysBeforeStale ); - // determine if this issue needs to be marked stale first + // Determine if this issue needs to be marked stale first if (!issue.isStale && shouldBeStale && shouldMarkAsStale) { issueLogger.info( `Marking $$type stale because it was last updated on ${issue.updated_at} and it does not have a stale label` ); await this._markStale(issue, staleMessage, staleLabel, skipMessage); - issue.isStale = true; // this issue is now considered stale + issue.isStale = true; // This issue is now considered stale } else if (!issue.isStale) { issueLogger.info( `Not marking as stale: shouldBeStale=${shouldBeStale}, shouldMarkAsStale=${shouldMarkAsStale}` ); } - // process the issue if it was marked stale + // Process the issue if it was marked stale if (issue.isStale) { issueLogger.info(`Found a stale $$type`); await this._processStaleIssue( @@ -317,9 +343,11 @@ export class IssuesProcessor { closeLabel ); } + + IssuesProcessor._endIssueProcessing(issue); } - if (this._operations.hasOperationsLeft()) { + if (!this._operations.hasRemainingOperations()) { this._logger.warning( chalk.yellowBright('No more operations left! Exiting...') ); @@ -340,16 +368,16 @@ export class IssuesProcessor { chalk.green(`Batch ${chalk.cyan(`#${page}`)} processed.`) ); - // do the next batch + // Do the next batch return this.processIssues(page + 1); } - // grab comments for an issue since a given date + // Grab comments for an issue since a given date async listIssueComments( - issueNumber: number, - sinceDate: string + issueNumber: Readonly, + sinceDate: Readonly ): Promise { - // find any comments since date on the given issue + // Find any comments since date on the given issue try { this._operations.consumeOperation(); this._statistics?.incrementFetchedItemsCommentsCount(); @@ -419,7 +447,7 @@ export class IssuesProcessor { issueLogger.info(`Checking for label on $$type`); - this._operations.consumeOperation(); + this._consumeIssueOperation(issue); this._statistics?.incrementFetchedItemsEventsCount(); const options = this.client.issues.listEvents.endpoint.merge({ owner: context.repo.owner, @@ -563,7 +591,7 @@ export class IssuesProcessor { if (!skipMessage) { try { - this._operations.consumeOperation(); + this._consumeIssueOperation(issue); this._statistics?.incrementAddedItemsComment(issue); await this.client.issues.createComment({ owner: context.repo.owner, @@ -577,7 +605,7 @@ export class IssuesProcessor { } try { - this._operations.consumeOperation(); + this._consumeIssueOperation(issue); this._statistics?.incrementAddedItemsLabel(issue); this._statistics?.incrementStaleItemsCount(issue); await this.client.issues.addLabels({ @@ -608,7 +636,7 @@ export class IssuesProcessor { if (closeMessage) { try { - this._operations.consumeOperation(); + this._consumeIssueOperation(issue); this._statistics?.incrementAddedItemsComment(issue); await this.client.issues.createComment({ owner: context.repo.owner, @@ -623,7 +651,7 @@ export class IssuesProcessor { if (closeLabel) { try { - this._operations.consumeOperation(); + this._consumeIssueOperation(issue); this._statistics?.incrementAddedItemsLabel(issue); await this.client.issues.addLabels({ owner: context.repo.owner, @@ -637,7 +665,7 @@ export class IssuesProcessor { } try { - this._operations.consumeOperation(); + this._consumeIssueOperation(issue); this._statistics?.incrementClosedItemsCount(issue); await this.client.issues.update({ owner: context.repo.owner, @@ -660,7 +688,7 @@ export class IssuesProcessor { } try { - this._operations.consumeOperation(); + this._consumeIssueOperation(issue); this._statistics?.incrementFetchedPullRequestsCount(); const pullRequest = await this.client.pulls.get({ owner: context.repo.owner, @@ -699,7 +727,7 @@ export class IssuesProcessor { ); try { - this._operations.consumeOperation(); + this._consumeIssueOperation(issue); this._statistics?.incrementDeletedBranchesCount(); await this.client.git.deleteRef({ owner: context.repo.owner, @@ -729,7 +757,7 @@ export class IssuesProcessor { } try { - this._operations.consumeOperation(); + this._consumeIssueOperation(issue); this._statistics?.incrementDeletedItemsLabelsCount(issue); await this.client.issues.removeLabel({ owner: context.repo.owner, @@ -854,4 +882,9 @@ export class IssuesProcessor { this._statistics?.incrementDeletedCloseItemsLabelsCount(issue); } } + + private _consumeIssueOperation(issue: Readonly): void { + this._operations.consumeOperation(); + issue.operations.consumeOperation(); + } } diff --git a/src/classes/operations.spec.ts b/src/classes/operations.spec.ts new file mode 100644 index 000000000..c52e6c17c --- /dev/null +++ b/src/classes/operations.spec.ts @@ -0,0 +1,49 @@ +import {Operations} from './operations'; + +describe('Operations', (): void => { + let operations: Operations; + + describe('consumeOperation()', (): void => { + beforeEach((): void => { + operations = new Operations(); + }); + + it('should increase the count of operation consume by 1', (): void => { + expect.assertions(1); + operations.consumeOperation(); + + const result = operations.getConsumedOperationsCount(); + + expect(result).toStrictEqual(1); + }); + }); + + describe('consumeOperations()', (): void => { + beforeEach((): void => { + operations = new Operations(); + }); + + it('should increase the count of operation consume by the provided quantity', (): void => { + expect.assertions(1); + operations.consumeOperations(8); + + const result = operations.getConsumedOperationsCount(); + + expect(result).toStrictEqual(8); + }); + }); + + describe('getConsumedOperationsCount()', (): void => { + beforeEach((): void => { + operations = new Operations(); + }); + + it('should return 0 by default', (): void => { + expect.assertions(1); + + const result = operations.getConsumedOperationsCount(); + + expect(result).toStrictEqual(0); + }); + }); +}); diff --git a/src/classes/operations.ts b/src/classes/operations.ts index 34a775efd..3fc4bfad9 100644 --- a/src/classes/operations.ts +++ b/src/classes/operations.ts @@ -1,33 +1,17 @@ -import {IIssuesProcessorOptions} from '../interfaces/issues-processor-options'; - export class Operations { - private readonly _options: IIssuesProcessorOptions; - private _operationsLeft; - - constructor(options: Readonly) { - this._options = options; - this._operationsLeft = this._options.operationsPerRun; - } + protected _operationsConsumed = 0; consumeOperation(): Operations { return this.consumeOperations(1); } consumeOperations(quantity: Readonly): Operations { - this._operationsLeft -= quantity; + this._operationsConsumed += quantity; return this; } - getUnconsumedOperationsCount(): number { - return this._options.operationsPerRun - this._operationsLeft; - } - - hasOperationsLeft(): boolean { - return this._operationsLeft <= 0; - } - - getOperationsLeftCount(): number { - return this._operationsLeft; + getConsumedOperationsCount(): number { + return this._operationsConsumed; } } diff --git a/src/classes/stale-operations.spec.ts b/src/classes/stale-operations.spec.ts new file mode 100644 index 000000000..a44fd7f84 --- /dev/null +++ b/src/classes/stale-operations.spec.ts @@ -0,0 +1,134 @@ +import {DefaultProcessorOptions} from '../../__tests__/constants/default-processor-options'; +import {IIssuesProcessorOptions} from '../interfaces/issues-processor-options'; +import {StaleOperations} from './stale-operations'; + +interface IHasRemainingOperationsMatrix { + operationsPerRun: number; + consumeOperations: number; + hasRemainingOperations: number; +} + +interface IGetRemainingOperationsCountMatrix { + operationsPerRun: number; + consumeOperations: number; + getRemainingOperationsCount: number; +} + +describe('StaleOperations', (): void => { + let operations: StaleOperations; + let options: IIssuesProcessorOptions; + + beforeEach((): void => { + options = {...DefaultProcessorOptions}; + }); + + describe('consumeOperation()', (): void => { + beforeEach((): void => { + operations = new StaleOperations(options); + }); + + it('should increase the count of operation consume by 1', (): void => { + expect.assertions(1); + operations.consumeOperation(); + + const result = operations.getConsumedOperationsCount(); + + expect(result).toStrictEqual(1); + }); + }); + + describe('consumeOperations()', (): void => { + beforeEach((): void => { + operations = new StaleOperations(options); + }); + + it('should increase the count of operation consume by the provided quantity', (): void => { + expect.assertions(1); + operations.consumeOperations(8); + + const result = operations.getConsumedOperationsCount(); + + expect(result).toStrictEqual(8); + }); + }); + + describe('getConsumedOperationsCount()', (): void => { + beforeEach((): void => { + operations = new StaleOperations(options); + }); + + it('should return 0 by default', (): void => { + expect.assertions(1); + + const result = operations.getConsumedOperationsCount(); + + expect(result).toStrictEqual(0); + }); + }); + + describe('hasRemainingOperations()', (): void => { + beforeEach((): void => { + operations = new StaleOperations(options); + }); + + describe.each` + operationsPerRun | consumeOperations | hasRemainingOperations + ${1} | ${1} | ${false} + ${2} | ${1} | ${true} + `( + 'when the operations per run is $operationsPerRun and $consumeOperations operations were consumed', + ({ + operationsPerRun, + consumeOperations, + hasRemainingOperations + }: IHasRemainingOperationsMatrix): void => { + beforeEach((): void => { + options.operationsPerRun = operationsPerRun; + operations = new StaleOperations(options); + }); + + it(`should return ${hasRemainingOperations}`, (): void => { + expect.assertions(1); + operations.consumeOperations(consumeOperations); + + const result = operations.hasRemainingOperations(); + + expect(result).toStrictEqual(hasRemainingOperations); + }); + } + ); + }); + + describe('getRemainingOperationsCount()', (): void => { + beforeEach((): void => { + operations = new StaleOperations(options); + }); + + describe.each` + operationsPerRun | consumeOperations | getRemainingOperationsCount + ${1} | ${1} | ${0} + ${2} | ${1} | ${1} + `( + 'when the operations per run is $operationsPerRun and $consumeOperations operations were consumed', + ({ + operationsPerRun, + consumeOperations, + getRemainingOperationsCount + }: IGetRemainingOperationsCountMatrix): void => { + beforeEach((): void => { + options.operationsPerRun = operationsPerRun; + operations = new StaleOperations(options); + }); + + it(`should return ${getRemainingOperationsCount}`, (): void => { + expect.assertions(1); + operations.consumeOperations(consumeOperations); + + const result = operations.getRemainingOperationsCount(); + + expect(result).toStrictEqual(getRemainingOperationsCount); + }); + } + ); + }); +}); diff --git a/src/classes/stale-operations.ts b/src/classes/stale-operations.ts new file mode 100644 index 000000000..79c097710 --- /dev/null +++ b/src/classes/stale-operations.ts @@ -0,0 +1,19 @@ +import {IIssuesProcessorOptions} from '../interfaces/issues-processor-options'; +import {Operations} from './operations'; + +export class StaleOperations extends Operations { + private readonly _options: IIssuesProcessorOptions; + + constructor(options: Readonly) { + super(); + this._options = options; + } + + hasRemainingOperations(): boolean { + return this._operationsConsumed < this._options.operationsPerRun; + } + + getRemainingOperationsCount(): number { + return this._options.operationsPerRun - this._operationsConsumed; + } +} diff --git a/src/classes/statistics.ts b/src/classes/statistics.ts index d3b8f4a79..74dd6d458 100644 --- a/src/classes/statistics.ts +++ b/src/classes/statistics.ts @@ -65,8 +65,8 @@ export class Statistics { return this._incrementUndoStaleIssuesCount(increment); } - setOperationsLeft(operationsLeft: Readonly): Statistics { - this._operationsCount = operationsLeft; + setRemainingOperations(remainingOperations: Readonly): Statistics { + this._operationsCount = remainingOperations; return this; } diff --git a/src/main.ts b/src/main.ts index 7b8d75f55..8a2ff12da 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,6 +1,6 @@ import * as core from '@actions/core'; -import {isValidDate} from './functions/dates/is-valid-date'; import {IssuesProcessor} from './classes/issues-processor'; +import {isValidDate} from './functions/dates/is-valid-date'; import {IIssuesProcessorOptions} from './interfaces/issues-processor-options'; async function _run(): Promise { @@ -85,9 +85,9 @@ function _getAndValidateArgs(): IIssuesProcessorOptions { 'operations-per-run' ]) { if (isNaN(parseInt(core.getInput(numberInput)))) { - core.setFailed( - new Error(`Option "${numberInput}" did not parse to a valid integer`) - ); + const errorMessage = `Option "${numberInput}" did not parse to a valid integer`; + core.setFailed(errorMessage); + throw new Error(errorMessage); } } @@ -95,11 +95,9 @@ function _getAndValidateArgs(): IIssuesProcessorOptions { // Ignore empty dates because it is considered as the right type for a default value (so a valid one) if (core.getInput(optionalDateInput) !== '') { if (!isValidDate(new Date(core.getInput(optionalDateInput)))) { - core.setFailed( - new Error( - `Option "${optionalDateInput}" did not parse to a valid date` - ) - ); + const errorMessage = `Option "${optionalDateInput}" did not parse to a valid date`; + core.setFailed(errorMessage); + throw new Error(errorMessage); } } } From 74663c78d90642cdb8b7011a0f5afcb82c40d1b1 Mon Sep 17 00:00:00 2001 From: TESTELIN Geoffrey Date: Wed, 5 May 2021 23:47:10 +0200 Subject: [PATCH 2/3] chore(logs): final overhaul of the logs display more values in cyan display all the options the same way (with links pointing to the readme so that with anchors we could find them easily later make them a little more humanized add more logs especially for the stale conditions --- dist/index.js | 95 ++++++++++++------ src/classes/assignees.ts | 2 +- src/classes/issues-processor.ts | 169 +++++++++++++++++++++++++------- src/classes/milestones.ts | 2 +- 4 files changed, 198 insertions(+), 70 deletions(-) diff --git a/dist/index.js b/dist/index.js index 86cccf8b6..93b103875 100644 --- a/dist/index.js +++ b/dist/index.js @@ -33,7 +33,7 @@ class Assignees { return false; } if (this._shouldExemptAllAssignees()) { - this._issueLogger.info(chalk_1.default.white('└──'), 'Skipping $$type because it has an exempt assignee'); + this._issueLogger.info(chalk_1.default.white('└──'), 'Skipping this $$type because it has an exempt assignee'); return true; } const exemptAssignees = this._getExemptAssignees(); @@ -280,6 +280,11 @@ class IssuesProcessor { issueLogger.info(chalk_1.default.cyan(consumedOperationsCount), `operation${consumedOperationsCount > 1 ? 's' : ''} consumed for this $$type`); } } + static _getStaleMessageUsedOptionName(issue) { + return issue.isPullRequest + ? option_1.Option.StalePrMessage + : option_1.Option.StaleIssueMessage; + } processIssues(page = 1) { var _a, _b; return __awaiter(this, void 0, void 0, function* () { @@ -297,7 +302,7 @@ class IssuesProcessor { for (const issue of issues.values()) { const issueLogger = new issue_logger_1.IssueLogger(issue); (_b = this._statistics) === null || _b === void 0 ? void 0 : _b.incrementProcessedItemsCount(issue); - issueLogger.info(`Found this $$type last updated ${issue.updated_at}`); + issueLogger.info(`Found this $$type last updated at: ${chalk_1.default.cyan(issue.updated_at)}`); // calculate string based messages for this issue const staleMessage = issue.isPullRequest ? this.options.stalePrMessage @@ -319,7 +324,7 @@ class IssuesProcessor { : this._getDaysBeforeIssueStale(); const onlyLabels = words_to_list_1.wordsToList(this._getOnlyLabels(issue)); if (onlyLabels.length > 0) { - issueLogger.info(`The option "onlyLabels" was specified to only processed the issues and pull requests with all those labels (${onlyLabels.length})`); + issueLogger.info(`The option ${issueLogger.createOptionLink(option_1.Option.OnlyLabels)} was specified to only processed issues and pull requests with all those labels (${chalk_1.default.cyan(onlyLabels.length)})`); const hasAllWhitelistedLabels = onlyLabels.every((label) => { return is_labeled_1.isLabeled(issue, label); }); @@ -334,23 +339,23 @@ class IssuesProcessor { } } else { - issueLogger.info(`The option "onlyLabels" was not specified`); + issueLogger.info(`The option ${issueLogger.createOptionLink(option_1.Option.OnlyLabels)} was not specified`); issueLogger.info(chalk_1.default.white('└──'), `Continuing the process for this $$type`); } - issueLogger.info(`Days before $$type stale: ${daysBeforeStale}`); + issueLogger.info(`Days before $$type stale: ${chalk_1.default.cyan(daysBeforeStale)}`); const shouldMarkAsStale = should_mark_when_stale_1.shouldMarkWhenStale(daysBeforeStale); if (!staleMessage && shouldMarkAsStale) { - issueLogger.info(`Skipping $$type due to empty stale message`); + issueLogger.info(`Skipping this $$type because it should be marked as stale based on the option ${issueLogger.createOptionLink(this._getDaysBeforeStaleUsedOptionName(issue))} (${chalk_1.default.cyan(daysBeforeStale)}) but the option ${issueLogger.createOptionLink(IssuesProcessor._getStaleMessageUsedOptionName(issue))} is not set`); IssuesProcessor._endIssueProcessing(issue); continue; } if (issue.state === 'closed') { - issueLogger.info(`Skipping $$type because it is closed`); + issueLogger.info(`Skipping this $$type because it is closed`); IssuesProcessor._endIssueProcessing(issue); continue; // Don't process closed issues } if (issue.locked) { - issueLogger.info(`Skipping $$type because it is locked`); + issueLogger.info(`Skipping this $$type because it is locked`); IssuesProcessor._endIssueProcessing(issue); continue; // Don't process locked issues } @@ -359,16 +364,16 @@ class IssuesProcessor { if (this.options.startDate) { const startDate = new Date(this.options.startDate); const createdAt = new Date(issue.created_at); - issueLogger.info(`A start date was specified for the ${get_humanized_date_1.getHumanizedDate(startDate)} (${this.options.startDate})`); + issueLogger.info(`A start date was specified for the ${get_humanized_date_1.getHumanizedDate(startDate)} (${chalk_1.default.cyan(this.options.startDate)})`); // Expecting that GitHub will always set a creation date on the issues and PRs // But you never know! if (!is_valid_date_1.isValidDate(createdAt)) { IssuesProcessor._endIssueProcessing(issue); core.setFailed(new Error(`Invalid issue field: "created_at". Expected a valid date`)); } - issueLogger.info(`$$type created the ${get_humanized_date_1.getHumanizedDate(createdAt)} (${issue.created_at})`); + issueLogger.info(`$$type created the ${get_humanized_date_1.getHumanizedDate(createdAt)} (${chalk_1.default.cyan(issue.created_at)})`); if (!is_date_more_recent_than_1.isDateMoreRecentThan(createdAt, startDate)) { - issueLogger.info(`Skipping $$type because it was created before the specified start date`); + issueLogger.info(`Skipping this $$type because it was created before the specified start date`); IssuesProcessor._endIssueProcessing(issue); continue; // Don't process issues which were created before the start date } @@ -387,13 +392,13 @@ class IssuesProcessor { issueLogger.info(`An exempt label was added after the stale label.`); yield this._removeStaleLabel(issue, staleLabel); } - issueLogger.info(`Skipping $$type because it has an exempt label`); + issueLogger.info(`Skipping this $$type because it has an exempt label`); IssuesProcessor._endIssueProcessing(issue); continue; // Don't process exempt issues } const anyOfLabels = words_to_list_1.wordsToList(this._getAnyOfLabels(issue)); if (anyOfLabels.length > 0) { - issueLogger.info(`The option "anyOfLabels" was specified to only processed the issues and pull requests with one of those labels (${anyOfLabels.length})`); + issueLogger.info(`The option ${issueLogger.createOptionLink(option_1.Option.AnyOfLabels)} was specified to only processed the issues and pull requests with one of those labels (${chalk_1.default.cyan(anyOfLabels.length)})`); const hasOneOfWhitelistedLabels = anyOfLabels.some((label) => { return is_labeled_1.isLabeled(issue, label); }); @@ -408,7 +413,7 @@ class IssuesProcessor { } } else { - issueLogger.info(`The option "anyOfLabels" was not specified`); + issueLogger.info(`The option ${issueLogger.createOptionLink(option_1.Option.AnyOfLabels)} was not specified`); issueLogger.info(chalk_1.default.white('└──'), `Continuing the process for this $$type`); } const milestones = new milestones_1.Milestones(this.options, issue); @@ -424,17 +429,28 @@ class IssuesProcessor { // Should this issue be marked stale? const shouldBeStale = !IssuesProcessor._updatedSince(issue.updated_at, daysBeforeStale); // Determine if this issue needs to be marked stale first - if (!issue.isStale && shouldBeStale && shouldMarkAsStale) { - issueLogger.info(`Marking $$type stale because it was last updated on ${issue.updated_at} and it does not have a stale label`); - yield this._markStale(issue, staleMessage, staleLabel, skipMessage); - issue.isStale = true; // This issue is now considered stale - } - else if (!issue.isStale) { - issueLogger.info(`Not marking as stale: shouldBeStale=${shouldBeStale}, shouldMarkAsStale=${shouldMarkAsStale}`); + if (!issue.isStale) { + issueLogger.info(`This $$type is not stale`); + const updatedAtDate = new Date(issue.updated_at); + if (shouldBeStale) { + issueLogger.info(`This $$type should be stale based on the last update date the ${get_humanized_date_1.getHumanizedDate(updatedAtDate)} (${chalk_1.default.cyan(issue.updated_at)})`); + if (shouldMarkAsStale) { + issueLogger.info(`This $$type should be marked as stale based on the option ${issueLogger.createOptionLink(this._getDaysBeforeStaleUsedOptionName(issue))} (${chalk_1.default.cyan(daysBeforeStale)})`); + yield this._markStale(issue, staleMessage, staleLabel, skipMessage); + issue.isStale = true; // This issue is now considered stale + issueLogger.info(`This $$type is now stale`); + } + else { + issueLogger.info(`This $$type should not be marked as stale based on the option ${issueLogger.createOptionLink(this._getDaysBeforeStaleUsedOptionName(issue))} (${chalk_1.default.cyan(daysBeforeStale)})`); + } + } + else { + issueLogger.info(`This $$type should not be stale based on the last update date the ${get_humanized_date_1.getHumanizedDate(updatedAtDate)} (${chalk_1.default.cyan(issue.updated_at)})`); + } } // Process the issue if it was marked stale if (issue.isStale) { - issueLogger.info(`Found a stale $$type`); + issueLogger.info(`This $$type is already stale`); yield this._processStaleIssue(issue, staleLabel, actor, closeMessage, closeLabel); } IssuesProcessor._endIssueProcessing(issue); @@ -516,7 +532,7 @@ class IssuesProcessor { var _a; return __awaiter(this, void 0, void 0, function* () { const issueLogger = new issue_logger_1.IssueLogger(issue); - issueLogger.info(`Checking for label on $$type`); + issueLogger.info(`Checking for label on this $$type`); this._consumeIssueOperation(issue); (_a = this._statistics) === null || _a === void 0 ? void 0 : _a.incrementFetchedItemsEventsCount(); const options = this.client.issues.listEvents.endpoint.merge({ @@ -546,7 +562,7 @@ class IssuesProcessor { const daysBeforeClose = issue.isPullRequest ? this._getDaysBeforePrClose() : this._getDaysBeforeIssueClose(); - issueLogger.info(`Days before $$type close: ${daysBeforeClose}`); + issueLogger.info(`Days before $$type close: ${chalk_1.default.cyan(daysBeforeClose)}`); const issueHasUpdate = IssuesProcessor._updatedSince(issue.updated_at, daysBeforeClose); issueLogger.info(`$$type has been updated: ${chalk_1.default.cyan(issueHasUpdate)}`); // should we un-stale this issue? @@ -560,10 +576,10 @@ class IssuesProcessor { return; // nothing to do because we aren't closing stale issues } if (!issueHasComments && !issueHasUpdate) { - issueLogger.info(`Closing $$type because it was last updated on ${issue.updated_at}`); + issueLogger.info(`Closing $$type because it was last updated on! ${chalk_1.default.cyan(issue.updated_at)}`); yield this._closeIssue(issue, closeMessage, closeLabel); if (this.options.deleteBranch && issue.pull_request) { - issueLogger.info(`Deleting branch for as delete-branch option was specified`); + issueLogger.info(`Deleting the branch the option ${issueLogger.createOptionLink(option_1.Option.DeleteBranch)} was specified`); yield this._deleteBranch(issue); this.deletedBranchIssues.push(issue); } @@ -577,14 +593,14 @@ class IssuesProcessor { _hasCommentsSince(issue, sinceDate, actor) { return __awaiter(this, void 0, void 0, function* () { const issueLogger = new issue_logger_1.IssueLogger(issue); - issueLogger.info(`Checking for comments on $$type since ${sinceDate}`); + issueLogger.info(`Checking for comments on $$type since: ${chalk_1.default.cyan(sinceDate)}`); if (!sinceDate) { return true; } // find any comments since the date const comments = yield this.listIssueComments(issue.number, sinceDate); const filteredComments = comments.filter(comment => comment.user.type === 'User' && comment.user.login !== actor); - issueLogger.info(`Comments not made by actor or another bot: ${filteredComments.length}`); + issueLogger.info(`Comments not made by actor or another bot: ${chalk_1.default.cyan(filteredComments.length)}`); // if there are any user comments returned return filteredComments.length > 0; }); @@ -594,7 +610,7 @@ class IssuesProcessor { var _a, _b, _c; return __awaiter(this, void 0, void 0, function* () { const issueLogger = new issue_logger_1.IssueLogger(issue); - issueLogger.info(`Marking $$type as stale`); + issueLogger.info(`Marking this $$type as stale`); this.staleIssues.push(issue); // if the issue is being marked stale, the updated date should be changed to right now // so that close calculations work correctly @@ -719,7 +735,7 @@ class IssuesProcessor { issueLogger.info(`Delete branch from closed $$type - ${issue.title}`); const pullRequest = yield this._getPullRequest(issue); if (!pullRequest) { - issueLogger.info(`Not deleting branch as pull request not found for this $$type`); + issueLogger.info(`Not deleting this branch as no pull request was found for this $$type`); return; } if (this.options.debugOnly) { @@ -746,7 +762,7 @@ class IssuesProcessor { var _a; return __awaiter(this, void 0, void 0, function* () { const issueLogger = new issue_logger_1.IssueLogger(issue); - issueLogger.info(`Removing the label "${chalk_1.default.cyan(label)}" from the $$type...`); + issueLogger.info(`Removing the label "${chalk_1.default.cyan(label)}" from this $$type...`); this.removedLabelIssues.push(issue); if (this.options.debugOnly) { return; @@ -854,6 +870,21 @@ class IssuesProcessor { this._operations.consumeOperation(); issue.operations.consumeOperation(); } + _getDaysBeforeStaleUsedOptionName(issue) { + return issue.isPullRequest + ? this._getDaysBeforePrStaleUsedOptionName() + : this._getDaysBeforeIssueStaleUsedOptionName(); + } + _getDaysBeforeIssueStaleUsedOptionName() { + return isNaN(this.options.daysBeforeIssueStale) + ? option_1.Option.DaysBeforeStale + : option_1.Option.DaysBeforeIssueStale; + } + _getDaysBeforePrStaleUsedOptionName() { + return isNaN(this.options.daysBeforePrStale) + ? option_1.Option.DaysBeforeStale + : option_1.Option.DaysBeforePrStale; + } } exports.IssuesProcessor = IssuesProcessor; @@ -1018,7 +1049,7 @@ class Milestones { return false; } if (this._shouldExemptAllMilestones()) { - this._issueLogger.info(chalk_1.default.white('└──'), 'Skipping $$type because it has a milestone'); + this._issueLogger.info(chalk_1.default.white('└──'), 'Skipping this $$type because it has a milestone'); return true; } const exemptMilestones = this._getExemptMilestones(); diff --git a/src/classes/assignees.ts b/src/classes/assignees.ts index ce9cb11b9..9a0a2a259 100644 --- a/src/classes/assignees.ts +++ b/src/classes/assignees.ts @@ -35,7 +35,7 @@ export class Assignees { if (this._shouldExemptAllAssignees()) { this._issueLogger.info( chalk.white('└──'), - 'Skipping $$type because it has an exempt assignee' + 'Skipping this $$type because it has an exempt assignee' ); return true; diff --git a/src/classes/issues-processor.ts b/src/classes/issues-processor.ts index 108034248..13c241938 100644 --- a/src/classes/issues-processor.ts +++ b/src/classes/issues-processor.ts @@ -51,6 +51,14 @@ export class IssuesProcessor { } } + private static _getStaleMessageUsedOptionName( + issue: Readonly + ): Option.StalePrMessage | Option.StaleIssueMessage { + return issue.isPullRequest + ? Option.StalePrMessage + : Option.StaleIssueMessage; + } + private readonly _logger: Logger = new Logger(); private readonly _operations: StaleOperations; private readonly _statistics: Statistics | undefined; @@ -112,7 +120,9 @@ export class IssuesProcessor { const issueLogger: IssueLogger = new IssueLogger(issue); this._statistics?.incrementProcessedItemsCount(issue); - issueLogger.info(`Found this $$type last updated ${issue.updated_at}`); + issueLogger.info( + `Found this $$type last updated at: ${chalk.cyan(issue.updated_at)}` + ); // calculate string based messages for this issue const staleMessage: string = issue.isPullRequest @@ -137,7 +147,11 @@ export class IssuesProcessor { if (onlyLabels.length > 0) { issueLogger.info( - `The option "onlyLabels" was specified to only processed the issues and pull requests with all those labels (${onlyLabels.length})` + `The option ${issueLogger.createOptionLink( + Option.OnlyLabels + )} was specified to only processed issues and pull requests with all those labels (${chalk.cyan( + onlyLabels.length + )})` ); const hasAllWhitelistedLabels: boolean = onlyLabels.every( @@ -165,31 +179,45 @@ export class IssuesProcessor { ); } } else { - issueLogger.info(`The option "onlyLabels" was not specified`); + issueLogger.info( + `The option ${issueLogger.createOptionLink( + Option.OnlyLabels + )} was not specified` + ); issueLogger.info( chalk.white('└──'), `Continuing the process for this $$type` ); } - issueLogger.info(`Days before $$type stale: ${daysBeforeStale}`); + issueLogger.info( + `Days before $$type stale: ${chalk.cyan(daysBeforeStale)}` + ); const shouldMarkAsStale: boolean = shouldMarkWhenStale(daysBeforeStale); if (!staleMessage && shouldMarkAsStale) { - issueLogger.info(`Skipping $$type due to empty stale message`); + issueLogger.info( + `Skipping this $$type because it should be marked as stale based on the option ${issueLogger.createOptionLink( + this._getDaysBeforeStaleUsedOptionName(issue) + )} (${chalk.cyan( + daysBeforeStale + )}) but the option ${issueLogger.createOptionLink( + IssuesProcessor._getStaleMessageUsedOptionName(issue) + )} is not set` + ); IssuesProcessor._endIssueProcessing(issue); continue; } if (issue.state === 'closed') { - issueLogger.info(`Skipping $$type because it is closed`); + issueLogger.info(`Skipping this $$type because it is closed`); IssuesProcessor._endIssueProcessing(issue); continue; // Don't process closed issues } if (issue.locked) { - issueLogger.info(`Skipping $$type because it is locked`); + issueLogger.info(`Skipping this $$type because it is locked`); IssuesProcessor._endIssueProcessing(issue); continue; // Don't process locked issues } @@ -202,9 +230,9 @@ export class IssuesProcessor { const createdAt: Date = new Date(issue.created_at); issueLogger.info( - `A start date was specified for the ${getHumanizedDate(startDate)} (${ - this.options.startDate - })` + `A start date was specified for the ${getHumanizedDate( + startDate + )} (${chalk.cyan(this.options.startDate)})` ); // Expecting that GitHub will always set a creation date on the issues and PRs @@ -219,14 +247,14 @@ export class IssuesProcessor { } issueLogger.info( - `$$type created the ${getHumanizedDate(createdAt)} (${ + `$$type created the ${getHumanizedDate(createdAt)} (${chalk.cyan( issue.created_at - })` + )})` ); if (!isDateMoreRecentThan(createdAt, startDate)) { issueLogger.info( - `Skipping $$type because it was created before the specified start date` + `Skipping this $$type because it was created before the specified start date` ); IssuesProcessor._endIssueProcessing(issue); @@ -256,7 +284,7 @@ export class IssuesProcessor { await this._removeStaleLabel(issue, staleLabel); } - issueLogger.info(`Skipping $$type because it has an exempt label`); + issueLogger.info(`Skipping this $$type because it has an exempt label`); IssuesProcessor._endIssueProcessing(issue); continue; // Don't process exempt issues } @@ -265,7 +293,11 @@ export class IssuesProcessor { if (anyOfLabels.length > 0) { issueLogger.info( - `The option "anyOfLabels" was specified to only processed the issues and pull requests with one of those labels (${anyOfLabels.length})` + `The option ${issueLogger.createOptionLink( + Option.AnyOfLabels + )} was specified to only processed the issues and pull requests with one of those labels (${chalk.cyan( + anyOfLabels.length + )})` ); const hasOneOfWhitelistedLabels: boolean = anyOfLabels.some( @@ -292,7 +324,11 @@ export class IssuesProcessor { ); } } else { - issueLogger.info(`The option "anyOfLabels" was not specified`); + issueLogger.info( + `The option ${issueLogger.createOptionLink( + Option.AnyOfLabels + )} was not specified` + ); issueLogger.info( chalk.white('└──'), `Continuing the process for this $$type` @@ -320,21 +356,45 @@ export class IssuesProcessor { ); // Determine if this issue needs to be marked stale first - if (!issue.isStale && shouldBeStale && shouldMarkAsStale) { - issueLogger.info( - `Marking $$type stale because it was last updated on ${issue.updated_at} and it does not have a stale label` - ); - await this._markStale(issue, staleMessage, staleLabel, skipMessage); - issue.isStale = true; // This issue is now considered stale - } else if (!issue.isStale) { - issueLogger.info( - `Not marking as stale: shouldBeStale=${shouldBeStale}, shouldMarkAsStale=${shouldMarkAsStale}` - ); + if (!issue.isStale) { + issueLogger.info(`This $$type is not stale`); + const updatedAtDate: Date = new Date(issue.updated_at); + + if (shouldBeStale) { + issueLogger.info( + `This $$type should be stale based on the last update date the ${getHumanizedDate( + updatedAtDate + )} (${chalk.cyan(issue.updated_at)})` + ); + + if (shouldMarkAsStale) { + issueLogger.info( + `This $$type should be marked as stale based on the option ${issueLogger.createOptionLink( + this._getDaysBeforeStaleUsedOptionName(issue) + )} (${chalk.cyan(daysBeforeStale)})` + ); + await this._markStale(issue, staleMessage, staleLabel, skipMessage); + issue.isStale = true; // This issue is now considered stale + issueLogger.info(`This $$type is now stale`); + } else { + issueLogger.info( + `This $$type should not be marked as stale based on the option ${issueLogger.createOptionLink( + this._getDaysBeforeStaleUsedOptionName(issue) + )} (${chalk.cyan(daysBeforeStale)})` + ); + } + } else { + issueLogger.info( + `This $$type should not be stale based on the last update date the ${getHumanizedDate( + updatedAtDate + )} (${chalk.cyan(issue.updated_at)})` + ); + } } // Process the issue if it was marked stale if (issue.isStale) { - issueLogger.info(`Found a stale $$type`); + issueLogger.info(`This $$type is already stale`); await this._processStaleIssue( issue, staleLabel, @@ -445,7 +505,7 @@ export class IssuesProcessor { ): Promise { const issueLogger: IssueLogger = new IssueLogger(issue); - issueLogger.info(`Checking for label on $$type`); + issueLogger.info(`Checking for label on this $$type`); this._consumeIssueOperation(issue); this._statistics?.incrementFetchedItemsEventsCount(); @@ -497,7 +557,9 @@ export class IssuesProcessor { ? this._getDaysBeforePrClose() : this._getDaysBeforeIssueClose(); - issueLogger.info(`Days before $$type close: ${daysBeforeClose}`); + issueLogger.info( + `Days before $$type close: ${chalk.cyan(daysBeforeClose)}` + ); const issueHasUpdate: boolean = IssuesProcessor._updatedSince( issue.updated_at, @@ -521,13 +583,17 @@ export class IssuesProcessor { if (!issueHasComments && !issueHasUpdate) { issueLogger.info( - `Closing $$type because it was last updated on ${issue.updated_at}` + `Closing $$type because it was last updated on! ${chalk.cyan( + issue.updated_at + )}` ); await this._closeIssue(issue, closeMessage, closeLabel); if (this.options.deleteBranch && issue.pull_request) { issueLogger.info( - `Deleting branch for as delete-branch option was specified` + `Deleting the branch the option ${issueLogger.createOptionLink( + Option.DeleteBranch + )} was specified` ); await this._deleteBranch(issue); this.deletedBranchIssues.push(issue); @@ -547,7 +613,9 @@ export class IssuesProcessor { ): Promise { const issueLogger: IssueLogger = new IssueLogger(issue); - issueLogger.info(`Checking for comments on $$type since ${sinceDate}`); + issueLogger.info( + `Checking for comments on $$type since: ${chalk.cyan(sinceDate)}` + ); if (!sinceDate) { return true; @@ -561,7 +629,9 @@ export class IssuesProcessor { ); issueLogger.info( - `Comments not made by actor or another bot: ${filteredComments.length}` + `Comments not made by actor or another bot: ${chalk.cyan( + filteredComments.length + )}` ); // if there are any user comments returned @@ -577,7 +647,7 @@ export class IssuesProcessor { ): Promise { const issueLogger: IssueLogger = new IssueLogger(issue); - issueLogger.info(`Marking $$type as stale`); + issueLogger.info(`Marking this $$type as stale`); this.staleIssues.push(issue); // if the issue is being marked stale, the updated date should be changed to right now @@ -712,7 +782,7 @@ export class IssuesProcessor { if (!pullRequest) { issueLogger.info( - `Not deleting branch as pull request not found for this $$type` + `Not deleting this branch as no pull request was found for this $$type` ); return; } @@ -748,7 +818,7 @@ export class IssuesProcessor { const issueLogger: IssueLogger = new IssueLogger(issue); issueLogger.info( - `Removing the label "${chalk.cyan(label)}" from the $$type...` + `Removing the label "${chalk.cyan(label)}" from this $$type...` ); this.removedLabelIssues.push(issue); @@ -887,4 +957,31 @@ export class IssuesProcessor { this._operations.consumeOperation(); issue.operations.consumeOperation(); } + + private _getDaysBeforeStaleUsedOptionName( + issue: Readonly + ): + | Option.DaysBeforeStale + | Option.DaysBeforeIssueStale + | Option.DaysBeforePrStale { + return issue.isPullRequest + ? this._getDaysBeforePrStaleUsedOptionName() + : this._getDaysBeforeIssueStaleUsedOptionName(); + } + + private _getDaysBeforeIssueStaleUsedOptionName(): + | Option.DaysBeforeStale + | Option.DaysBeforeIssueStale { + return isNaN(this.options.daysBeforeIssueStale) + ? Option.DaysBeforeStale + : Option.DaysBeforeIssueStale; + } + + private _getDaysBeforePrStaleUsedOptionName(): + | Option.DaysBeforeStale + | Option.DaysBeforePrStale { + return isNaN(this.options.daysBeforePrStale) + ? Option.DaysBeforeStale + : Option.DaysBeforePrStale; + } } diff --git a/src/classes/milestones.ts b/src/classes/milestones.ts index 7f71b41a7..dd3fa355d 100644 --- a/src/classes/milestones.ts +++ b/src/classes/milestones.ts @@ -34,7 +34,7 @@ export class Milestones { if (this._shouldExemptAllMilestones()) { this._issueLogger.info( chalk.white('└──'), - 'Skipping $$type because it has a milestone' + 'Skipping this $$type because it has a milestone' ); return true; From 342f6b29c4a89236625323758acd97def3bb0205 Mon Sep 17 00:00:00 2001 From: Geoffrey Testelin Date: Thu, 6 May 2021 09:59:40 +0200 Subject: [PATCH 3/3] style(logs): fix typos --- dist/index.js | 4 ++-- src/classes/issues-processor.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dist/index.js b/dist/index.js index 93b103875..aa30bcc05 100644 --- a/dist/index.js +++ b/dist/index.js @@ -324,7 +324,7 @@ class IssuesProcessor { : this._getDaysBeforeIssueStale(); const onlyLabels = words_to_list_1.wordsToList(this._getOnlyLabels(issue)); if (onlyLabels.length > 0) { - issueLogger.info(`The option ${issueLogger.createOptionLink(option_1.Option.OnlyLabels)} was specified to only processed issues and pull requests with all those labels (${chalk_1.default.cyan(onlyLabels.length)})`); + issueLogger.info(`The option ${issueLogger.createOptionLink(option_1.Option.OnlyLabels)} was specified to only process issues and pull requests with all those labels (${chalk_1.default.cyan(onlyLabels.length)})`); const hasAllWhitelistedLabels = onlyLabels.every((label) => { return is_labeled_1.isLabeled(issue, label); }); @@ -398,7 +398,7 @@ class IssuesProcessor { } const anyOfLabels = words_to_list_1.wordsToList(this._getAnyOfLabels(issue)); if (anyOfLabels.length > 0) { - issueLogger.info(`The option ${issueLogger.createOptionLink(option_1.Option.AnyOfLabels)} was specified to only processed the issues and pull requests with one of those labels (${chalk_1.default.cyan(anyOfLabels.length)})`); + issueLogger.info(`The option ${issueLogger.createOptionLink(option_1.Option.AnyOfLabels)} was specified to only process the issues and pull requests with one of those labels (${chalk_1.default.cyan(anyOfLabels.length)})`); const hasOneOfWhitelistedLabels = anyOfLabels.some((label) => { return is_labeled_1.isLabeled(issue, label); }); diff --git a/src/classes/issues-processor.ts b/src/classes/issues-processor.ts index 13c241938..fac5778fd 100644 --- a/src/classes/issues-processor.ts +++ b/src/classes/issues-processor.ts @@ -149,7 +149,7 @@ export class IssuesProcessor { issueLogger.info( `The option ${issueLogger.createOptionLink( Option.OnlyLabels - )} was specified to only processed issues and pull requests with all those labels (${chalk.cyan( + )} was specified to only process issues and pull requests with all those labels (${chalk.cyan( onlyLabels.length )})` ); @@ -295,7 +295,7 @@ export class IssuesProcessor { issueLogger.info( `The option ${issueLogger.createOptionLink( Option.AnyOfLabels - )} was specified to only processed the issues and pull requests with one of those labels (${chalk.cyan( + )} was specified to only process the issues and pull requests with one of those labels (${chalk.cyan( anyOfLabels.length )})` );