diff --git a/__tests__/any-of-labels.spec.ts b/__tests__/any-of-labels.spec.ts index 39734b30c..63cee5d46 100644 --- a/__tests__/any-of-labels.spec.ts +++ b/__tests__/any-of-labels.spec.ts @@ -1141,7 +1141,9 @@ class IssuesProcessorBuilder { this._options, async p => (p === 1 ? this._issues : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); } } diff --git a/__tests__/assignees.spec.ts b/__tests__/assignees.spec.ts index 86c453498..fe6f61520 100644 --- a/__tests__/assignees.spec.ts +++ b/__tests__/assignees.spec.ts @@ -50,7 +50,9 @@ describe('assignees options', (): void => { opts, async p => (p === 1 ? testIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); }; diff --git a/__tests__/classes/issues-processor-mock.ts b/__tests__/classes/issues-processor-mock.ts index 0ef05ed2a..7f534c1d7 100644 --- a/__tests__/classes/issues-processor-mock.ts +++ b/__tests__/classes/issues-processor-mock.ts @@ -1,6 +1,7 @@ import {Issue} from '../../src/classes/issue'; import {IssuesProcessor} from '../../src/classes/issues-processor'; import {IComment} from '../../src/interfaces/comment'; +import { IIssueEvent } from '../../src/interfaces/issue-event'; import {IIssuesProcessorOptions} from '../../src/interfaces/issues-processor-options'; import {IPullRequest} from '../../src/interfaces/pull-request'; @@ -13,10 +14,12 @@ export class IssuesProcessorMock extends IssuesProcessor { sinceDate: string ) => Promise, getLabelCreationDate?: ( + events: IIssueEvent[], issue: Issue, label: string - ) => Promise, - getPullRequest?: (issue: Issue) => Promise + ) => string | undefined, + getPullRequest?: (issue: Issue) => Promise, + getIssueEvents?: (issue: Issue) => Promise ) { super(options); @@ -35,5 +38,9 @@ export class IssuesProcessorMock extends IssuesProcessor { if (getPullRequest) { this.getPullRequest = getPullRequest; } + + if (getIssueEvents) { + this.getIssueEvents = getIssueEvents; + } } } diff --git a/__tests__/exempt-draft-pr.spec.ts b/__tests__/exempt-draft-pr.spec.ts index 7291f5a06..2ee470327 100644 --- a/__tests__/exempt-draft-pr.spec.ts +++ b/__tests__/exempt-draft-pr.spec.ts @@ -124,7 +124,7 @@ class IssuesProcessorBuilder { this._options, async p => (p === 1 ? this._issues : []), async () => [], - async () => new Date().toDateString(), + () => new Date().toDateString(), async (): Promise => { return Promise.resolve({ number: 0, @@ -134,7 +134,8 @@ class IssuesProcessorBuilder { repo: null } }); - } + }, + async () => [] ); } } diff --git a/__tests__/main.spec.ts b/__tests__/main.spec.ts index 0675a5b7f..c6ab1383a 100644 --- a/__tests__/main.spec.ts +++ b/__tests__/main.spec.ts @@ -18,7 +18,9 @@ test('processing an issue with no label will make it stale and close it, if it i opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -49,7 +51,9 @@ test('processing an issue with no label and a start date as ECMAScript epoch in opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -80,7 +84,9 @@ test('processing an issue with no label and a start date as ECMAScript epoch in opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -111,7 +117,9 @@ test('processing an issue with no label and a start date as ECMAScript epoch in opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -142,7 +150,9 @@ test('processing an issue with no label and a start date as ECMAScript epoch in opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -173,7 +183,9 @@ test('processing an issue with no label and a start date as ISO 8601 being befor opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -204,7 +216,9 @@ test('processing an issue with no label and a start date as ISO 8601 being after opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -235,7 +249,9 @@ test('processing an issue with no label and a start date as RFC 2822 being befor opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -266,7 +282,9 @@ test('processing an issue with no label and a start date as RFC 2822 being after opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -289,7 +307,9 @@ test('processing an issue with no label will make it stale and close it, if it i opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -313,7 +333,9 @@ test('processing an issue with no label will make it stale and not close it, if opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -335,7 +357,9 @@ test('processing an issue with no label will make it stale and not close it if d opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -358,7 +382,9 @@ test('processing an issue with no label will make it stale and not close it if d opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -381,7 +407,9 @@ test('processing an issue with no label will not make it stale if days-before-st opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -405,7 +433,9 @@ test('processing an issue with no label will not make it stale if days-before-st opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -432,7 +462,9 @@ test('processing an issue with no label will make it stale but not close it', as DefaultProcessorOptions, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -462,7 +494,9 @@ test('processing a stale issue will close it', async () => { opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -492,7 +526,9 @@ test('processing a stale issue containing a space in the label will close it', a opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -522,7 +558,9 @@ test('processing a stale issue containing a slash in the label will close it', a opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -553,7 +591,9 @@ test('processing a stale issue will close it when days-before-issue-stale overri opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -583,7 +623,9 @@ test('processing a stale PR will close it', async () => { opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -614,7 +656,9 @@ test('processing a stale PR will close it when days-before-pr-stale override day opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -645,7 +689,9 @@ test('processing a stale issue will close it even if configured not to mark as s opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -677,7 +723,9 @@ test('processing a stale issue will close it even if configured not to mark as s opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -708,7 +756,9 @@ test('processing a stale PR will close it even if configured not to mark as stal opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -740,7 +790,9 @@ test('processing a stale PR will close it even if configured not to mark as stal opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -766,6 +818,9 @@ test('closed issues will not be marked stale', async () => { const processor = new IssuesProcessorMock( DefaultProcessorOptions, async p => (p === 1 ? TestIssueList : []), + async () => [], + () => new Date().toDateString(), + async () => undefined, async () => [] ); @@ -793,7 +848,9 @@ test('stale closed issues will not be closed', async () => { DefaultProcessorOptions, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -820,7 +877,9 @@ test('closed prs will not be marked stale', async () => { DefaultProcessorOptions, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -847,7 +906,9 @@ test('stale closed prs will not be closed', async () => { DefaultProcessorOptions, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -872,7 +933,11 @@ test('locked issues will not be marked stale', async () => { ) ]; const processor = new IssuesProcessorMock(DefaultProcessorOptions, async p => - p === 1 ? TestIssueList : [] + p === 1 ? TestIssueList : [], + async () => [], + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -900,7 +965,9 @@ test('stale locked issues will not be closed', async () => { DefaultProcessorOptions, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -924,8 +991,13 @@ test('locked prs will not be marked stale', async () => { true ) ]; - const processor = new IssuesProcessorMock(DefaultProcessorOptions, async p => - p === 1 ? TestIssueList : [] + const processor = new IssuesProcessorMock( + DefaultProcessorOptions, + async p => p === 1 ? TestIssueList : [], + async () => [], + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -953,7 +1025,9 @@ test('stale locked prs will not be closed', async () => { DefaultProcessorOptions, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -982,7 +1056,9 @@ test('exempt issue labels will not be marked stale', async () => { opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -1011,7 +1087,9 @@ test('exempt issue labels will not be marked stale (multi issue label with space opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -1039,7 +1117,9 @@ test('exempt issue labels will not be marked stale (multi issue label)', async ( opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -1085,7 +1165,9 @@ test('exempt pr labels will not be marked stale', async () => { opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -1130,7 +1212,9 @@ test('stale issues should not be closed if days is set to -1', async () => { opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -1165,7 +1249,9 @@ test('stale label should be removed if a comment was added to a stale issue', as body: 'Body' } ], // return a fake comment to indicate there was an update - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -1206,7 +1292,9 @@ test('when the option "labelsToAddWhenUnstale" is set, the labels should be adde body: 'Body' } ], // return a fake comment to indicate there was an update - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -1250,7 +1338,9 @@ test('when the option "labelsToRemoveWhenStale" is set, the labels should be rem body: 'Body' } ], // return a fake comment to indicate there was an update - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -1288,7 +1378,9 @@ test('stale label should not be removed if a comment was added by the bot (and t body: 'This issue is stale' } ], // return a fake comment to indicate there was an update by the bot - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -1320,7 +1412,9 @@ test('stale label containing a space should be removed if a comment was added to opts, async p => (p === 1 ? TestIssueList : []), async () => [{user: {login: 'notme', type: 'User'}, body: 'Body'}], // return a fake comment to indicate there was an update - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -1351,7 +1445,9 @@ test('stale issues should not be closed until after the closed number of days', opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -1383,7 +1479,9 @@ test('stale issues should be closed if the closed nubmer of days (additive) is a opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -1414,7 +1512,9 @@ test('stale issues should not be closed until after the closed number of days (l opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -1446,7 +1546,9 @@ test('skips stale message on issues when stale-issue-message is empty', async () opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // for sake of testing, mocking private function @@ -1490,7 +1592,9 @@ test('send stale message on issues when stale-issue-message is not empty', async opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // for sake of testing, mocking private function @@ -1534,7 +1638,9 @@ test('skips stale message on prs when stale-pr-message is empty', async () => { opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // for sake of testing, mocking private function @@ -1578,7 +1684,9 @@ test('send stale message on prs when stale-pr-message is not empty', async () => opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // for sake of testing, mocking private function @@ -1619,7 +1727,9 @@ test('git branch is deleted when option is enabled', async () => { opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); await processor.processIssues(1); @@ -1648,7 +1758,9 @@ test('git branch is not deleted when issue is not pull request', async () => { opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); await processor.processIssues(1); @@ -1679,7 +1791,9 @@ test('an issue without a milestone will be marked as stale', async () => { DefaultProcessorOptions, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -1712,7 +1826,9 @@ test('an issue without an exempted milestone will be marked as stale', async () opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -1745,7 +1861,9 @@ test('an issue with an exempted milestone will not be marked as stale', async () opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -1778,7 +1896,9 @@ test('an issue with an exempted milestone will not be marked as stale (multi mil opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -1811,7 +1931,9 @@ test('an issue with an exempted milestone will not be marked as stale (multi mil opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -1845,7 +1967,9 @@ test('an issue with an exempted milestone but without an exempted issue mileston opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -1879,7 +2003,9 @@ test('an issue with an exempted milestone but with another exempted issue milest opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -1913,7 +2039,9 @@ test('an issue with an exempted milestone and with an exempted issue milestone w opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -1940,7 +2068,9 @@ test('processing an issue opened since 2 days and with the option "daysBeforeIss opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -1966,7 +2096,9 @@ test('processing an issue opened since 2 days and with the option "daysBeforeIss opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -1992,7 +2124,9 @@ test('processing an issue opened since 2 days and with the option "daysBeforeIss opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -2018,7 +2152,9 @@ test('processing an issue opened since 1 hour and with the option "daysBeforeIss opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toISOString() + () => new Date().toISOString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -2044,7 +2180,9 @@ test('processing an issue opened since 4 hours and with the option "daysBeforeIs opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toISOString() + () => new Date().toISOString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -2070,7 +2208,9 @@ test('processing an issue opened since 5 hours and with the option "daysBeforeIs opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toISOString() + () => new Date().toISOString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -2103,7 +2243,9 @@ test('processing a pull request opened since 2 days and with the option "daysBef opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -2136,7 +2278,9 @@ test('processing a pull request opened since 2 days and with the option "daysBef opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -2169,7 +2313,9 @@ test('processing a pull request opened since 2 days and with the option "daysBef opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -2202,7 +2348,9 @@ test('processing a pull request opened since 1 hour and with the option "daysBef opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toISOString() + () => new Date().toISOString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -2235,7 +2383,9 @@ test('processing a pull request opened since 4 hours and with the option "daysBe opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toISOString() + () => new Date().toISOString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -2268,7 +2418,9 @@ test('processing a pull request opened since 5 hours and with the option "daysBe opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toISOString() + () => new Date().toISOString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -2304,7 +2456,9 @@ test('processing a previously closed issue with a close label will remove the cl opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -2339,7 +2493,9 @@ test('processing a closed issue with a close label will not remove the close lab opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -2374,7 +2530,9 @@ test('processing a locked issue with a close label will not remove the close lab opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -2413,7 +2571,9 @@ test('processing an issue stale since less than the daysBeforeStale with a stale opts, async p => (p === 1 ? TestIssueList : []), async (): Promise => Promise.resolve([]), - async () => labelCreatedAt.toDateString() + () => labelCreatedAt.toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -2453,7 +2613,9 @@ test('processing an issue stale since less than the daysBeforeStale without a st opts, async p => (p === 1 ? TestIssueList : []), async (): Promise => Promise.resolve([]), - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -2488,7 +2650,9 @@ test('processing a pull request to be stale with the "stalePrMessage" option set opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -2523,7 +2687,9 @@ test('processing a pull request to be stale with the "stalePrMessage" option set opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -2563,7 +2729,9 @@ test('processing an issue with the "includeOnlyAssigned" option and nonempty ass opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list @@ -2590,7 +2758,9 @@ test('processing an issue with the "includeOnlyAssigned" option set and no assig opts, async p => (p === 1 ? TestIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); // process our fake issue list diff --git a/__tests__/milestones.spec.ts b/__tests__/milestones.spec.ts index 3483d59da..a54fa9ee1 100644 --- a/__tests__/milestones.spec.ts +++ b/__tests__/milestones.spec.ts @@ -41,7 +41,9 @@ describe('milestones options', (): void => { opts, async p => (p === 1 ? testIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); }; diff --git a/__tests__/only-labels.spec.ts b/__tests__/only-labels.spec.ts index d1f070f34..67856d201 100644 --- a/__tests__/only-labels.spec.ts +++ b/__tests__/only-labels.spec.ts @@ -1141,7 +1141,9 @@ class IssuesProcessorBuilder { this._options, async p => (p === 1 ? this._issues : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); } } diff --git a/__tests__/operations-per-run.spec.ts b/__tests__/operations-per-run.spec.ts index f42397c93..64df926fa 100644 --- a/__tests__/operations-per-run.spec.ts +++ b/__tests__/operations-per-run.spec.ts @@ -207,7 +207,9 @@ class SUT { this._opts, async p => (p === 1 ? this._testIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); return this.processor.processIssues(1); diff --git a/__tests__/remove-stale-when-updated.spec.ts b/__tests__/remove-stale-when-updated.spec.ts index 98092d801..cf742a385 100644 --- a/__tests__/remove-stale-when-updated.spec.ts +++ b/__tests__/remove-stale-when-updated.spec.ts @@ -549,7 +549,9 @@ class IssuesProcessorBuilder { body: 'body' } ], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); } } diff --git a/__tests__/updates-reset-stale.spec.ts b/__tests__/updates-reset-stale.spec.ts index 11865ecf1..fa258c972 100644 --- a/__tests__/updates-reset-stale.spec.ts +++ b/__tests__/updates-reset-stale.spec.ts @@ -688,7 +688,9 @@ class SUT { this._opts, async p => (p === 1 ? this._testIssueList : []), async () => [], - async () => new Date().toDateString() + () => new Date().toDateString(), + async () => undefined, + async () => [] ); return this.processor.processIssues(1); diff --git a/dist/index.js b/dist/index.js index 6937fa60b..bc65b05f8 100644 --- a/dist/index.js +++ b/dist/index.js @@ -447,12 +447,25 @@ class IssuesProcessor { return this.processIssues(page + 1); }); } + getIssueEvents(issue) { + return __awaiter(this, void 0, void 0, function* () { + const options = this.client.rest.issues.listEvents.endpoint.merge({ + owner: github_1.context.repo.owner, + repo: github_1.context.repo.repo, + per_page: 100, + issue_number: issue.number + }); + const events = yield this.client.paginate(options); + return events.reverse(); + }); + } processIssue(issue, labelsToAddWhenUnstale, labelsToRemoveWhenUnstale, labelsToRemoveWhenStale) { var _a; return __awaiter(this, void 0, void 0, function* () { (_a = this.statistics) === null || _a === void 0 ? void 0 : _a.incrementProcessedItemsCount(issue); const issueLogger = new issue_logger_1.IssueLogger(issue); issueLogger.info(`Found this $$type last updated at: ${logger_service_1.LoggerService.cyan(issue.updated_at)}`); + const events = yield this.getIssueEvents(issue); // calculate string based messages for this issue const staleMessage = issue.isPullRequest ? this.options.stalePrMessage @@ -472,6 +485,12 @@ class IssuesProcessor { const daysBeforeStale = issue.isPullRequest ? this._getDaysBeforePrStale() : this._getDaysBeforeIssueStale(); + const isPinned = this.getPinnedStatus(events); + if (isPinned) { + issueLogger.info('Skipping this issue because it is pinned'); + IssuesProcessor._endIssueProcessing(issue); + return; // Don't process pinned issues + } if (issue.state === 'closed') { issueLogger.info(`Skipping this $$type because it is closed`); IssuesProcessor._endIssueProcessing(issue); @@ -627,7 +646,7 @@ class IssuesProcessor { // Process the issue if it was marked stale if (issue.isStale) { issueLogger.info(`This $$type is already stale`); - yield this._processStaleIssue(issue, staleLabel, staleMessage, labelsToAddWhenUnstale, labelsToRemoveWhenUnstale, labelsToRemoveWhenStale, closeMessage, closeLabel); + yield this._processStaleIssue(issue, staleLabel, staleMessage, labelsToAddWhenUnstale, labelsToRemoveWhenUnstale, labelsToRemoveWhenStale, events, closeMessage, closeLabel); } IssuesProcessor._endIssueProcessing(issue); }); @@ -676,31 +695,29 @@ class IssuesProcessor { } }); } + getPinnedStatus(events) { + const pinnedEvent = events.find(event => event.event === 'pinned'); + const unpinnedEvent = events.find(event => event.event === 'unpinned'); + if (pinnedEvent) { + return !unpinnedEvent || new Date(pinnedEvent.created_at) > new Date(unpinnedEvent === null || unpinnedEvent === void 0 ? void 0 : unpinnedEvent.created_at); + } + return false; + } // returns the creation date of a given label on an issue (or nothing if no label existed) ///see https://developer.github.com/v3/activity/events/ - getLabelCreationDate(issue, label) { + getLabelCreationDate(events, issue, label) { var _a; - return __awaiter(this, void 0, void 0, function* () { - const issueLogger = new issue_logger_1.IssueLogger(issue); - issueLogger.info(`Checking for label on this $$type`); - this._consumeIssueOperation(issue); - (_a = this.statistics) === null || _a === void 0 ? void 0 : _a.incrementFetchedItemsEventsCount(); - const options = this.client.rest.issues.listEvents.endpoint.merge({ - owner: github_1.context.repo.owner, - repo: github_1.context.repo.repo, - per_page: 100, - issue_number: issue.number - }); - const events = yield this.client.paginate(options); - const reversedEvents = events.reverse(); - const staleLabeledEvent = reversedEvents.find(event => event.event === 'labeled' && - (0, clean_label_1.cleanLabel)(event.label.name) === (0, clean_label_1.cleanLabel)(label)); - if (!staleLabeledEvent) { - // Must be old rather than labeled - return undefined; - } - return staleLabeledEvent.created_at; - }); + const issueLogger = new issue_logger_1.IssueLogger(issue); + issueLogger.info(`Checking for label on this $$type`); + this._consumeIssueOperation(issue); + (_a = this.statistics) === null || _a === void 0 ? void 0 : _a.incrementFetchedItemsEventsCount(); + const staleLabeledEvent = events.find(event => event.event === 'labeled' && + (0, clean_label_1.cleanLabel)(event.label.name) === (0, clean_label_1.cleanLabel)(label)); + if (!staleLabeledEvent) { + // Must be old rather than labeled + return undefined; + } + return staleLabeledEvent.created_at; } getPullRequest(issue) { var _a; @@ -722,10 +739,10 @@ class IssuesProcessor { }); } // handle all of the stale issue logic when we find a stale issue - _processStaleIssue(issue, staleLabel, staleMessage, labelsToAddWhenUnstale, labelsToRemoveWhenUnstale, labelsToRemoveWhenStale, closeMessage, closeLabel) { + _processStaleIssue(issue, staleLabel, staleMessage, labelsToAddWhenUnstale, labelsToRemoveWhenUnstale, labelsToRemoveWhenStale, events, closeMessage, closeLabel) { return __awaiter(this, void 0, void 0, function* () { const issueLogger = new issue_logger_1.IssueLogger(issue); - const markedStaleOn = (yield this.getLabelCreationDate(issue, staleLabel)) || issue.updated_at; + const markedStaleOn = this.getLabelCreationDate(events, issue, staleLabel) || issue.updated_at; issueLogger.info(`$$type marked stale on: ${logger_service_1.LoggerService.cyan(markedStaleOn)}`); const issueHasCommentsSinceStale = yield this._hasCommentsSince(issue, markedStaleOn, staleMessage); issueLogger.info(`$$type has been commented on: ${logger_service_1.LoggerService.cyan(issueHasCommentsSinceStale)}`); diff --git a/src/classes/issues-processor.ts b/src/classes/issues-processor.ts index 9c4a633d5..5a6d6cada 100644 --- a/src/classes/issues-processor.ts +++ b/src/classes/issues-processor.ts @@ -180,6 +180,17 @@ export class IssuesProcessor { // Do the next batch return this.processIssues(page + 1); } + + async getIssueEvents(issue: Issue): Promise { + const options = this.client.rest.issues.listEvents.endpoint.merge({ + owner: context.repo.owner, + repo: context.repo.repo, + per_page: 100, + issue_number: issue.number + }); + const events: IIssueEvent[] = await this.client.paginate(options); + return events.reverse() + } async processIssue( issue: Issue, @@ -196,6 +207,8 @@ export class IssuesProcessor { )}` ); + const events: IIssueEvent[] = await this.getIssueEvents(issue); + // calculate string based messages for this issue const staleMessage: string = issue.isPullRequest ? this.options.stalePrMessage @@ -215,6 +228,13 @@ export class IssuesProcessor { const daysBeforeStale: number = issue.isPullRequest ? this._getDaysBeforePrStale() : this._getDaysBeforeIssueStale(); + const isPinned = this.getPinnedStatus(events); + + if (isPinned) { + issueLogger.info('Skipping this issue because it is pinned'); + IssuesProcessor._endIssueProcessing(issue); + return; // Don't process pinned issues + } if (issue.state === 'closed') { issueLogger.info(`Skipping this $$type because it is closed`); @@ -516,6 +536,7 @@ export class IssuesProcessor { labelsToAddWhenUnstale, labelsToRemoveWhenUnstale, labelsToRemoveWhenStale, + events, closeMessage, closeLabel ); @@ -568,29 +589,31 @@ export class IssuesProcessor { } } + getPinnedStatus(events: IIssueEvent[]): boolean { + const pinnedEvent = events.find(event => event.event === 'pinned'); + const unpinnedEvent = events.find(event => event.event === 'unpinned'); + + if (pinnedEvent) { + return !unpinnedEvent || new Date(pinnedEvent.created_at) > new Date(unpinnedEvent?.created_at); + } + return false; +} + // returns the creation date of a given label on an issue (or nothing if no label existed) ///see https://developer.github.com/v3/activity/events/ - async getLabelCreationDate( + getLabelCreationDate( + events: IIssueEvent[], issue: Issue, label: string - ): Promise { + ): string | undefined { const issueLogger: IssueLogger = new IssueLogger(issue); issueLogger.info(`Checking for label on this $$type`); this._consumeIssueOperation(issue); this.statistics?.incrementFetchedItemsEventsCount(); - const options = this.client.rest.issues.listEvents.endpoint.merge({ - owner: context.repo.owner, - repo: context.repo.repo, - per_page: 100, - issue_number: issue.number - }); - - const events: IIssueEvent[] = await this.client.paginate(options); - const reversedEvents = events.reverse(); - const staleLabeledEvent = reversedEvents.find( + const staleLabeledEvent = events.find( event => event.event === 'labeled' && cleanLabel(event.label.name) === cleanLabel(label) @@ -631,12 +654,13 @@ export class IssuesProcessor { labelsToAddWhenUnstale: Readonly[], labelsToRemoveWhenUnstale: Readonly[], labelsToRemoveWhenStale: Readonly[], + events: IIssueEvent[], closeMessage?: string, closeLabel?: string ) { const issueLogger: IssueLogger = new IssueLogger(issue); const markedStaleOn: string = - (await this.getLabelCreationDate(issue, staleLabel)) || issue.updated_at; + this.getLabelCreationDate(events, issue, staleLabel) || issue.updated_at; issueLogger.info( `$$type marked stale on: ${LoggerService.cyan(markedStaleOn)}` );