fix(logs): coloured logs (#465)

* refactor(logs): replace chalk by ansi-styles

* test(logs): fix the failing tests due to ansi styles

I was not able to disable or mock ansi-styles so instead I found a way to make the tests pass
it's not perfect but it's still nice because the logs will keep their trustful colour when running through the tests

* refactor(logs): simplify the syntax to colour the logs

* chore(rebase): update files due to rebase

* refactor(logger): reduce code duplication
This commit is contained in:
Geoffrey Testelin 2021-06-02 23:04:34 +02:00 committed by GitHub
parent e884599072
commit 5fbbfba142
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 671 additions and 2262 deletions

View File

@ -28,7 +28,7 @@
"@typescript-eslint/no-array-constructor": "error", "@typescript-eslint/no-array-constructor": "error",
"@typescript-eslint/no-empty-interface": "error", "@typescript-eslint/no-empty-interface": "error",
"@typescript-eslint/no-explicit-any": "off", "@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-extraneous-class": "error", "@typescript-eslint/no-extraneous-class": "off",
"@typescript-eslint/no-for-in-array": "error", "@typescript-eslint/no-for-in-array": "error",
"@typescript-eslint/no-inferrable-types": "error", "@typescript-eslint/no-inferrable-types": "error",
"@typescript-eslint/no-misused-new": "error", "@typescript-eslint/no-misused-new": "error",

2453
dist/index.js vendored

File diff suppressed because it is too large Load Diff

View File

@ -7,6 +7,5 @@ module.exports = {
transform: { transform: {
'^.+\\.ts$': 'ts-jest' '^.+\\.ts$': 'ts-jest'
}, },
verbose: true, verbose: true
setupFilesAfterEnv: [`./jest/test.ts`]
}; };

View File

@ -1,11 +0,0 @@
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;

99
package-lock.json generated
View File

@ -217,6 +217,17 @@
"ansi-styles": "^3.2.1", "ansi-styles": "^3.2.1",
"escape-string-regexp": "^1.0.5", "escape-string-regexp": "^1.0.5",
"supports-color": "^5.3.0" "supports-color": "^5.3.0"
},
"dependencies": {
"ansi-styles": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
"dev": true,
"requires": {
"color-convert": "^1.9.0"
}
}
} }
} }
} }
@ -2081,13 +2092,10 @@
"dev": true "dev": true
}, },
"ansi-styles": { "ansi-styles": {
"version": "3.2.1", "version": "5.2.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
"dev": true, "dev": true
"requires": {
"color-convert": "^1.9.0"
}
}, },
"anymatch": { "anymatch": {
"version": "2.0.0", "version": "2.0.0",
@ -2556,57 +2564,6 @@
"integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=",
"dev": true "dev": true
}, },
"chalk": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
"integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
"dev": true,
"requires": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
},
"dependencies": {
"ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
"requires": {
"color-convert": "^2.0.1"
}
},
"color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"requires": {
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true
},
"supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
"requires": {
"has-flag": "^4.0.0"
}
}
}
},
"char-regex": { "char-regex": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz",
@ -3167,7 +3124,33 @@
"ansi-styles": "^3.2.1", "ansi-styles": "^3.2.1",
"escape-string-regexp": "^1.0.5", "escape-string-regexp": "^1.0.5",
"supports-color": "^5.3.0" "supports-color": "^5.3.0"
},
"dependencies": {
"ansi-styles": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
"dev": true,
"requires": {
"color-convert": "^1.9.0"
}
}
} }
},
"color-convert": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
"dev": true,
"requires": {
"color-name": "1.1.3"
}
},
"color-name": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
"dev": true
} }
} }
}, },

View File

@ -43,7 +43,7 @@
"@typescript-eslint/eslint-plugin": "^4.16.1", "@typescript-eslint/eslint-plugin": "^4.16.1",
"@typescript-eslint/parser": "^4.22.1", "@typescript-eslint/parser": "^4.22.1",
"@vercel/ncc": "^0.27.0", "@vercel/ncc": "^0.27.0",
"chalk": "^4.1.0", "ansi-styles": "5.2.0",
"eslint": "^7.21.0", "eslint": "^7.21.0",
"eslint-plugin-github": "^4.1.2", "eslint-plugin-github": "^4.1.2",
"eslint-plugin-jest": "^24.3.6", "eslint-plugin-jest": "^24.3.6",

View File

@ -1,4 +1,3 @@
import chalk from 'chalk';
import deburr from 'lodash.deburr'; import deburr from 'lodash.deburr';
import {Option} from '../enums/option'; import {Option} from '../enums/option';
import {wordsToList} from '../functions/words-to-list'; import {wordsToList} from '../functions/words-to-list';
@ -6,6 +5,7 @@ import {IAssignee} from '../interfaces/assignee';
import {IIssuesProcessorOptions} from '../interfaces/issues-processor-options'; import {IIssuesProcessorOptions} from '../interfaces/issues-processor-options';
import {Issue} from './issue'; import {Issue} from './issue';
import {IssueLogger} from './loggers/issue-logger'; import {IssueLogger} from './loggers/issue-logger';
import {LoggerService} from '../services/logger.service';
type CleanAssignee = string; type CleanAssignee = string;
@ -34,7 +34,7 @@ export class Assignees {
if (this._shouldExemptAllAssignees()) { if (this._shouldExemptAllAssignees()) {
this._issueLogger.info( this._issueLogger.info(
chalk.white('└──'), LoggerService.white('└──'),
'Skipping this $$type because it has an exempt assignee' 'Skipping this $$type because it has an exempt assignee'
); );
@ -45,7 +45,7 @@ export class Assignees {
if (exemptAssignees.length === 0) { if (exemptAssignees.length === 0) {
this._issueLogger.info( this._issueLogger.info(
chalk.white('├──'), LoggerService.white('├──'),
`No assignee option was specified to skip the stale process for this $$type` `No assignee option was specified to skip the stale process for this $$type`
); );
this._logSkip(); this._logSkip();
@ -54,8 +54,8 @@ export class Assignees {
} }
this._issueLogger.info( this._issueLogger.info(
chalk.white('├──'), LoggerService.white('├──'),
`Found ${chalk.cyan(exemptAssignees.length)} assignee${ `Found ${LoggerService.cyan(exemptAssignees.length)} assignee${
exemptAssignees.length > 1 ? 's' : '' exemptAssignees.length > 1 ? 's' : ''
} that can exempt stale on this $$type` } that can exempt stale on this $$type`
); );
@ -67,13 +67,13 @@ export class Assignees {
if (!hasExemptAssignee) { if (!hasExemptAssignee) {
this._issueLogger.info( this._issueLogger.info(
chalk.white('├──'), LoggerService.white('├──'),
'No assignee on this $$type can exempt the stale process' 'No assignee on this $$type can exempt the stale process'
); );
this._logSkip(); this._logSkip();
} else { } else {
this._issueLogger.info( this._issueLogger.info(
chalk.white('└──'), LoggerService.white('└──'),
'Skipping this $$type because it has an exempt assignee' 'Skipping this $$type because it has an exempt assignee'
); );
} }
@ -90,7 +90,7 @@ export class Assignees {
private _getExemptIssueAssignees(): string[] { private _getExemptIssueAssignees(): string[] {
if (this._options.exemptIssueAssignees === '') { if (this._options.exemptIssueAssignees === '') {
this._issueLogger.info( this._issueLogger.info(
chalk.white('├──'), LoggerService.white('├──'),
`The option ${this._issueLogger.createOptionLink( `The option ${this._issueLogger.createOptionLink(
Option.ExemptIssueAssignees Option.ExemptIssueAssignees
)} is disabled. No specific assignee can skip the stale process for this $$type` )} is disabled. No specific assignee can skip the stale process for this $$type`
@ -98,7 +98,7 @@ export class Assignees {
if (this._options.exemptAssignees === '') { if (this._options.exemptAssignees === '') {
this._issueLogger.info( this._issueLogger.info(
chalk.white('├──'), LoggerService.white('├──'),
`The option ${this._issueLogger.createOptionLink( `The option ${this._issueLogger.createOptionLink(
Option.ExemptAssignees Option.ExemptAssignees
)} is disabled. No specific assignee can skip the stale process for this $$type` )} is disabled. No specific assignee can skip the stale process for this $$type`
@ -112,10 +112,10 @@ export class Assignees {
); );
this._issueLogger.info( this._issueLogger.info(
chalk.white('├──'), LoggerService.white('├──'),
`The option ${this._issueLogger.createOptionLink( `The option ${this._issueLogger.createOptionLink(
Option.ExemptAssignees Option.ExemptAssignees
)} is set. ${chalk.cyan(exemptAssignees.length)} assignee${ )} is set. ${LoggerService.cyan(exemptAssignees.length)} assignee${
exemptAssignees.length === 1 ? '' : 's' exemptAssignees.length === 1 ? '' : 's'
} can skip the stale process for this $$type` } can skip the stale process for this $$type`
); );
@ -128,10 +128,10 @@ export class Assignees {
); );
this._issueLogger.info( this._issueLogger.info(
chalk.white('├──'), LoggerService.white('├──'),
`The option ${this._issueLogger.createOptionLink( `The option ${this._issueLogger.createOptionLink(
Option.ExemptIssueAssignees Option.ExemptIssueAssignees
)} is set. ${chalk.cyan(exemptAssignees.length)} assignee${ )} is set. ${LoggerService.cyan(exemptAssignees.length)} assignee${
exemptAssignees.length === 1 ? '' : 's' exemptAssignees.length === 1 ? '' : 's'
} can skip the stale process for this $$type` } can skip the stale process for this $$type`
); );
@ -142,7 +142,7 @@ export class Assignees {
private _getExemptPullRequestAssignees(): string[] { private _getExemptPullRequestAssignees(): string[] {
if (this._options.exemptPrAssignees === '') { if (this._options.exemptPrAssignees === '') {
this._issueLogger.info( this._issueLogger.info(
chalk.white('├──'), LoggerService.white('├──'),
`The option ${this._issueLogger.createOptionLink( `The option ${this._issueLogger.createOptionLink(
Option.ExemptPrAssignees Option.ExemptPrAssignees
)} is disabled. No specific assignee can skip the stale process for this $$type` )} is disabled. No specific assignee can skip the stale process for this $$type`
@ -150,7 +150,7 @@ export class Assignees {
if (this._options.exemptAssignees === '') { if (this._options.exemptAssignees === '') {
this._issueLogger.info( this._issueLogger.info(
chalk.white('├──'), LoggerService.white('├──'),
`The option ${this._issueLogger.createOptionLink( `The option ${this._issueLogger.createOptionLink(
Option.ExemptAssignees Option.ExemptAssignees
)} is disabled. No specific assignee can skip the stale process for this $$type` )} is disabled. No specific assignee can skip the stale process for this $$type`
@ -164,10 +164,10 @@ export class Assignees {
); );
this._issueLogger.info( this._issueLogger.info(
chalk.white('├──'), LoggerService.white('├──'),
`The option ${this._issueLogger.createOptionLink( `The option ${this._issueLogger.createOptionLink(
Option.ExemptAssignees Option.ExemptAssignees
)} is set. ${chalk.cyan(exemptAssignees.length)} assignee${ )} is set. ${LoggerService.cyan(exemptAssignees.length)} assignee${
exemptAssignees.length === 1 ? '' : 's' exemptAssignees.length === 1 ? '' : 's'
} can skip the stale process for this $$type` } can skip the stale process for this $$type`
); );
@ -180,10 +180,10 @@ export class Assignees {
); );
this._issueLogger.info( this._issueLogger.info(
chalk.white('├──'), LoggerService.white('├──'),
`The option ${this._issueLogger.createOptionLink( `The option ${this._issueLogger.createOptionLink(
Option.ExemptPrAssignees Option.ExemptPrAssignees
)} is set. ${chalk.cyan(exemptAssignees.length)} assignee${ )} is set. ${LoggerService.cyan(exemptAssignees.length)} assignee${
exemptAssignees.length === 1 ? '' : 's' exemptAssignees.length === 1 ? '' : 's'
} can skip the stale process for this $$type` } can skip the stale process for this $$type`
); );
@ -201,7 +201,7 @@ export class Assignees {
if (isSameAssignee) { if (isSameAssignee) {
this._issueLogger.info( this._issueLogger.info(
chalk.white('├──'), LoggerService.white('├──'),
`@${issueAssignee.login} is assigned on this $$type and is an exempt assignee` `@${issueAssignee.login} is assigned on this $$type and is an exempt assignee`
); );
} }
@ -282,6 +282,9 @@ export class Assignees {
} }
private _logSkip(): void { private _logSkip(): void {
this._issueLogger.info(chalk.white('└──'), 'Skip the assignees checks'); this._issueLogger.info(
LoggerService.white('└──'),
'Skip the assignees checks'
);
} }
} }

View File

@ -2,7 +2,6 @@ import * as core from '@actions/core';
import {context, getOctokit} from '@actions/github'; import {context, getOctokit} from '@actions/github';
import {GitHub} from '@actions/github/lib/utils'; import {GitHub} from '@actions/github/lib/utils';
import {GetResponseTypeFromEndpointMethod} from '@octokit/types'; import {GetResponseTypeFromEndpointMethod} from '@octokit/types';
import chalk from 'chalk';
import {Option} from '../enums/option'; import {Option} from '../enums/option';
import {getHumanizedDate} from '../functions/dates/get-humanized-date'; import {getHumanizedDate} from '../functions/dates/get-humanized-date';
import {isDateMoreRecentThan} from '../functions/dates/is-date-more-recent-than'; import {isDateMoreRecentThan} from '../functions/dates/is-date-more-recent-than';
@ -23,6 +22,7 @@ import {Logger} from './loggers/logger';
import {Milestones} from './milestones'; import {Milestones} from './milestones';
import {StaleOperations} from './stale-operations'; import {StaleOperations} from './stale-operations';
import {Statistics} from './statistics'; import {Statistics} from './statistics';
import {LoggerService} from '../services/logger.service';
/*** /***
* Handle processing of issues for staleness/closure. * Handle processing of issues for staleness/closure.
@ -43,7 +43,7 @@ export class IssuesProcessor {
const issueLogger: IssueLogger = new IssueLogger(issue); const issueLogger: IssueLogger = new IssueLogger(issue);
issueLogger.info( issueLogger.info(
chalk.cyan(consumedOperationsCount), LoggerService.cyan(consumedOperationsCount),
`operation${ `operation${
consumedOperationsCount > 1 ? 's' : '' consumedOperationsCount > 1 ? 's' : ''
} consumed for this $$type` } consumed for this $$type`
@ -74,13 +74,17 @@ export class IssuesProcessor {
this.client = getOctokit(this.options.repoToken); this.client = getOctokit(this.options.repoToken);
this._operations = new StaleOperations(this.options); this._operations = new StaleOperations(this.options);
this._logger.info(chalk.yellow('Starting the stale action process...')); this._logger.info(
LoggerService.yellow(`Starting the stale action process...`)
);
if (this.options.debugOnly) { if (this.options.debugOnly) {
this._logger.warning(chalk.yellowBright('Executing in debug mode!'));
this._logger.warning( this._logger.warning(
chalk.yellowBright( LoggerService.yellowBright(`Executing in debug mode!`)
'The debug output will be written but no issues/PRs will be processed.' );
this._logger.warning(
LoggerService.yellowBright(
`The debug output will be written but no issues/PRs will be processed.`
) )
); );
} }
@ -97,7 +101,7 @@ export class IssuesProcessor {
if (issues.length <= 0) { if (issues.length <= 0) {
this._logger.info( this._logger.info(
chalk.green('No more issues found to process. Exiting...') LoggerService.green(`No more issues found to process. Exiting...`)
); );
this._statistics this._statistics
?.setRemainingOperations(this._operations.getRemainingOperationsCount()) ?.setRemainingOperations(this._operations.getRemainingOperationsCount())
@ -106,13 +110,13 @@ export class IssuesProcessor {
return this._operations.getRemainingOperationsCount(); return this._operations.getRemainingOperationsCount();
} else { } else {
this._logger.info( this._logger.info(
chalk.yellow( `${LoggerService.yellow(
`Processing the batch of issues ${chalk.cyan( 'Processing the batch of issues'
`#${page}` )} ${LoggerService.cyan(`#${page}`)} ${LoggerService.yellow(
)} containing ${chalk.cyan(issues.length)} issue${ 'containing'
issues.length > 1 ? 's' : '' )} ${LoggerService.cyan(issues.length)} ${LoggerService.yellow(
}...` `issue${issues.length > 1 ? 's' : ''}...`
) )}`
); );
} }
@ -121,7 +125,9 @@ export class IssuesProcessor {
this._statistics?.incrementProcessedItemsCount(issue); this._statistics?.incrementProcessedItemsCount(issue);
issueLogger.info( issueLogger.info(
`Found this $$type last updated at: ${chalk.cyan(issue.updated_at)}` `Found this $$type last updated at: ${LoggerService.cyan(
issue.updated_at
)}`
); );
// calculate string based messages for this issue // calculate string based messages for this issue
@ -149,7 +155,7 @@ export class IssuesProcessor {
issueLogger.info( issueLogger.info(
`The option ${issueLogger.createOptionLink( `The option ${issueLogger.createOptionLink(
Option.OnlyLabels Option.OnlyLabels
)} was specified to only process issues and pull requests with all those labels (${chalk.cyan( )} was specified to only process issues and pull requests with all those labels (${LoggerService.cyan(
onlyLabels.length onlyLabels.length
)})` )})`
); );
@ -162,7 +168,7 @@ export class IssuesProcessor {
if (!hasAllWhitelistedLabels) { if (!hasAllWhitelistedLabels) {
issueLogger.info( issueLogger.info(
chalk.white('└──'), LoggerService.white('└──'),
`Skipping this $$type because it doesn't have all the required labels` `Skipping this $$type because it doesn't have all the required labels`
); );
@ -170,11 +176,11 @@ export class IssuesProcessor {
continue; // Don't process issues without all of the required labels continue; // Don't process issues without all of the required labels
} else { } else {
issueLogger.info( issueLogger.info(
chalk.white('├──'), LoggerService.white('├──'),
`All the required labels are present on this $$type` `All the required labels are present on this $$type`
); );
issueLogger.info( issueLogger.info(
chalk.white('└──'), LoggerService.white('└──'),
`Continuing the process for this $$type` `Continuing the process for this $$type`
); );
} }
@ -185,13 +191,13 @@ export class IssuesProcessor {
)} was not specified` )} was not specified`
); );
issueLogger.info( issueLogger.info(
chalk.white('└──'), LoggerService.white('└──'),
`Continuing the process for this $$type` `Continuing the process for this $$type`
); );
} }
issueLogger.info( issueLogger.info(
`Days before $$type stale: ${chalk.cyan(daysBeforeStale)}` `Days before $$type stale: ${LoggerService.cyan(daysBeforeStale)}`
); );
const shouldMarkAsStale: boolean = shouldMarkWhenStale(daysBeforeStale); const shouldMarkAsStale: boolean = shouldMarkWhenStale(daysBeforeStale);
@ -218,7 +224,7 @@ export class IssuesProcessor {
issueLogger.info( issueLogger.info(
`A start date was specified for the ${getHumanizedDate( `A start date was specified for the ${getHumanizedDate(
startDate startDate
)} (${chalk.cyan(this.options.startDate)})` )} (${LoggerService.cyan(this.options.startDate)})`
); );
// Expecting that GitHub will always set a creation date on the issues and PRs // Expecting that GitHub will always set a creation date on the issues and PRs
@ -233,9 +239,9 @@ export class IssuesProcessor {
} }
issueLogger.info( issueLogger.info(
`$$type created the ${getHumanizedDate(createdAt)} (${chalk.cyan( `$$type created the ${getHumanizedDate(
issue.created_at createdAt
)})` )} (${LoggerService.cyan(issue.created_at)})`
); );
if (!isDateMoreRecentThan(createdAt, startDate)) { if (!isDateMoreRecentThan(createdAt, startDate)) {
@ -281,7 +287,7 @@ export class IssuesProcessor {
issueLogger.info( issueLogger.info(
`The option ${issueLogger.createOptionLink( `The option ${issueLogger.createOptionLink(
Option.AnyOfLabels Option.AnyOfLabels
)} was specified to only process 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 (${LoggerService.cyan(
anyOfLabels.length anyOfLabels.length
)})` )})`
); );
@ -294,18 +300,18 @@ export class IssuesProcessor {
if (!hasOneOfWhitelistedLabels) { if (!hasOneOfWhitelistedLabels) {
issueLogger.info( issueLogger.info(
chalk.white('└──'), LoggerService.white('└──'),
`Skipping this $$type because it doesn't have one of the required labels` `Skipping this $$type because it doesn't have one of the required labels`
); );
IssuesProcessor._endIssueProcessing(issue); IssuesProcessor._endIssueProcessing(issue);
continue; // Don't process issues without any of the required labels continue; // Don't process issues without any of the required labels
} else { } else {
issueLogger.info( issueLogger.info(
chalk.white('├──'), LoggerService.white('├──'),
`One of the required labels is present on this $$type` `One of the required labels is present on this $$type`
); );
issueLogger.info( issueLogger.info(
chalk.white('└──'), LoggerService.white('└──'),
`Continuing the process for this $$type` `Continuing the process for this $$type`
); );
} }
@ -316,7 +322,7 @@ export class IssuesProcessor {
)} was not specified` )} was not specified`
); );
issueLogger.info( issueLogger.info(
chalk.white('└──'), LoggerService.white('└──'),
`Continuing the process for this $$type` `Continuing the process for this $$type`
); );
} }
@ -350,14 +356,14 @@ export class IssuesProcessor {
issueLogger.info( issueLogger.info(
`This $$type should be stale based on the last update date the ${getHumanizedDate( `This $$type should be stale based on the last update date the ${getHumanizedDate(
updatedAtDate updatedAtDate
)} (${chalk.cyan(issue.updated_at)})` )} (${LoggerService.cyan(issue.updated_at)})`
); );
if (shouldMarkAsStale) { if (shouldMarkAsStale) {
issueLogger.info( issueLogger.info(
`This $$type should be marked as stale based on the option ${issueLogger.createOptionLink( `This $$type should be marked as stale based on the option ${issueLogger.createOptionLink(
this._getDaysBeforeStaleUsedOptionName(issue) this._getDaysBeforeStaleUsedOptionName(issue)
)} (${chalk.cyan(daysBeforeStale)})` )} (${LoggerService.cyan(daysBeforeStale)})`
); );
await this._markStale(issue, staleMessage, staleLabel, skipMessage); 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
@ -366,14 +372,14 @@ export class IssuesProcessor {
issueLogger.info( issueLogger.info(
`This $$type should not be marked as stale based on the option ${issueLogger.createOptionLink( `This $$type should not be marked as stale based on the option ${issueLogger.createOptionLink(
this._getDaysBeforeStaleUsedOptionName(issue) this._getDaysBeforeStaleUsedOptionName(issue)
)} (${chalk.cyan(daysBeforeStale)})` )} (${LoggerService.cyan(daysBeforeStale)})`
); );
} }
} else { } else {
issueLogger.info( issueLogger.info(
`This $$type should not be stale based on the last update date the ${getHumanizedDate( `This $$type should not be stale based on the last update date the ${getHumanizedDate(
updatedAtDate updatedAtDate
)} (${chalk.cyan(issue.updated_at)})` )} (${LoggerService.cyan(issue.updated_at)})`
); );
} }
} }
@ -395,23 +401,25 @@ export class IssuesProcessor {
if (!this._operations.hasRemainingOperations()) { if (!this._operations.hasRemainingOperations()) {
this._logger.warning( this._logger.warning(
chalk.yellowBright('No more operations left! Exiting...') LoggerService.yellowBright(`No more operations left! Exiting...`)
); );
this._logger.warning( this._logger.warning(
chalk.yellowBright( `${LoggerService.yellowBright(
`If you think that not enough issues were processed you could try to increase the quantity related to the ${this._logger.createOptionLink( 'If you think that not enough issues were processed you could try to increase the quantity related to the'
Option.OperationsPerRun )} ${this._logger.createOptionLink(
)} option which is currently set to ${chalk.cyan( Option.OperationsPerRun
this.options.operationsPerRun )} ${LoggerService.yellowBright(
)}` 'option which is currently set to'
) )} ${LoggerService.cyan(this.options.operationsPerRun)}`
); );
return 0; return 0;
} }
this._logger.info( this._logger.info(
chalk.green(`Batch ${chalk.cyan(`#${page}`)} processed.`) `${LoggerService.green('Batch')} ${LoggerService.cyan(
`#${page}`
)} ${LoggerService.green('processed.')}`
); );
// Do the next batch // Do the next batch
@ -528,7 +536,9 @@ export class IssuesProcessor {
const issueLogger: IssueLogger = new IssueLogger(issue); const issueLogger: IssueLogger = new IssueLogger(issue);
const markedStaleOn: string = const markedStaleOn: string =
(await this.getLabelCreationDate(issue, staleLabel)) || issue.updated_at; (await this.getLabelCreationDate(issue, staleLabel)) || issue.updated_at;
issueLogger.info(`$$type marked stale on: ${chalk.cyan(markedStaleOn)}`); issueLogger.info(
`$$type marked stale on: ${LoggerService.cyan(markedStaleOn)}`
);
const issueHasComments: boolean = await this._hasCommentsSince( const issueHasComments: boolean = await this._hasCommentsSince(
issue, issue,
@ -536,7 +546,7 @@ export class IssuesProcessor {
actor actor
); );
issueLogger.info( issueLogger.info(
`$$type has been commented on: ${chalk.cyan(issueHasComments)}` `$$type has been commented on: ${LoggerService.cyan(issueHasComments)}`
); );
const daysBeforeClose: number = issue.isPullRequest const daysBeforeClose: number = issue.isPullRequest
@ -544,14 +554,16 @@ export class IssuesProcessor {
: this._getDaysBeforeIssueClose(); : this._getDaysBeforeIssueClose();
issueLogger.info( issueLogger.info(
`Days before $$type close: ${chalk.cyan(daysBeforeClose)}` `Days before $$type close: ${LoggerService.cyan(daysBeforeClose)}`
); );
const issueHasUpdate: boolean = IssuesProcessor._updatedSince( const issueHasUpdate: boolean = IssuesProcessor._updatedSince(
issue.updated_at, issue.updated_at,
daysBeforeClose daysBeforeClose
); );
issueLogger.info(`$$type has been updated: ${chalk.cyan(issueHasUpdate)}`); issueLogger.info(
`$$type has been updated: ${LoggerService.cyan(issueHasUpdate)}`
);
// should we un-stale this issue? // should we un-stale this issue?
if (this._shouldRemoveStaleWhenUpdated(issue) && issueHasComments) { if (this._shouldRemoveStaleWhenUpdated(issue) && issueHasComments) {
@ -569,7 +581,7 @@ export class IssuesProcessor {
if (!issueHasComments && !issueHasUpdate) { if (!issueHasComments && !issueHasUpdate) {
issueLogger.info( issueLogger.info(
`Closing $$type because it was last updated on! ${chalk.cyan( `Closing $$type because it was last updated on! ${LoggerService.cyan(
issue.updated_at issue.updated_at
)}` )}`
); );
@ -600,7 +612,7 @@ export class IssuesProcessor {
const issueLogger: IssueLogger = new IssueLogger(issue); const issueLogger: IssueLogger = new IssueLogger(issue);
issueLogger.info( issueLogger.info(
`Checking for comments on $$type since: ${chalk.cyan(sinceDate)}` `Checking for comments on $$type since: ${LoggerService.cyan(sinceDate)}`
); );
if (!sinceDate) { if (!sinceDate) {
@ -615,7 +627,7 @@ export class IssuesProcessor {
); );
issueLogger.info( issueLogger.info(
`Comments not made by actor or another bot: ${chalk.cyan( `Comments not made by actor or another bot: ${LoggerService.cyan(
filteredComments.length filteredComments.length
)}` )}`
); );
@ -779,7 +791,7 @@ export class IssuesProcessor {
const branch = pullRequest.head.ref; const branch = pullRequest.head.ref;
issueLogger.info( issueLogger.info(
`Deleting the branch "${chalk.cyan(branch)}" from closed $$type` `Deleting the branch "${LoggerService.cyan(branch)}" from closed $$type`
); );
try { try {
@ -792,9 +804,9 @@ export class IssuesProcessor {
}); });
} catch (error) { } catch (error) {
issueLogger.error( issueLogger.error(
`Error when deleting the branch "${chalk.cyan(branch)}" from $$type: ${ `Error when deleting the branch "${LoggerService.cyan(
error.message branch
}` )}" from $$type: ${error.message}`
); );
} }
} }
@ -804,7 +816,7 @@ export class IssuesProcessor {
const issueLogger: IssueLogger = new IssueLogger(issue); const issueLogger: IssueLogger = new IssueLogger(issue);
issueLogger.info( issueLogger.info(
`Removing the label "${chalk.cyan(label)}" from this $$type...` `Removing the label "${LoggerService.cyan(label)}" from this $$type...`
); );
this.removedLabelIssues.push(issue); this.removedLabelIssues.push(issue);
@ -821,10 +833,10 @@ export class IssuesProcessor {
issue_number: issue.number, issue_number: issue.number,
name: label name: label
}); });
issueLogger.info(`The label "${chalk.cyan(label)}" was removed`); issueLogger.info(`The label "${LoggerService.cyan(label)}" was removed`);
} catch (error) { } catch (error) {
issueLogger.error( issueLogger.error(
`Error when removing the label: "${chalk.cyan(error.message)}"` `Error when removing the label: "${LoggerService.cyan(error.message)}"`
); );
} }
} }
@ -929,7 +941,7 @@ export class IssuesProcessor {
if (isLabeled(issue, closeLabel)) { if (isLabeled(issue, closeLabel)) {
issueLogger.info( issueLogger.info(
`The $$type has a close label "${chalk.cyan( `The $$type has a close label "${LoggerService.cyan(
closeLabel closeLabel
)}". Removing the close label...` )}". Removing the close label...`
); );

View File

@ -26,12 +26,17 @@ describe('IssueLogger', (): void => {
}); });
it('should log a warning with the given message and with the issue number as prefix', (): void => { it('should log a warning with the given message and with the issue number as prefix', (): void => {
expect.assertions(2); expect.assertions(3);
issueLogger.warning(message); issueLogger.warning(message);
expect(coreWarningSpy).toHaveBeenCalledTimes(1); expect(coreWarningSpy).toHaveBeenCalledTimes(1);
expect(coreWarningSpy).toHaveBeenCalledWith('[#8] dummy-message'); expect(coreWarningSpy).toHaveBeenCalledWith(
expect.stringContaining('[#8]')
);
expect(coreWarningSpy).toHaveBeenCalledWith(
expect.stringContaining('dummy-message')
);
}); });
}); });
@ -52,12 +57,15 @@ describe('IssueLogger', (): void => {
}); });
it('should log an information with the given message and with the issue number as prefix', (): void => { it('should log an information with the given message and with the issue number as prefix', (): void => {
expect.assertions(2); expect.assertions(3);
issueLogger.info(message); issueLogger.info(message);
expect(coreInfoSpy).toHaveBeenCalledTimes(1); expect(coreInfoSpy).toHaveBeenCalledTimes(1);
expect(coreInfoSpy).toHaveBeenCalledWith('[#8] dummy-message'); expect(coreInfoSpy).toHaveBeenCalledWith(expect.stringContaining('[#8]'));
expect(coreInfoSpy).toHaveBeenCalledWith(
expect.stringContaining('dummy-message')
);
}); });
}); });
@ -78,17 +86,22 @@ describe('IssueLogger', (): void => {
}); });
it('should log an error with the given message and with the issue number as prefix', (): void => { it('should log an error with the given message and with the issue number as prefix', (): void => {
expect.assertions(2); expect.assertions(3);
issueLogger.error(message); issueLogger.error(message);
expect(coreErrorSpy).toHaveBeenCalledTimes(1); expect(coreErrorSpy).toHaveBeenCalledTimes(1);
expect(coreErrorSpy).toHaveBeenCalledWith('[#8] dummy-message'); expect(coreErrorSpy).toHaveBeenCalledWith(
expect.stringContaining('[#8]')
);
expect(coreErrorSpy).toHaveBeenCalledWith(
expect.stringContaining('dummy-message')
);
}); });
}); });
it('should prefix the message with the issue number', (): void => { it('should prefix the message with the issue number', (): void => {
expect.assertions(2); expect.assertions(3);
message = 'dummy-message'; message = 'dummy-message';
issue = new Issue( issue = new Issue(
DefaultProcessorOptions, DefaultProcessorOptions,
@ -102,7 +115,12 @@ describe('IssueLogger', (): void => {
issueLogger.warning(message); issueLogger.warning(message);
expect(coreWarningSpy).toHaveBeenCalledTimes(1); expect(coreWarningSpy).toHaveBeenCalledTimes(1);
expect(coreWarningSpy).toHaveBeenCalledWith('[#123] dummy-message'); expect(coreWarningSpy).toHaveBeenCalledWith(
expect.stringContaining('[#123]')
);
expect(coreWarningSpy).toHaveBeenCalledWith(
expect.stringContaining('dummy-message')
);
}); });
it.each` it.each`
@ -114,7 +132,7 @@ describe('IssueLogger', (): void => {
`( `(
'should replace the special tokens "$$type" with the corresponding type', 'should replace the special tokens "$$type" with the corresponding type',
({pull_request, replacement}): void => { ({pull_request, replacement}): void => {
expect.assertions(2); expect.assertions(3);
message = 'The $$type will stale! $$type will soon be closed!'; message = 'The $$type will stale! $$type will soon be closed!';
issue = new Issue( issue = new Issue(
DefaultProcessorOptions, DefaultProcessorOptions,
@ -130,7 +148,12 @@ describe('IssueLogger', (): void => {
expect(coreWarningSpy).toHaveBeenCalledTimes(1); expect(coreWarningSpy).toHaveBeenCalledTimes(1);
expect(coreWarningSpy).toHaveBeenCalledWith( expect(coreWarningSpy).toHaveBeenCalledWith(
`[#8] The ${replacement} will stale! ${replacement} will soon be closed!` expect.stringContaining(`[#8]`)
);
expect(coreWarningSpy).toHaveBeenCalledWith(
expect.stringContaining(
`The ${replacement} will stale! ${replacement} will soon be closed!`
)
); );
} }
); );
@ -144,7 +167,7 @@ describe('IssueLogger', (): void => {
`( `(
'should replace the special token "$$type" with the corresponding type with first letter as uppercase', 'should replace the special token "$$type" with the corresponding type with first letter as uppercase',
({pull_request, replacement}): void => { ({pull_request, replacement}): void => {
expect.assertions(2); expect.assertions(3);
message = '$$type will stale'; message = '$$type will stale';
issue = new Issue( issue = new Issue(
DefaultProcessorOptions, DefaultProcessorOptions,
@ -160,7 +183,10 @@ describe('IssueLogger', (): void => {
expect(coreWarningSpy).toHaveBeenCalledTimes(1); expect(coreWarningSpy).toHaveBeenCalledTimes(1);
expect(coreWarningSpy).toHaveBeenCalledWith( expect(coreWarningSpy).toHaveBeenCalledWith(
`[#8] ${replacement} will stale` expect.stringContaining(`[#8]`)
);
expect(coreWarningSpy).toHaveBeenCalledWith(
expect.stringContaining(`${replacement} will stale`)
); );
} }
); );

View File

@ -1,6 +1,6 @@
import chalk from 'chalk';
import {Issue} from '../issue'; import {Issue} from '../issue';
import {Logger} from './logger'; import {Logger} from './logger';
import {LoggerService} from '../../services/logger.service';
/** /**
* @description * @description
@ -70,10 +70,10 @@ export class IssueLogger extends Logger {
} }
private _getIssuePrefix(): string { private _getIssuePrefix(): string {
return chalk.red(`[#${this._getIssueNumber()}]`); return LoggerService.red(`[#${this._getIssueNumber()}]`);
} }
private _getPullRequestPrefix(): string { private _getPullRequestPrefix(): string {
return chalk.blue(`[#${this._getIssueNumber()}]`); return LoggerService.blue(`[#${this._getIssueNumber()}]`);
} }
} }

View File

@ -25,7 +25,9 @@ describe('Logger', (): void => {
logger.warning(message); logger.warning(message);
expect(coreWarningSpy).toHaveBeenCalledTimes(1); expect(coreWarningSpy).toHaveBeenCalledTimes(1);
expect(coreWarningSpy).toHaveBeenCalledWith('dummy-message'); expect(coreWarningSpy).toHaveBeenCalledWith(
expect.stringContaining('dummy-message')
);
}); });
}); });
@ -46,7 +48,9 @@ describe('Logger', (): void => {
logger.info(message); logger.info(message);
expect(coreInfoSpy).toHaveBeenCalledTimes(1); expect(coreInfoSpy).toHaveBeenCalledTimes(1);
expect(coreInfoSpy).toHaveBeenCalledWith('dummy-message'); expect(coreInfoSpy).toHaveBeenCalledWith(
expect.stringContaining('dummy-message')
);
}); });
}); });
@ -67,7 +71,9 @@ describe('Logger', (): void => {
logger.error(message); logger.error(message);
expect(coreErrorSpy).toHaveBeenCalledTimes(1); expect(coreErrorSpy).toHaveBeenCalledTimes(1);
expect(coreErrorSpy).toHaveBeenCalledWith('dummy-message'); expect(coreErrorSpy).toHaveBeenCalledWith(
expect.stringContaining('dummy-message')
);
}); });
}); });
}); });

View File

@ -1,19 +1,19 @@
import * as core from '@actions/core'; import * as core from '@actions/core';
import chalk from 'chalk';
import terminalLink from 'terminal-link'; import terminalLink from 'terminal-link';
import {Option} from '../../enums/option'; import {Option} from '../../enums/option';
import {LoggerService} from '../../services/logger.service';
export class Logger { export class Logger {
warning(...message: string[]): void { warning(...message: string[]): void {
core.warning(chalk.whiteBright(...message)); core.warning(LoggerService.whiteBright(message.join(' ')));
} }
info(...message: string[]): void { info(...message: string[]): void {
core.info(chalk.whiteBright(...message)); core.info(LoggerService.whiteBright(message.join(' ')));
} }
error(...message: string[]): void { error(...message: string[]): void {
core.error(chalk.whiteBright(...message)); core.error(LoggerService.whiteBright(message.join(' ')));
} }
createLink(name: Readonly<string>, link: Readonly<string>): string { createLink(name: Readonly<string>, link: Readonly<string>): string {
@ -21,7 +21,7 @@ export class Logger {
} }
createOptionLink(option: Readonly<Option>): string { createOptionLink(option: Readonly<Option>): string {
return chalk.magenta( return LoggerService.magenta(
this.createLink(option, `https://github.com/actions/stale#${option}`) this.createLink(option, `https://github.com/actions/stale#${option}`)
); );
} }

View File

@ -1,10 +1,10 @@
import chalk from 'chalk';
import deburr from 'lodash.deburr'; import deburr from 'lodash.deburr';
import {Option} from '../enums/option'; import {Option} from '../enums/option';
import {wordsToList} from '../functions/words-to-list'; import {wordsToList} from '../functions/words-to-list';
import {IIssuesProcessorOptions} from '../interfaces/issues-processor-options'; import {IIssuesProcessorOptions} from '../interfaces/issues-processor-options';
import {Issue} from './issue'; import {Issue} from './issue';
import {IssueLogger} from './loggers/issue-logger'; import {IssueLogger} from './loggers/issue-logger';
import {LoggerService} from '../services/logger.service';
type CleanMilestone = string; type CleanMilestone = string;
@ -33,7 +33,7 @@ export class Milestones {
if (this._shouldExemptAllMilestones()) { if (this._shouldExemptAllMilestones()) {
this._issueLogger.info( this._issueLogger.info(
chalk.white('└──'), LoggerService.white('└──'),
'Skipping this $$type because it has a milestone' 'Skipping this $$type because it has a milestone'
); );
@ -44,7 +44,7 @@ export class Milestones {
if (exemptMilestones.length === 0) { if (exemptMilestones.length === 0) {
this._issueLogger.info( this._issueLogger.info(
chalk.white('├──'), LoggerService.white('├──'),
`No milestone option was specified to skip the stale process for this $$type` `No milestone option was specified to skip the stale process for this $$type`
); );
this._logSkip(); this._logSkip();
@ -53,8 +53,8 @@ export class Milestones {
} }
this._issueLogger.info( this._issueLogger.info(
chalk.white('├──'), LoggerService.white('├──'),
`Found ${chalk.cyan(exemptMilestones.length)} milestone${ `Found ${LoggerService.cyan(exemptMilestones.length)} milestone${
exemptMilestones.length > 1 ? 's' : '' exemptMilestones.length > 1 ? 's' : ''
} that can exempt stale on this $$type` } that can exempt stale on this $$type`
); );
@ -66,13 +66,13 @@ export class Milestones {
if (!hasExemptMilestone) { if (!hasExemptMilestone) {
this._issueLogger.info( this._issueLogger.info(
chalk.white('├──'), LoggerService.white('├──'),
'No milestone on this $$type can exempt the stale process' 'No milestone on this $$type can exempt the stale process'
); );
this._logSkip(); this._logSkip();
} else { } else {
this._issueLogger.info( this._issueLogger.info(
chalk.white('└──'), LoggerService.white('└──'),
'Skipping this $$type because it has an exempt milestone' 'Skipping this $$type because it has an exempt milestone'
); );
} }
@ -89,7 +89,7 @@ export class Milestones {
private _getExemptIssueMilestones(): string[] { private _getExemptIssueMilestones(): string[] {
if (this._options.exemptIssueMilestones === '') { if (this._options.exemptIssueMilestones === '') {
this._issueLogger.info( this._issueLogger.info(
chalk.white('├──'), LoggerService.white('├──'),
`The option ${this._issueLogger.createOptionLink( `The option ${this._issueLogger.createOptionLink(
Option.ExemptIssueMilestones Option.ExemptIssueMilestones
)} is disabled. No specific milestone can skip the stale process for this $$type` )} is disabled. No specific milestone can skip the stale process for this $$type`
@ -97,7 +97,7 @@ export class Milestones {
if (this._options.exemptMilestones === '') { if (this._options.exemptMilestones === '') {
this._issueLogger.info( this._issueLogger.info(
chalk.white('├──'), LoggerService.white('├──'),
`The option ${this._issueLogger.createOptionLink( `The option ${this._issueLogger.createOptionLink(
Option.ExemptMilestones Option.ExemptMilestones
)} is disabled. No specific milestone can skip the stale process for this $$type` )} is disabled. No specific milestone can skip the stale process for this $$type`
@ -111,10 +111,10 @@ export class Milestones {
); );
this._issueLogger.info( this._issueLogger.info(
chalk.white('├──'), LoggerService.white('├──'),
`The option ${this._issueLogger.createOptionLink( `The option ${this._issueLogger.createOptionLink(
Option.ExemptMilestones Option.ExemptMilestones
)} is set. ${chalk.cyan(exemptMilestones.length)} milestone${ )} is set. ${LoggerService.cyan(exemptMilestones.length)} milestone${
exemptMilestones.length === 1 ? '' : 's' exemptMilestones.length === 1 ? '' : 's'
} can skip the stale process for this $$type` } can skip the stale process for this $$type`
); );
@ -127,10 +127,10 @@ export class Milestones {
); );
this._issueLogger.info( this._issueLogger.info(
chalk.white('├──'), LoggerService.white('├──'),
`The option ${this._issueLogger.createOptionLink( `The option ${this._issueLogger.createOptionLink(
Option.ExemptIssueMilestones Option.ExemptIssueMilestones
)} is set. ${chalk.cyan(exemptMilestones.length)} milestone${ )} is set. ${LoggerService.cyan(exemptMilestones.length)} milestone${
exemptMilestones.length === 1 ? '' : 's' exemptMilestones.length === 1 ? '' : 's'
} can skip the stale process for this $$type` } can skip the stale process for this $$type`
); );
@ -141,7 +141,7 @@ export class Milestones {
private _getExemptPullRequestMilestones(): string[] { private _getExemptPullRequestMilestones(): string[] {
if (this._options.exemptPrMilestones === '') { if (this._options.exemptPrMilestones === '') {
this._issueLogger.info( this._issueLogger.info(
chalk.white('├──'), LoggerService.white('├──'),
`The option ${this._issueLogger.createOptionLink( `The option ${this._issueLogger.createOptionLink(
Option.ExemptPrMilestones Option.ExemptPrMilestones
)} is disabled. No specific milestone can skip the stale process for this $$type` )} is disabled. No specific milestone can skip the stale process for this $$type`
@ -149,7 +149,7 @@ export class Milestones {
if (this._options.exemptMilestones === '') { if (this._options.exemptMilestones === '') {
this._issueLogger.info( this._issueLogger.info(
chalk.white('├──'), LoggerService.white('├──'),
`The option ${this._issueLogger.createOptionLink( `The option ${this._issueLogger.createOptionLink(
Option.ExemptMilestones Option.ExemptMilestones
)} is disabled. No specific milestone can skip the stale process for this $$type` )} is disabled. No specific milestone can skip the stale process for this $$type`
@ -163,10 +163,10 @@ export class Milestones {
); );
this._issueLogger.info( this._issueLogger.info(
chalk.white('├──'), LoggerService.white('├──'),
`The option ${this._issueLogger.createOptionLink( `The option ${this._issueLogger.createOptionLink(
Option.ExemptMilestones Option.ExemptMilestones
)} is set. ${chalk.cyan(exemptMilestones.length)} milestone${ )} is set. ${LoggerService.cyan(exemptMilestones.length)} milestone${
exemptMilestones.length === 1 ? '' : 's' exemptMilestones.length === 1 ? '' : 's'
} can skip the stale process for this $$type` } can skip the stale process for this $$type`
); );
@ -179,10 +179,10 @@ export class Milestones {
); );
this._issueLogger.info( this._issueLogger.info(
chalk.white('├──'), LoggerService.white('├──'),
`The option ${this._issueLogger.createOptionLink( `The option ${this._issueLogger.createOptionLink(
Option.ExemptPrMilestones Option.ExemptPrMilestones
)} is set. ${chalk.cyan(exemptMilestones.length)} milestone${ )} is set. ${LoggerService.cyan(exemptMilestones.length)} milestone${
exemptMilestones.length === 1 ? '' : 's' exemptMilestones.length === 1 ? '' : 's'
} can skip the stale process for this $$type` } can skip the stale process for this $$type`
); );
@ -205,8 +205,10 @@ export class Milestones {
if (isSameMilestone) { if (isSameMilestone) {
this._issueLogger.info( this._issueLogger.info(
chalk.white('├──'), LoggerService.white('├──'),
`The milestone "${milestone}" is set on this $$type and is an exempt milestone` `The milestone "${LoggerService.cyan(
milestone
)}" is set on this $$type and is an exempt milestone`
); );
} }
@ -288,6 +290,9 @@ export class Milestones {
} }
private _logSkip(): void { private _logSkip(): void {
this._issueLogger.info(chalk.white('└──'), 'Skip the milestones checks'); this._issueLogger.info(
LoggerService.white('└──'),
'Skip the milestones checks'
);
} }
} }

View File

@ -1,6 +1,6 @@
import chalk from 'chalk';
import {Issue} from './issue'; import {Issue} from './issue';
import {Logger} from './loggers/logger'; import {Logger} from './loggers/logger';
import {LoggerService} from '../services/logger.service';
interface IGroupValue { interface IGroupValue {
name: string; name: string;
@ -163,7 +163,7 @@ export class Statistics {
} }
logStats(): Statistics { logStats(): Statistics {
this._logger.info(chalk.yellow.bold('Statistics:')); this._logger.info(LoggerService.yellow(LoggerService.bold(`Statistics:`)));
this._logProcessedIssuesAndPullRequestsCount(); this._logProcessedIssuesAndPullRequestsCount();
this._logStaleIssuesAndPullRequestsCount(); this._logStaleIssuesAndPullRequestsCount();
this._logUndoStaleIssuesAndPullRequestsCount(); this._logUndoStaleIssuesAndPullRequestsCount();
@ -440,7 +440,7 @@ export class Statistics {
private _logCount(name: Readonly<string>, count: Readonly<number>): void { private _logCount(name: Readonly<string>, count: Readonly<number>): void {
if (count > 0) { if (count > 0) {
this._logger.info(`${name}:`, chalk.cyan(count)); this._logger.info(`${name}:`, LoggerService.cyan(count));
} }
} }
@ -498,7 +498,10 @@ export class Statistics {
const prefix = index === onlyValuesSet.length - 1 ? '└──' : '├──'; const prefix = index === onlyValuesSet.length - 1 ? '└──' : '├──';
this._logCount( this._logCount(
`${chalk.white(prefix)} ${value.name.padEnd(longestValue, ' ')}`, `${LoggerService.white(prefix)} ${value.name.padEnd(
longestValue,
' '
)}`,
value.count value.count
); );
} }

View File

@ -0,0 +1,52 @@
import styles, {Modifier, ForegroundColor} from 'ansi-styles';
type Message = string | number | boolean;
export class LoggerService {
static whiteBright(message: Readonly<Message>): string {
return this._format(message, 'whiteBright');
}
static yellowBright(message: Readonly<Message>): string {
return this._format(message, 'yellowBright');
}
static magenta(message: Readonly<Message>): string {
return this._format(message, 'magenta');
}
static cyan(message: Readonly<Message>): string {
return this._format(message, 'cyan');
}
static yellow(message: Readonly<Message>): string {
return this._format(message, 'yellow');
}
static white(message: Readonly<Message>): string {
return this._format(message, 'white');
}
static green(message: Readonly<Message>): string {
return this._format(message, 'green');
}
static red(message: Readonly<Message>): string {
return this._format(message, 'red');
}
static blue(message: Readonly<Message>): string {
return this._format(message, 'blue');
}
static bold(message: Readonly<Message>): string {
return this._format(message, 'bold');
}
private static _format(
message: Readonly<Message>,
style: keyof Modifier | keyof ForegroundColor
): string {
return `${styles[style].open}${message}${styles[style].close}`;
}
}