feat(remove-stale-when-updated): add 2 options for issues and prs (#383)

* 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>

* 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(remove-stale-when-updated): add 2 options for issues and prs

closes #377
also I closed the stale process once the stale label is removed since the following process is regarding the closing and it should simply not occur if no longer stale

* chore(logs): add more logs to understand the process

* chore(logs): highlights more logs and humanize a bit more

* chore(index): update it

* refactor(checks): simplify if complexity

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
This commit is contained in:
Geoffrey Testelin
2021-04-30 15:14:51 +02:00
committed by GitHub
parent 043fbbdea3
commit 440fb174b5
12 changed files with 767 additions and 81 deletions

View File

@@ -35,6 +35,8 @@ describe('Issue', (): void => {
anyOfPrLabels: '',
operationsPerRun: 0,
removeStaleWhenUpdated: false,
removeIssueStaleWhenUpdated: undefined,
removePrStaleWhenUpdated: undefined,
repoToken: '',
skipStaleIssueMessage: false,
skipStalePrMessage: false,

View File

@@ -7,6 +7,7 @@ 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 {isBoolean} from '../functions/is-boolean';
import {isLabeled} from '../functions/is-labeled';
import {shouldMarkWhenStale} from '../functions/should-mark-when-stale';
import {wordsToList} from '../functions/words-to-list';
@@ -453,14 +454,16 @@ export class IssuesProcessor {
const issueLogger: IssueLogger = new IssueLogger(issue);
const markedStaleOn: string =
(await this.getLabelCreationDate(issue, staleLabel)) || issue.updated_at;
issueLogger.info(`$$type marked stale on: ${markedStaleOn}`);
issueLogger.info(`$$type marked stale on: ${chalk.cyan(markedStaleOn)}`);
const issueHasComments: boolean = await this._hasCommentsSince(
issue,
markedStaleOn,
actor
);
issueLogger.info(`$$type has been commented on: ${issueHasComments}`);
issueLogger.info(
`$$type has been commented on: ${chalk.cyan(issueHasComments)}`
);
const daysBeforeClose: number = issue.isPullRequest
? this._getDaysBeforePrClose()
@@ -472,11 +475,15 @@ export class IssuesProcessor {
issue.updated_at,
daysBeforeClose
);
issueLogger.info(`$$type has been updated: ${issueHasUpdate}`);
issueLogger.info(`$$type has been updated: ${chalk.cyan(issueHasUpdate)}`);
// should we un-stale this issue?
if (this.options.removeStaleWhenUpdated && issueHasComments) {
if (this._shouldRemoveStaleWhenUpdated(issue) && issueHasComments) {
await this._removeStaleLabel(issue, staleLabel);
issueLogger.info(`Skipping the process since the $$type is now un-stale`);
return; // nothing to do because it is no longer stale
}
// now start closing logic
@@ -565,7 +572,7 @@ export class IssuesProcessor {
body: staleMessage
});
} catch (error) {
issueLogger.error(`Error creating a comment: ${error.message}`);
issueLogger.error(`Error when creating a comment: ${error.message}`);
}
}
@@ -580,7 +587,7 @@ export class IssuesProcessor {
labels: [staleLabel]
});
} catch (error) {
issueLogger.error(`Error adding a label: ${error.message}`);
issueLogger.error(`Error when adding a label: ${error.message}`);
}
}
@@ -610,7 +617,7 @@ export class IssuesProcessor {
body: closeMessage
});
} catch (error) {
issueLogger.error(`Error creating a comment: ${error.message}`);
issueLogger.error(`Error when creating a comment: ${error.message}`);
}
}
@@ -625,7 +632,7 @@ export class IssuesProcessor {
labels: [closeLabel]
});
} catch (error) {
issueLogger.error(`Error adding a label: ${error.message}`);
issueLogger.error(`Error when adding a label: ${error.message}`);
}
}
@@ -639,7 +646,7 @@ export class IssuesProcessor {
state: 'closed'
});
} catch (error) {
issueLogger.error(`Error updating this $$type: ${error.message}`);
issueLogger.error(`Error when updating this $$type: ${error.message}`);
}
}
@@ -663,7 +670,7 @@ export class IssuesProcessor {
return pullRequest.data;
} catch (error) {
issueLogger.error(`Error getting this $$type: ${error.message}`);
issueLogger.error(`Error when getting this $$type: ${error.message}`);
}
}
@@ -687,7 +694,9 @@ export class IssuesProcessor {
}
const branch = pullRequest.head.ref;
issueLogger.info(`Deleting branch ${branch} from closed $$type`);
issueLogger.info(
`Deleting the branch "${chalk.cyan(branch)}" from closed $$type`
);
try {
this._operations.consumeOperation();
@@ -699,7 +708,9 @@ export class IssuesProcessor {
});
} catch (error) {
issueLogger.error(
`Error deleting branch ${branch} from $$type: ${error.message}`
`Error when deleting the branch "${chalk.cyan(branch)}" from $$type: ${
error.message
}`
);
}
}
@@ -708,7 +719,9 @@ export class IssuesProcessor {
private async _removeLabel(issue: Issue, label: string): Promise<void> {
const issueLogger: IssueLogger = new IssueLogger(issue);
issueLogger.info(`Removing label "${label}" from $$type`);
issueLogger.info(
`Removing the label "${chalk.cyan(label)}" from the $$type...`
);
this.removedLabelIssues.push(issue);
if (this.options.debugOnly) {
@@ -724,8 +737,11 @@ export class IssuesProcessor {
issue_number: issue.number,
name: label
});
issueLogger.info(`The label "${chalk.cyan(label)}" was removed`);
} catch (error) {
issueLogger.error(`Error removing a label: ${error.message}`);
issueLogger.error(
`Error when removing the label: "${chalk.cyan(error.message)}"`
);
}
}
@@ -781,6 +797,22 @@ export class IssuesProcessor {
return this.options.anyOfLabels;
}
private _shouldRemoveStaleWhenUpdated(issue: Issue): boolean {
if (issue.isPullRequest) {
if (isBoolean(this.options.removePrStaleWhenUpdated)) {
return this.options.removePrStaleWhenUpdated;
}
return this.options.removeStaleWhenUpdated;
}
if (isBoolean(this.options.removeIssueStaleWhenUpdated)) {
return this.options.removeIssueStaleWhenUpdated;
}
return this.options.removeStaleWhenUpdated;
}
private async _removeStaleLabel(
issue: Issue,
staleLabel: Readonly<string>
@@ -813,7 +845,9 @@ export class IssuesProcessor {
if (isLabeled(issue, closeLabel)) {
issueLogger.info(
`The $$type has a close label "${closeLabel}". Removing the close label...`
`The $$type has a close label "${chalk.cyan(
closeLabel
)}". Removing the close label...`
);
await this._removeLabel(issue, closeLabel);

View File

@@ -0,0 +1,29 @@
import {isBoolean} from './is-boolean';
describe('isBoolean()', (): void => {
describe.each([0, 1, undefined, null, ''])(
'when the given value is not a boolean',
(value): void => {
it('should return false', (): void => {
expect.assertions(1);
const result = isBoolean(value);
expect(result).toStrictEqual(false);
});
}
);
describe.each([false, true])(
'when the given value is a boolean',
(value): void => {
it('should return true', (): void => {
expect.assertions(1);
const result = isBoolean(value);
expect(result).toStrictEqual(true);
});
}
);
});

View File

@@ -0,0 +1,3 @@
export function isBoolean(value: unknown): value is boolean {
return value === true || value === false;
}

View File

@@ -26,6 +26,8 @@ export interface IIssuesProcessorOptions {
anyOfPrLabels: string;
operationsPerRun: number;
removeStaleWhenUpdated: boolean;
removeIssueStaleWhenUpdated: boolean | undefined;
removePrStaleWhenUpdated: boolean | undefined;
debugOnly: boolean;
ascending: boolean;
skipStaleIssueMessage: boolean;

View File

@@ -49,6 +49,12 @@ function _getAndValidateArgs(): IIssuesProcessorOptions {
removeStaleWhenUpdated: !(
core.getInput('remove-stale-when-updated') === 'false'
),
removeIssueStaleWhenUpdated: _toOptionalBoolean(
core.getInput('remove-issue-stale-when-updated')
),
removePrStaleWhenUpdated: _toOptionalBoolean(
core.getInput('remove-pr-stale-when-updated')
),
debugOnly: core.getInput('debug-only') === 'true',
ascending: core.getInput('ascending') === 'true',
skipStalePrMessage: core.getInput('skip-stale-pr-message') === 'true',