feat(close-label): automatically remove close-label when no longer closed nor locked (#334)
* feat(assignees): add new option to avoid stale for assignees closes #271 * test: add more coverage * docs: fix readme format issue * docs: reorder and enhance typo * docs(contributing): add more information about the npm scripts * docs(readme): update the default values to reflect the real applied ones * feat(close-label): automatically remove it when no longer closed nor locked closes #278
This commit is contained in:
parent
ec96ff65b0
commit
836169b81a
|
@ -17,10 +17,10 @@ Warns and then closes issues and PRs that have had no activity for a specified a
|
|||
| `stale-pr-message` | Message to post on the stale PR. | Optional |
|
||||
| `close-issue-message` | Message to post on the stale issue while closing it. | Optional |
|
||||
| `close-pr-message` | Message to post on the stale PR while closing it. | Optional |
|
||||
| `stale-issue-label` | Label to apply on the stale issue. _Defaults to **stale**_ | Optional |
|
||||
| `close-issue-label` | Label to apply on closing issue. | Optional |
|
||||
| `stale-pr-label` | Label to apply on the stale PR. | Optional |
|
||||
| `close-pr-label` | Label to apply on the closing PR. | Optional |
|
||||
| `stale-issue-label` | Label to apply on the stale issue. _Defaults to **Stale**_ | Optional |
|
||||
| `close-issue-label` | Label to apply on closing issue (automatically removed if no longer closed nor locked). | Optional |
|
||||
| `stale-pr-label` | Label to apply on the stale PR. _Defaults to **Stale**_ | Optional |
|
||||
| `close-pr-label` | Label to apply on the closing PR (automatically removed if no longer closed nor locked). | Optional |
|
||||
| `exempt-issue-labels` | Labels on an issue exempted from being marked as stale. | Optional |
|
||||
| `exempt-pr-labels` | Labels on the PR exempted from being marked as stale. | Optional |
|
||||
| `only-labels` | Only labels checked for stale issue/PR. | Optional |
|
||||
|
|
|
@ -2112,3 +2112,111 @@ test('processing a pull request opened since 2 days and with the option "daysBef
|
|||
expect(processor.staleIssues.length).toEqual(1);
|
||||
expect(processor.closedIssues.length).toEqual(0);
|
||||
});
|
||||
|
||||
test('processing a previously closed issue with a close label will remove the close label', async () => {
|
||||
expect.assertions(1);
|
||||
const opts: IIssuesProcessorOptions = {
|
||||
...DefaultProcessorOptions,
|
||||
closeIssueLabel: 'close',
|
||||
staleIssueLabel: 'stale'
|
||||
};
|
||||
const now: Date = new Date();
|
||||
const oneWeekAgo: Date = new Date(now.getDate() - 7);
|
||||
const TestIssueList: Issue[] = [
|
||||
generateIssue(
|
||||
opts,
|
||||
1,
|
||||
'An opened issue with a close label',
|
||||
oneWeekAgo.toDateString(),
|
||||
now.toDateString(),
|
||||
false,
|
||||
['close'],
|
||||
false,
|
||||
false
|
||||
)
|
||||
];
|
||||
const processor = new IssuesProcessor(
|
||||
opts,
|
||||
async () => 'abot',
|
||||
async p => (p === 1 ? TestIssueList : []),
|
||||
async () => [],
|
||||
async () => new Date().toDateString()
|
||||
);
|
||||
|
||||
// process our fake issue list
|
||||
await processor.processIssues(1);
|
||||
|
||||
expect(processor.removedLabelIssues).toHaveLength(1);
|
||||
});
|
||||
|
||||
test('processing a closed issue with a close label will not remove the close label', async () => {
|
||||
expect.assertions(1);
|
||||
const opts: IIssuesProcessorOptions = {
|
||||
...DefaultProcessorOptions,
|
||||
closeIssueLabel: 'close',
|
||||
staleIssueLabel: 'stale'
|
||||
};
|
||||
const now: Date = new Date();
|
||||
const oneWeekAgo: Date = new Date(now.getDate() - 7);
|
||||
const TestIssueList: Issue[] = [
|
||||
generateIssue(
|
||||
opts,
|
||||
1,
|
||||
'A closed issue with a close label',
|
||||
oneWeekAgo.toDateString(),
|
||||
now.toDateString(),
|
||||
false,
|
||||
['close'],
|
||||
true,
|
||||
false
|
||||
)
|
||||
];
|
||||
const processor = new IssuesProcessor(
|
||||
opts,
|
||||
async () => 'abot',
|
||||
async p => (p === 1 ? TestIssueList : []),
|
||||
async () => [],
|
||||
async () => new Date().toDateString()
|
||||
);
|
||||
|
||||
// process our fake issue list
|
||||
await processor.processIssues(1);
|
||||
|
||||
expect(processor.removedLabelIssues).toHaveLength(0);
|
||||
});
|
||||
|
||||
test('processing a locked issue with a close label will not remove the close label', async () => {
|
||||
expect.assertions(1);
|
||||
const opts: IIssuesProcessorOptions = {
|
||||
...DefaultProcessorOptions,
|
||||
closeIssueLabel: 'close',
|
||||
staleIssueLabel: 'stale'
|
||||
};
|
||||
const now: Date = new Date();
|
||||
const oneWeekAgo: Date = new Date(now.getDate() - 7);
|
||||
const TestIssueList: Issue[] = [
|
||||
generateIssue(
|
||||
opts,
|
||||
1,
|
||||
'A closed issue with a close label',
|
||||
oneWeekAgo.toDateString(),
|
||||
now.toDateString(),
|
||||
false,
|
||||
['close'],
|
||||
false,
|
||||
true
|
||||
)
|
||||
];
|
||||
const processor = new IssuesProcessor(
|
||||
opts,
|
||||
async () => 'abot',
|
||||
async p => (p === 1 ? TestIssueList : []),
|
||||
async () => [],
|
||||
async () => new Date().toDateString()
|
||||
);
|
||||
|
||||
// process our fake issue list
|
||||
await processor.processIssues(1);
|
||||
|
||||
expect(processor.removedLabelIssues).toHaveLength(0);
|
||||
});
|
||||
|
|
|
@ -299,6 +299,8 @@ class IssuesProcessor {
|
|||
issueLogger.info(`Skipping $$type because it is locked`);
|
||||
continue; // don't process locked issues
|
||||
}
|
||||
// Try to remove the close label when not close/locked issue or PR
|
||||
yield this._removeCloseLabel(issue, closeLabel);
|
||||
if (this.options.startDate) {
|
||||
const startDate = new Date(this.options.startDate);
|
||||
const createdAt = new Date(issue.created_at);
|
||||
|
@ -677,10 +679,24 @@ class IssuesProcessor {
|
|||
_removeStaleLabel(issue, staleLabel) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const issueLogger = new issue_logger_1.IssueLogger(issue);
|
||||
issueLogger.info(`$$type is no longer stale. Removing stale label.`);
|
||||
issueLogger.info(`The $$type is no longer stale. Removing the stale label...`);
|
||||
return this._removeLabel(issue, staleLabel);
|
||||
});
|
||||
}
|
||||
_removeCloseLabel(issue, closeLabel) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const issueLogger = new issue_logger_1.IssueLogger(issue);
|
||||
issueLogger.info(`The $$type is not closed nor locked. Trying to remove the close label...`);
|
||||
if (!closeLabel) {
|
||||
issueLogger.info(`There is no close label on this $$type. Skip`);
|
||||
return Promise.resolve();
|
||||
}
|
||||
if (is_labeled_1.isLabeled(issue, closeLabel)) {
|
||||
issueLogger.info(`The $$type has a close label "${closeLabel}". Removing the close label...`);
|
||||
return this._removeLabel(issue, closeLabel);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
exports.IssuesProcessor = IssuesProcessor;
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ export class Issue implements IIssue {
|
|||
updated_at: IsoDateString;
|
||||
readonly labels: ILabel[];
|
||||
readonly pull_request: Object | null | undefined;
|
||||
readonly state: string;
|
||||
readonly state: string | 'closed' | 'open';
|
||||
readonly locked: boolean;
|
||||
readonly milestone: IMilestone | undefined;
|
||||
readonly assignees: IAssignee[];
|
||||
|
|
|
@ -140,6 +140,9 @@ export class IssuesProcessor {
|
|||
continue; // don't process locked issues
|
||||
}
|
||||
|
||||
// Try to remove the close label when not close/locked issue or PR
|
||||
await this._removeCloseLabel(issue, closeLabel);
|
||||
|
||||
if (this.options.startDate) {
|
||||
const startDate: Date = new Date(this.options.startDate);
|
||||
const createdAt: Date = new Date(issue.created_at);
|
||||
|
@ -663,8 +666,35 @@ export class IssuesProcessor {
|
|||
): Promise<void> {
|
||||
const issueLogger: IssueLogger = new IssueLogger(issue);
|
||||
|
||||
issueLogger.info(`$$type is no longer stale. Removing stale label.`);
|
||||
issueLogger.info(
|
||||
`The $$type is no longer stale. Removing the stale label...`
|
||||
);
|
||||
|
||||
return this._removeLabel(issue, staleLabel);
|
||||
}
|
||||
|
||||
private async _removeCloseLabel(
|
||||
issue: Issue,
|
||||
closeLabel: Readonly<string | undefined>
|
||||
): Promise<void> {
|
||||
const issueLogger: IssueLogger = new IssueLogger(issue);
|
||||
|
||||
issueLogger.info(
|
||||
`The $$type is not closed nor locked. Trying to remove the close label...`
|
||||
);
|
||||
|
||||
if (!closeLabel) {
|
||||
issueLogger.info(`There is no close label on this $$type. Skip`);
|
||||
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
if (isLabeled(issue, closeLabel)) {
|
||||
issueLogger.info(
|
||||
`The $$type has a close label "${closeLabel}". Removing the close label...`
|
||||
);
|
||||
|
||||
return this._removeLabel(issue, closeLabel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue