mirror of
https://github.com/actions/stale.git
synced 2025-12-11 12:37:27 +00:00
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:
committed by
GitHub
parent
043fbbdea3
commit
440fb174b5
@@ -35,6 +35,8 @@ describe('Issue', (): void => {
|
||||
anyOfPrLabels: '',
|
||||
operationsPerRun: 0,
|
||||
removeStaleWhenUpdated: false,
|
||||
removeIssueStaleWhenUpdated: undefined,
|
||||
removePrStaleWhenUpdated: undefined,
|
||||
repoToken: '',
|
||||
skipStaleIssueMessage: false,
|
||||
skipStalePrMessage: false,
|
||||
|
||||
@@ -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);
|
||||
|
||||
29
src/functions/is-boolean.spec.ts
Normal file
29
src/functions/is-boolean.spec.ts
Normal 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);
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
3
src/functions/is-boolean.ts
Normal file
3
src/functions/is-boolean.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export function isBoolean(value: unknown): value is boolean {
|
||||
return value === true || value === false;
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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',
|
||||
|
||||
Reference in New Issue
Block a user