feat(stale-and-close): add new options to change the days before close (#224)

* docs(readme): add new options in the documentation

* chore: update the action schema

* chore: parse the new arguments

* feat(stale-and-close): add new options to change the days before close

to avoid a breaking change and simplify the configuration the old options 'daysBeforeStale' and 'daysBeforePrClose' are kept and new options are available to override them with 'daysBeforeIssueStale', 'daysBeforePrStale', 'daysBeforeIssueClose' and 'daysBeforePrClose'

* chore: rename the issue type enum to remove the enum suffix

* chore: add missing dependency for eslint and typescript

also upgrade the parser

* chore: fix an issue with the linter for the shadow rules

it was not configured properly for TypeScript

* chore: use camelCase for constants

* chore: use camelCase for enum members

* chore: fix the tests

* chore: enhance prettier to also lint other kind of files

it was configured to only work with ts and it was not working well to be honest
also now the lint scripts will also run prettier
This commit is contained in:
Geoffrey Testelin
2021-01-16 14:28:29 +01:00
committed by GitHub
parent b12dccced8
commit 552e4c60f0
19 changed files with 767 additions and 203 deletions

View File

@@ -1,8 +1,8 @@
import * as github from '@actions/github';
import {
IssueProcessor,
Issue,
IssueProcessor,
IssueProcessorOptions
} from '../src/IssueProcessor';
@@ -35,7 +35,11 @@ const DefaultProcessorOptions: IssueProcessorOptions = Object.freeze({
closeIssueMessage: 'This issue is being closed',
closePrMessage: 'This PR is being closed',
daysBeforeStale: 1,
daysBeforeIssueStale: NaN,
daysBeforePrStale: NaN,
daysBeforeClose: 30,
daysBeforeIssueClose: NaN,
daysBeforePrClose: NaN,
staleIssueLabel: 'Stale',
closeIssueLabel: '',
exemptIssueLabels: '',
@@ -73,8 +77,36 @@ test('processing an issue with no label will make it stale and close it, if it i
generateIssue(1, 'An issue with no label', '2020-01-01T17:00:00Z')
];
const opts = {...DefaultProcessorOptions};
opts.daysBeforeClose = 0;
const opts: IssueProcessorOptions = {
...DefaultProcessorOptions,
daysBeforeClose: 0
};
const processor = new IssueProcessor(
opts,
async () => 'abot',
async p => (p == 1 ? TestIssueList : []),
async (num, dt) => [],
async (issue, label) => new Date().toDateString()
);
// process our fake issue list
await processor.processIssues(1);
expect(processor.staleIssues.length).toEqual(1);
expect(processor.closedIssues.length).toEqual(1);
});
test('processing an issue with no label will make it stale and close it, if it is old enough only if days-before-close is set to > 0 and days-before-issue-close is set to 0', async () => {
const TestIssueList: Issue[] = [
generateIssue(1, 'An issue with no label', '2020-01-01T17:00:00Z')
];
const opts: IssueProcessorOptions = {
...DefaultProcessorOptions,
daysBeforeClose: 1,
daysBeforeIssueClose: 0
};
const processor = new IssueProcessor(
opts,
@@ -92,16 +124,70 @@ test('processing an issue with no label will make it stale and close it, if it i
expect(processor.deletedBranchIssues.length).toEqual(0);
});
test('processing an issue with no label will make it stale and not close it, if it is old enough only if days-before-close is set to > 0 and days-before-issue-close is set to > 0', async () => {
const TestIssueList: Issue[] = [
generateIssue(1, 'An issue with no label', '2020-01-01T17:00:00Z')
];
const opts: IssueProcessorOptions = {
...DefaultProcessorOptions,
daysBeforeClose: 1,
daysBeforeIssueClose: 1
};
const processor = new IssueProcessor(
opts,
async () => 'abot',
async p => (p == 1 ? TestIssueList : []),
async (num, dt) => [],
async (issue, label) => new Date().toDateString()
);
// process our fake issue list
await processor.processIssues(1);
expect(processor.staleIssues.length).toEqual(1);
expect(processor.closedIssues.length).toEqual(0);
});
test('processing an issue with no label will make it stale and not close it if days-before-close is set to > 0', async () => {
const TestIssueList: Issue[] = [
generateIssue(1, 'An issue with no label', '2020-01-01T17:00:00Z')
];
const opts = {...DefaultProcessorOptions};
opts.daysBeforeClose = 15;
const opts: IssueProcessorOptions = {
...DefaultProcessorOptions,
daysBeforeClose: 15
};
const processor = new IssueProcessor(
DefaultProcessorOptions,
opts,
async () => 'abot',
async p => (p == 1 ? TestIssueList : []),
async (num, dt) => [],
async (issue, label) => new Date().toDateString()
);
// process our fake issue list
await processor.processIssues(1);
expect(processor.staleIssues.length).toEqual(1);
expect(processor.closedIssues.length).toEqual(0);
});
test('processing an issue with no label will make it stale and not close it if days-before-close is set to -1 and days-before-issue-close is set to > 0', async () => {
const TestIssueList: Issue[] = [
generateIssue(1, 'An issue with no label', '2020-01-01T17:00:00Z')
];
const opts: IssueProcessorOptions = {
...DefaultProcessorOptions,
daysBeforeClose: -1,
daysBeforeIssueClose: 15
};
const processor = new IssueProcessor(
opts,
async () => 'abot',
async p => (p == 1 ? TestIssueList : []),
async (num, dt) => [],
@@ -120,7 +206,7 @@ test('processing an issue with no label will not make it stale if days-before-st
generateIssue(1, 'An issue with no label', '2020-01-01T17:00:00Z')
];
const opts = {
const opts: IssueProcessorOptions = {
...DefaultProcessorOptions,
staleIssueMessage: '',
daysBeforeStale: -1
@@ -141,6 +227,33 @@ test('processing an issue with no label will not make it stale if days-before-st
expect(processor.closedIssues.length).toEqual(0);
});
test('processing an issue with no label will not make it stale if days-before-stale and days-before-issue-stale are set to -1', async () => {
const TestIssueList: Issue[] = [
generateIssue(1, 'An issue with no label', '2020-01-01T17:00:00Z')
];
const opts: IssueProcessorOptions = {
...DefaultProcessorOptions,
staleIssueMessage: '',
daysBeforeStale: -1,
daysBeforeIssueStale: -1
};
const processor = new IssueProcessor(
opts,
async () => 'abot',
async p => (p == 1 ? TestIssueList : []),
async (num, dt) => [],
async (issue, label) => new Date().toDateString()
);
// process our fake issue list
await processor.processIssues(1);
expect(processor.staleIssues.length).toEqual(0);
expect(processor.closedIssues.length).toEqual(0);
});
test('processing an issue with no label will make it stale but not close it', async () => {
// issue should be from 2 days ago so it will be
// stale but not close-able, based on default settings
@@ -177,8 +290,13 @@ test('processing a stale issue will close it', async () => {
)
];
const opts: IssueProcessorOptions = {
...DefaultProcessorOptions,
daysBeforeClose: 30
};
const processor = new IssueProcessor(
DefaultProcessorOptions,
opts,
async () => 'abot',
async p => (p == 1 ? TestIssueList : []),
async (num, dt) => [],
@@ -254,6 +372,38 @@ test('processing a stale issue containing a slash in the label will close it', a
expect(processor.closedIssues.length).toEqual(1);
});
test('processing a stale issue will close it when days-before-issue-stale override days-before-stale', async () => {
const TestIssueList: Issue[] = [
generateIssue(
1,
'A stale issue that should be closed',
'2020-01-01T17:00:00Z',
false,
['Stale']
)
];
const opts: IssueProcessorOptions = {
...DefaultProcessorOptions,
daysBeforeClose: 30,
daysBeforeIssueStale: 30
};
const processor = new IssueProcessor(
opts,
async () => 'abot',
async p => (p == 1 ? TestIssueList : []),
async (num, dt) => [],
async (issue, label) => new Date().toDateString()
);
// process our fake issue list
await processor.processIssues(1);
expect(processor.staleIssues.length).toEqual(0);
expect(processor.closedIssues.length).toEqual(1);
});
test('processing a stale PR will close it', async () => {
const TestIssueList: Issue[] = [
generateIssue(
@@ -265,8 +415,45 @@ test('processing a stale PR will close it', async () => {
)
];
const opts: IssueProcessorOptions = {
...DefaultProcessorOptions,
daysBeforeClose: 30
};
const processor = new IssueProcessor(
DefaultProcessorOptions,
opts,
async () => 'abot',
async p => (p == 1 ? TestIssueList : []),
async (num, dt) => [],
async (issue, label) => new Date().toDateString()
);
// process our fake issue list
await processor.processIssues(1);
expect(processor.staleIssues.length).toEqual(0);
expect(processor.closedIssues.length).toEqual(1);
});
test('processing a stale PR will close it when days-before-pr-stale override days-before-stale', async () => {
const TestIssueList: Issue[] = [
generateIssue(
1,
'A stale PR that should be closed',
'2020-01-01T17:00:00Z',
true,
['Stale']
)
];
const opts: IssueProcessorOptions = {
...DefaultProcessorOptions,
daysBeforeClose: 30,
daysBeforePrClose: 30
};
const processor = new IssueProcessor(
opts,
async () => 'abot',
async p => (p == 1 ? TestIssueList : []),
async (num, dt) => [],
@@ -308,6 +495,35 @@ test('processing a stale issue will close it even if configured not to mark as s
expect(processor.closedIssues.length).toEqual(1);
});
test('processing a stale issue will close it even if configured not to mark as stale when days-before-issue-stale override days-before-stale', async () => {
const TestIssueList: Issue[] = [
generateIssue(1, 'An issue with no label', '2020-01-01T17:00:00Z', false, [
'Stale'
])
];
const opts = {
...DefaultProcessorOptions,
daysBeforeStale: 0,
daysBeforeIssueStale: -1,
staleIssueMessage: ''
};
const processor = new IssueProcessor(
opts,
async () => 'abot',
async p => (p == 1 ? TestIssueList : []),
async (num, dt) => [],
async (issue, label) => new Date().toDateString()
);
// process our fake issue list
await processor.processIssues(1);
expect(processor.staleIssues.length).toEqual(0);
expect(processor.closedIssues.length).toEqual(1);
});
test('processing a stale PR will close it even if configured not to mark as stale', async () => {
const TestIssueList: Issue[] = [
generateIssue(1, 'An issue with no label', '2020-01-01T17:00:00Z', true, [
@@ -336,6 +552,35 @@ test('processing a stale PR will close it even if configured not to mark as stal
expect(processor.closedIssues.length).toEqual(1);
});
test('processing a stale PR will close it even if configured not to mark as stale when days-before-pr-stale override days-before-stale', async () => {
const TestIssueList: Issue[] = [
generateIssue(1, 'An issue with no label', '2020-01-01T17:00:00Z', true, [
'Stale'
])
];
const opts = {
...DefaultProcessorOptions,
daysBeforeStale: 0,
daysBeforePrStale: -1,
stalePrMessage: ''
};
const processor = new IssueProcessor(
opts,
async () => 'abot',
async p => (p == 1 ? TestIssueList : []),
async (num, dt) => [],
async (issue, label) => new Date().toDateString()
);
// process our fake issue list
await processor.processIssues(1);
expect(processor.staleIssues.length).toEqual(0);
expect(processor.closedIssues.length).toEqual(1);
});
test('closed issues will not be marked stale', async () => {
const TestIssueList: Issue[] = [
generateIssue(
@@ -692,7 +937,14 @@ test('stale label should be removed if a comment was added to a stale issue', as
opts,
async () => 'abot',
async p => (p == 1 ? TestIssueList : []),
async (num: number, dt: string) => [{user: {login: 'notme', type: 'User'}}], // return a fake comment to indicate there was an update
async (num: number, dt: string) => [
{
user: {
login: 'notme',
type: 'User'
}
}
], // return a fake comment to indicate there was an update
async (issue: Issue, label: string) => new Date().toDateString()
);
@@ -723,7 +975,14 @@ test('stale label should not be removed if a comment was added by the bot (and t
opts,
async () => 'abot',
async p => (p == 1 ? TestIssueList : []),
async (num: number, dt: string) => [{user: {login: 'abot', type: 'User'}}], // return a fake comment to indicate there was an update by the bot
async (num: number, dt: string) => [
{
user: {
login: 'abot',
type: 'User'
}
}
], // return a fake comment to indicate there was an update by the bot
async (issue: Issue, label: string) => new Date().toDateString()
);