chore(logs): enhance the logs (#358)

* 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] <support@github.com>

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] <support@github.com>

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>

* chore(logs): add logs for the milestones

* chore(errors): use actions error instead of throw errors

* chore(logs): enhance the logs and add some colors

tl;dr: blue for values, megenta for options, white for messages, yellow light for warnings, yellow for milestones and green for success
still a WIP but I wish to confirm this before continuing
@hross is it ok for you?

* chore(index): update the index

* chore(ci): use npm ci instead of npm i

* chore(logs): removed some useless logs

* refactor(issues): remove useless check

* chore(statistics): show the real count of fetched issues

* refactor(operations): use a class to handle the operations left

closes #361

* chore(logs): include the total number of issues in the log for a batch

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
This commit is contained in:
Geoffrey Testelin
2021-03-08 11:56:52 +01:00
committed by GitHub
parent 3b3c3f03cd
commit b717aa9f47
15 changed files with 3217 additions and 230 deletions

View File

@@ -42,7 +42,7 @@ export class Assignees {
if (exemptAssignees.length === 0) {
this._issueLogger.info(
`No 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();
@@ -52,7 +52,7 @@ export class Assignees {
this._issueLogger.info(
`Found ${exemptAssignees.length} assignee${
exemptAssignees.length > 1 ? 's' : ''
} on this $$type`
} that can exempt stale on this $$type`
);
const hasExemptAssignee: boolean = exemptAssignees.some(

View File

@@ -1,11 +1,13 @@
import * as core from '@actions/core';
import {context, getOctokit} from '@actions/github';
import {GitHub} from '@actions/github/lib/utils';
import {GetResponseTypeFromEndpointMethod} from '@octokit/types';
import chalk from 'chalk';
import {Option} from '../enums/option';
import {getHumanizedDate} from '../functions/dates/get-humanized-date';
import {isDateMoreRecentThan} from '../functions/dates/is-date-more-recent-than';
import {isValidDate} from '../functions/dates/is-valid-date';
import {isLabeled} from '../functions/is-labeled';
import {isPullRequest} from '../functions/is-pull-request';
import {shouldMarkWhenStale} from '../functions/should-mark-when-stale';
import {wordsToList} from '../functions/words-to-list';
import {IComment} from '../interfaces/comment';
@@ -18,6 +20,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 {Statistics} from './statistics';
/***
@@ -33,8 +36,8 @@ export class IssuesProcessor {
}
private readonly _logger: Logger = new Logger();
private readonly _operations: Operations;
private readonly _statistics: Statistics | undefined;
private _operationsLeft = 0;
readonly client: InstanceType<typeof GitHub>;
readonly options: IIssuesProcessorOptions;
readonly staleIssues: Issue[] = [];
@@ -44,31 +47,49 @@ export class IssuesProcessor {
constructor(options: IIssuesProcessorOptions) {
this.options = options;
this._operationsLeft = this.options.operationsPerRun;
this.client = getOctokit(this.options.repoToken);
this._operations = new Operations(this.options);
this._logger.info(chalk.yellow('Starting the stale action process...'));
if (this.options.debugOnly) {
this._logger.warning(chalk.yellowBright('Executing in debug mode!'));
this._logger.warning(
'Executing in debug mode. Debug output will be written but no issues will be processed.'
chalk.yellowBright(
'The debug output will be written but no issues/PRs will be processed.'
)
);
}
if (this.options.enableStatistics) {
this._statistics = new Statistics(this.options);
this._statistics = new Statistics();
}
}
async processIssues(page = 1): Promise<number> {
async processIssues(page: Readonly<number> = 1): Promise<number> {
// get the next batch of issues
const issues: Issue[] = await this.getIssues(page);
const actor: string = await this.getActor();
if (issues.length <= 0) {
this._logger.info('---');
this._statistics?.setOperationsLeft(this._operationsLeft).logStats();
this._logger.info('No more issues found to process. Exiting.');
this._logger.info(
chalk.green('No more issues found to process. Exiting...')
);
this._statistics
?.setOperationsLeft(this._operations.getUnconsumedOperationsCount())
.logStats();
return this._operationsLeft;
return this._operations.getOperationsLeftCount();
} else {
this._logger.info(
chalk.yellow(
`Processing the batch of issues ${chalk.cyan(
`#${page}`
)} containing ${chalk.cyan(issues.length)} issue${
issues.length > 1 ? 's' : ''
}...`
)
);
}
for (const issue of issues.values()) {
@@ -160,8 +181,10 @@ export class IssuesProcessor {
// Expecting that GitHub will always set a creation date on the issues and PRs
// But you never know!
if (!isValidDate(createdAt)) {
throw new Error(
`Invalid issue field: "created_at". Expected a valid date`
core.setFailed(
new Error(
`Invalid issue field: "created_at". Expected a valid date`
)
);
}
@@ -207,6 +230,7 @@ export class IssuesProcessor {
}
const anyOfLabels: string[] = wordsToList(this.options.anyOfLabels);
if (
anyOfLabels.length &&
!anyOfLabels.some((label: Readonly<string>): boolean =>
@@ -222,9 +246,6 @@ export class IssuesProcessor {
const milestones: Milestones = new Milestones(this.options, issue);
if (milestones.shouldExemptMilestones()) {
issueLogger.info(
`Skipping $$type because it has an exempted milestone`
);
continue; // don't process exempt milestones
}
@@ -266,13 +287,27 @@ export class IssuesProcessor {
}
}
if (this._operationsLeft <= 0) {
if (this._operations.hasOperationsLeft()) {
this._logger.warning(
'Reached max number of operations to process. Exiting.'
chalk.yellowBright('No more operations left! Exiting...')
);
this._logger.warning(
chalk.yellowBright(
`If you think that not enough issues were processed you could try to increase the quantity related to the ${this._logger.createOptionLink(
Option.OperationsPerRun
)} option which is currently set to ${chalk.cyan(
this.options.operationsPerRun
)}`
)
);
return 0;
}
this._logger.info(
chalk.green(`Batch ${chalk.cyan(`#${page}`)} processed.`)
);
// do the next batch
return this.processIssues(page + 1);
}
@@ -284,7 +319,7 @@ export class IssuesProcessor {
): Promise<IComment[]> {
// find any comments since date on the given issue
try {
this._operationsLeft -= 1;
this._operations.consumeOperation();
this._statistics?.incrementFetchedIssuesCommentsCount();
const comments = await this.client.issues.listComments({
owner: context.repo.owner,
@@ -304,7 +339,7 @@ export class IssuesProcessor {
let actor;
try {
this._operationsLeft -= 1;
this._operations.consumeOperation();
actor = await this.client.users.getAuthenticated();
} catch (error) {
return context.actor;
@@ -320,8 +355,7 @@ export class IssuesProcessor {
type OctoKitIssueList = GetResponseTypeFromEndpointMethod<typeof endpoint>;
try {
this._operationsLeft -= 1;
this._statistics?.incrementFetchedIssuesCount();
this._operations.consumeOperation();
const issueResult: OctoKitIssueList = await this.client.issues.listForRepo(
{
owner: context.repo.owner,
@@ -332,6 +366,7 @@ export class IssuesProcessor {
page
}
);
this._statistics?.incrementFetchedIssuesCount(issueResult.data.length);
return issueResult.data.map(
(issue: Readonly<IIssue>): Issue => new Issue(this.options, issue)
@@ -352,7 +387,7 @@ export class IssuesProcessor {
issueLogger.info(`Checking for label on $$type`);
this._operationsLeft -= 1;
this._operations.consumeOperation();
this._statistics?.incrementFetchedIssuesEventsCount();
const options = this.client.issues.listEvents.endpoint.merge({
owner: context.repo.owner,
@@ -396,8 +431,7 @@ export class IssuesProcessor {
);
issueLogger.info(`$$type has been commented on: ${issueHasComments}`);
const isPr: boolean = isPullRequest(issue);
const daysBeforeClose: number = isPr
const daysBeforeClose: number = issue.isPullRequest
? this._getDaysBeforePrClose()
: this._getDaysBeforeIssueClose();
@@ -491,7 +525,7 @@ export class IssuesProcessor {
if (!skipMessage) {
try {
this._operationsLeft -= 1;
this._operations.consumeOperation();
this._statistics?.incrementAddedComment();
await this.client.issues.createComment({
owner: context.repo.owner,
@@ -505,7 +539,7 @@ export class IssuesProcessor {
}
try {
this._operationsLeft -= 1;
this._operations.consumeOperation();
this._statistics?.incrementAddedLabel();
this._statistics?.incrementStaleIssuesCount();
await this.client.issues.addLabels({
@@ -536,7 +570,7 @@ export class IssuesProcessor {
if (closeMessage) {
try {
this._operationsLeft -= 1;
this._operations.consumeOperation();
this._statistics?.incrementAddedComment();
await this.client.issues.createComment({
owner: context.repo.owner,
@@ -551,7 +585,7 @@ export class IssuesProcessor {
if (closeLabel) {
try {
this._operationsLeft -= 1;
this._operations.consumeOperation();
this._statistics?.incrementAddedLabel();
await this.client.issues.addLabels({
owner: context.repo.owner,
@@ -565,7 +599,7 @@ export class IssuesProcessor {
}
try {
this._operationsLeft -= 1;
this._operations.consumeOperation();
this._statistics?.incrementClosedIssuesCount();
await this.client.issues.update({
owner: context.repo.owner,
@@ -588,7 +622,7 @@ export class IssuesProcessor {
}
try {
this._operationsLeft -= 1;
this._operations.consumeOperation();
this._statistics?.incrementFetchedPullRequestsCount();
const pullRequest = await this.client.pulls.get({
owner: context.repo.owner,
@@ -625,7 +659,7 @@ export class IssuesProcessor {
issueLogger.info(`Deleting branch ${branch} from closed $$type`);
try {
this._operationsLeft -= 1;
this._operations.consumeOperation();
this._statistics?.incrementDeletedBranchesCount();
await this.client.git.deleteRef({
owner: context.repo.owner,
@@ -646,13 +680,12 @@ export class IssuesProcessor {
issueLogger.info(`Removing label "${label}" from $$type`);
this.removedLabelIssues.push(issue);
// @todo remove the debug only to be able to test the code below
if (this.options.debugOnly) {
return;
}
try {
this._operationsLeft -= 1;
this._operations.consumeOperation();
this._statistics?.incrementDeletedLabelsCount();
await this.client.issues.removeLabel({
owner: context.repo.owner,

View File

@@ -1,4 +1,4 @@
import * as core from '@actions/core';
import chalk from 'chalk';
import {Issue} from '../issue';
import {Logger} from './logger';
@@ -15,23 +15,24 @@ import {Logger} from './logger';
* @example
* warning('The $$type will stale') => "The pull request will stale"
*/
export class IssueLogger implements Logger {
export class IssueLogger extends Logger {
private readonly _issue: Issue;
constructor(issue: Issue) {
super();
this._issue = issue;
}
warning(message: Readonly<string>): void {
core.warning(this._format(message));
warning(...message: string[]): void {
super.warning(this._format(...message));
}
info(message: Readonly<string>): void {
core.info(this._format(message));
info(...message: string[]): void {
super.info(this._format(...message));
}
error(message: Readonly<string>): void {
core.error(this._format(message));
error(...message: string[]): void {
super.error(this._format(...message));
}
private _replaceTokens(message: Readonly<string>): string {
@@ -51,14 +52,28 @@ export class IssueLogger implements Logger {
}
private _prefixWithIssueNumber(message: Readonly<string>): string {
return `[#${this._getIssueNumber()}] ${message}`;
return `${this._getPrefix()} ${message}`;
}
private _getIssueNumber(): number {
return this._issue.number;
}
private _format(message: Readonly<string>): string {
return this._prefixWithIssueNumber(this._replaceTokens(message));
private _format(...message: string[]): string {
return this._prefixWithIssueNumber(this._replaceTokens(message.join(' ')));
}
private _getPrefix(): string {
return this._issue.isPullRequest
? this._getPullRequestPrefix()
: this._getIssuePrefix();
}
private _getIssuePrefix(): string {
return chalk.red(`[#${this._getIssueNumber()}]`);
}
private _getPullRequestPrefix(): string {
return chalk.blue(`[#${this._getIssueNumber()}]`);
}
}

View File

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

View File

@@ -2,6 +2,7 @@ import deburr from 'lodash.deburr';
import {wordsToList} from '../functions/words-to-list';
import {IIssuesProcessorOptions} from '../interfaces/issues-processor-options';
import {Issue} from './issue';
import {IssueLogger} from './loggers/issue-logger';
type CleanMilestone = string;
@@ -12,42 +13,158 @@ export class Milestones {
private readonly _options: IIssuesProcessorOptions;
private readonly _issue: Issue;
private readonly _issueLogger: IssueLogger;
constructor(options: Readonly<IIssuesProcessorOptions>, issue: Issue) {
this._options = options;
this._issue = issue;
this._issueLogger = new IssueLogger(issue);
}
shouldExemptMilestones(): boolean {
if (!this._issue.milestone) {
this._issueLogger.info('This $$type has no milestone');
this._logSkip();
return false;
}
if (this._shouldExemptAllMilestones()) {
this._issueLogger.info(
'Skipping $$type because it has an exempt milestone'
);
return true;
}
const exemptMilestones: string[] = this._getExemptMilestones();
return exemptMilestones.some((exemptMilestone: Readonly<string>): boolean =>
this._hasMilestone(exemptMilestone)
if (exemptMilestones.length === 0) {
this._issueLogger.info(
`No milestone option was specified to skip the stale process for this $$type`
);
this._logSkip();
return false;
}
this._issueLogger.info(
`Found ${exemptMilestones.length} milestone${
exemptMilestones.length > 1 ? 's' : ''
} that can exempt stale on this $$type`
);
const hasExemptMilestone: boolean = exemptMilestones.some(
(exemptMilestone: Readonly<string>): boolean =>
this._hasMilestone(exemptMilestone)
);
if (!hasExemptMilestone) {
this._issueLogger.info(
'No milestone on this $$type can exempt the stale process'
);
this._logSkip();
} else {
this._issueLogger.info(
'Skipping this $$type because it has an exempt milestone'
);
}
return hasExemptMilestone;
}
private _getExemptMilestones(): string[] {
return wordsToList(
this._issue.isPullRequest
? this._getExemptPullRequestMilestones()
: this._getExemptIssueMilestones()
return this._issue.isPullRequest
? this._getExemptPullRequestMilestones()
: this._getExemptIssueMilestones();
}
private _getExemptIssueMilestones(): string[] {
if (this._options.exemptIssueMilestones === '') {
this._issueLogger.info(
'The option "exemptIssueMilestones" is disabled. No specific milestone can skip the stale process for this $$type'
);
if (this._options.exemptMilestones === '') {
this._issueLogger.info(
'The option "exemptMilestones" is disabled. No specific milestone can skip the stale process for this $$type'
);
return [];
}
const exemptMilestones: string[] = wordsToList(
this._options.exemptMilestones
);
this._issueLogger.info(
`The option "exemptMilestones" is set. ${
exemptMilestones.length
} milestone${
exemptMilestones.length === 1 ? '' : 's'
} can skip the stale process for this $$type`
);
return exemptMilestones;
}
const exemptMilestones: string[] = wordsToList(
this._options.exemptIssueMilestones
);
this._issueLogger.info(
`The option "exemptIssueMilestones" is set. ${
exemptMilestones.length
} milestone${
exemptMilestones.length === 1 ? '' : 's'
} can skip the stale process for this $$type`
);
return exemptMilestones;
}
private _getExemptIssueMilestones(): string {
return this._options.exemptIssueMilestones !== ''
? this._options.exemptIssueMilestones
: this._options.exemptMilestones;
}
private _getExemptPullRequestMilestones(): string[] {
if (this._options.exemptPrMilestones === '') {
this._issueLogger.info(
'The option "exemptPrMilestones" is disabled. No specific milestone can skip the stale process for this $$type'
);
private _getExemptPullRequestMilestones(): string {
return this._options.exemptPrMilestones !== ''
? this._options.exemptPrMilestones
: this._options.exemptMilestones;
if (this._options.exemptMilestones === '') {
this._issueLogger.info(
'The option "exemptMilestones" is disabled. No specific milestone can skip the stale process for this $$type'
);
return [];
}
const exemptMilestones: string[] = wordsToList(
this._options.exemptMilestones
);
this._issueLogger.info(
`The option "exemptMilestones" is set. ${
exemptMilestones.length
} milestone${
exemptMilestones.length === 1 ? '' : 's'
} can skip the stale process for this $$type`
);
return exemptMilestones;
}
const exemptMilestones: string[] = wordsToList(
this._options.exemptPrMilestones
);
this._issueLogger.info(
`The option "exemptPrMilestones" is set. ${
exemptMilestones.length
} milestone${
exemptMilestones.length === 1 ? '' : 's'
} can skip the stale process for this $$type`
);
return exemptMilestones;
}
private _hasMilestone(milestone: Readonly<string>): boolean {
@@ -55,10 +172,21 @@ export class Milestones {
return false;
}
return (
Milestones._cleanMilestone(milestone) ===
Milestones._cleanMilestone(this._issue.milestone.title)
const cleanMilestone: CleanMilestone = Milestones._cleanMilestone(
milestone
);
const isSameMilestone: boolean =
cleanMilestone ===
Milestones._cleanMilestone(this._issue.milestone.title);
if (isSameMilestone) {
this._issueLogger.info(
`The milestone "${milestone}" is set on this $$type and is an exempt milestone`
);
}
return isSameMilestone;
}
private _shouldExemptAllMilestones(): boolean {
@@ -73,21 +201,57 @@ export class Milestones {
private _shouldExemptAllIssueMilestones(): boolean {
if (this._options.exemptAllIssueMilestones === true) {
this._issueLogger.info(
'The option "exemptAllIssueMilestones" is enabled. Any milestone on this $$type will skip the stale process'
);
return true;
} else if (this._options.exemptAllIssueMilestones === false) {
this._issueLogger.info(
'The option "exemptAllIssueMilestones" is disabled. Only some specific milestones on this $$type will skip the stale process'
);
return false;
}
this._logExemptAllMilestonesOption();
return this._options.exemptAllMilestones;
}
private _shouldExemptAllPullRequestMilestones(): boolean {
if (this._options.exemptAllPrMilestones === true) {
this._issueLogger.info(
'The option "exemptAllPrMilestones" is enabled. Any milestone on this $$type will skip the stale process'
);
return true;
} else if (this._options.exemptAllPrMilestones === false) {
this._issueLogger.info(
'The option "exemptAllPrMilestones" is disabled. Only some specific milestones on this $$type will skip the stale process'
);
return false;
}
this._logExemptAllMilestonesOption();
return this._options.exemptAllMilestones;
}
private _logExemptAllMilestonesOption(): void {
if (this._options.exemptAllMilestones) {
this._issueLogger.info(
'The option "exemptAllMilestones" is enabled. Any milestone on this $$type will skip the stale process'
);
} else {
this._issueLogger.info(
'The option "exemptAllMilestones" is disabled. Only some specific milestones on this $$type will skip the stale process'
);
}
}
private _logSkip(): void {
this._issueLogger.info('Skip the milestones checks');
}
}

33
src/classes/operations.ts Normal file
View File

@@ -0,0 +1,33 @@
import {IIssuesProcessorOptions} from '../interfaces/issues-processor-options';
export class Operations {
private readonly _options: IIssuesProcessorOptions;
private _operationsLeft;
constructor(options: Readonly<IIssuesProcessorOptions>) {
this._options = options;
this._operationsLeft = this._options.operationsPerRun;
}
consumeOperation(): Operations {
return this.consumeOperations(1);
}
consumeOperations(quantity: Readonly<number>): Operations {
this._operationsLeft -= quantity;
return this;
}
getUnconsumedOperationsCount(): number {
return this._options.operationsPerRun - this._operationsLeft;
}
hasOperationsLeft(): boolean {
return this._operationsLeft <= 0;
}
getOperationsLeftCount(): number {
return this._operationsLeft;
}
}

View File

@@ -1,9 +1,8 @@
import {IIssuesProcessorOptions} from '../interfaces/issues-processor-options';
import chalk from 'chalk';
import {Logger} from './loggers/logger';
export class Statistics {
private readonly _logger: Logger = new Logger();
private readonly _options: IIssuesProcessorOptions;
private _processedIssuesCount = 0;
private _staleIssuesCount = 0;
private _undoStaleIssuesCount = 0;
@@ -19,10 +18,6 @@ export class Statistics {
private _fetchedIssuesCommentsCount = 0;
private _fetchedPullRequestsCount = 0;
constructor(options: IIssuesProcessorOptions) {
this._options = options;
}
incrementProcessedIssuesCount(increment: Readonly<number> = 1): Statistics {
this._processedIssuesCount += increment;
@@ -42,7 +37,7 @@ export class Statistics {
}
setOperationsLeft(operationsLeft: Readonly<number>): Statistics {
this._operationsCount = this._options.operationsPerRun - operationsLeft;
this._operationsCount = operationsLeft;
return this;
}
@@ -116,7 +111,7 @@ export class Statistics {
}
logStats(): Statistics {
this._logger.info('Statistics');
this._logger.info(chalk.yellow.bold('Statistics:'));
this._logProcessedIssuesCount();
this._logStaleIssuesCount();
this._logUndoStaleIssuesCount();
@@ -131,7 +126,6 @@ export class Statistics {
this._logFetchedIssuesEventsCount();
this._logFetchedIssuesCommentsCount();
this._logFetchedPullRequestsCount();
this._logger.info('---');
return this;
}
@@ -194,7 +188,7 @@ export class Statistics {
private _logCount(name: Readonly<string>, count: Readonly<number>): void {
if (count > 0) {
this._logger.info(`${name}: ${count}`);
this._logger.info(`${name}:`, chalk.cyan(count));
}
}
}

44
src/enums/option.ts Normal file
View File

@@ -0,0 +1,44 @@
export enum Option {
RepoToken = 'repo-token',
StaleIssueMessage = 'stale-issue-message',
StalePrMessage = 'stale-pr-message',
CloseIssueMessage = 'close-issue-message',
ClosePrMessage = 'close-pr-message',
DaysBeforeStale = 'days-before-stale',
DaysBeforeIssueStale = 'days-before-issue-stale',
DaysBeforePrStale = 'days-before-pr-stale',
DaysBeforeClose = 'days-before-close',
DaysBeforeIssueClose = 'days-before-issue-close',
DaysBeforePrClose = 'days-before-pr-close',
StaleIssueLabel = 'stale-issue-label',
CloseIssueLabel = 'close-issue-label',
ExemptIssueLabels = 'exempt-issue-labels',
StalePrLabel = 'stale-pr-label',
ClosePrLabel = 'close-pr-label',
ExemptPrLabels = 'exempt-pr-labels',
OnlyLabels = 'only-labels',
OnlyIssueLabels = 'only-issue-labels',
OnlyPrLabels = 'only-pr-labels',
AnyOfLabels = 'any-of-labels',
OperationsPerRun = 'operations-per-run',
RemoveStaleWhenUpdated = 'remove-stale-when-updated',
DebugOnly = 'debug-only',
Ascending = 'ascending',
SkipStaleIssueMessage = 'skip-stale-issue-message',
SkipStalePrMessage = 'skip-stale-pr-message',
DeleteBranch = 'delete-branch',
StartDate = 'start-date',
ExemptMilestones = 'exempt-milestones',
ExemptIssueMilestones = 'exempt-issue-milestones',
ExemptPrMilestones = 'exempt-pr-milestones',
ExemptAllMilestones = 'exempt-all-milestones',
ExemptAllIssueMilestones = 'exempt-all-issue-milestones',
ExemptAllPrMilestones = 'exempt-all-pr-milestones',
ExemptAssignees = 'exempt-assignees',
ExemptIssueAssignees = 'exempt-issue-assignees',
ExemptPrAssignees = 'exempt-pr-assignees',
ExemptAllAssignees = 'exempt-all-assignees',
ExemptAllIssueAssignees = 'exempt-all-issue-assignees',
ExemptAllPrAssignees = 'exempt-all-pr-assignees',
EnableStatistics = 'enable-statistics'
}

View File

@@ -7,8 +7,7 @@ async function _run(): Promise<void> {
try {
const args = _getAndValidateArgs();
const processor: IssuesProcessor = new IssuesProcessor(args);
await processor.processIssues();
await new IssuesProcessor(args).processIssues();
} catch (error) {
core.error(error);
core.setFailed(error.message);
@@ -78,7 +77,9 @@ function _getAndValidateArgs(): IIssuesProcessorOptions {
'operations-per-run'
]) {
if (isNaN(parseInt(core.getInput(numberInput)))) {
throw Error(`input ${numberInput} did not parse to a valid integer`);
core.setFailed(
new Error(`Option "${numberInput}" did not parse to a valid integer`)
);
}
}
@@ -86,8 +87,10 @@ 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)))) {
throw new Error(
`input ${optionalDateInput} did not parse to a valid date`
core.setFailed(
new Error(
`Option "${optionalDateInput}" did not parse to a valid date`
)
);
}
}