mirror of
https://github.com/actions/stale.git
synced 2026-02-07 14:48:17 +00:00
Compare commits
2 Commits
enhancemen
...
ab3a99355d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ab3a99355d | ||
|
|
012207ad41 |
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
name: "@actions/http-client"
|
name: "@actions/http-client"
|
||||||
version: 3.0.1
|
version: 3.0.2
|
||||||
type: npm
|
type: npm
|
||||||
summary: Actions Http Client
|
summary: Actions Http Client
|
||||||
homepage: https://github.com/actions/toolkit/tree/main/packages/http-client
|
homepage: https://github.com/actions/toolkit/tree/main/packages/http-client
|
||||||
2
.licenses/npm/fast-xml-parser.dep.yml
generated
2
.licenses/npm/fast-xml-parser.dep.yml
generated
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
name: fast-xml-parser
|
name: fast-xml-parser
|
||||||
version: 5.3.3
|
version: 5.3.4
|
||||||
type: npm
|
type: npm
|
||||||
summary: Validate XML, Parse XML, Build XML without C/C++ based libraries
|
summary: Validate XML, Parse XML, Build XML without C/C++ based libraries
|
||||||
homepage:
|
homepage:
|
||||||
|
|||||||
34
.licenses/npm/undici-6.23.0.dep.yml
generated
Normal file
34
.licenses/npm/undici-6.23.0.dep.yml
generated
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
---
|
||||||
|
name: undici
|
||||||
|
version: 6.23.0
|
||||||
|
type: npm
|
||||||
|
summary: An HTTP/1.1 client, written from scratch for Node.js
|
||||||
|
homepage: https://undici.nodejs.org
|
||||||
|
license: mit
|
||||||
|
licenses:
|
||||||
|
- sources: LICENSE
|
||||||
|
text: |
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) Matteo Collina and Undici contributors
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
- sources: README.md
|
||||||
|
text: MIT
|
||||||
|
notices: []
|
||||||
@@ -4,7 +4,6 @@ import {IComment} from '../../src/interfaces/comment';
|
|||||||
import {IIssuesProcessorOptions} from '../../src/interfaces/issues-processor-options';
|
import {IIssuesProcessorOptions} from '../../src/interfaces/issues-processor-options';
|
||||||
import {IPullRequest} from '../../src/interfaces/pull-request';
|
import {IPullRequest} from '../../src/interfaces/pull-request';
|
||||||
import {IState} from '../../src/interfaces/state/state';
|
import {IState} from '../../src/interfaces/state/state';
|
||||||
import {IIssueEvent} from '../../src/interfaces/issue-event';
|
|
||||||
|
|
||||||
export class IssuesProcessorMock extends IssuesProcessor {
|
export class IssuesProcessorMock extends IssuesProcessor {
|
||||||
constructor(
|
constructor(
|
||||||
@@ -18,15 +17,7 @@ export class IssuesProcessorMock extends IssuesProcessor {
|
|||||||
getLabelCreationDate?: (
|
getLabelCreationDate?: (
|
||||||
issue: Issue,
|
issue: Issue,
|
||||||
label: string
|
label: string
|
||||||
) =>
|
) => Promise<string | undefined>,
|
||||||
| Promise<string | undefined>
|
|
||||||
| Promise<{creationDate?: string; events: IIssueEvent[]}>,
|
|
||||||
hasOnlyStaleLabelingEventsSince?: (
|
|
||||||
issue: Issue,
|
|
||||||
sinceDate: string,
|
|
||||||
staleLabel: string,
|
|
||||||
events: IIssueEvent[]
|
|
||||||
) => Promise<boolean>,
|
|
||||||
getPullRequest?: (issue: Issue) => Promise<IPullRequest | undefined | void>
|
getPullRequest?: (issue: Issue) => Promise<IPullRequest | undefined | void>
|
||||||
) {
|
) {
|
||||||
super(options, state);
|
super(options, state);
|
||||||
@@ -40,21 +31,7 @@ export class IssuesProcessorMock extends IssuesProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (getLabelCreationDate) {
|
if (getLabelCreationDate) {
|
||||||
this.getLabelCreationDate = async (
|
this.getLabelCreationDate = getLabelCreationDate;
|
||||||
issue: Issue,
|
|
||||||
label: string
|
|
||||||
): Promise<{creationDate?: string; events: IIssueEvent[]}> => {
|
|
||||||
const result = await getLabelCreationDate(issue, label);
|
|
||||||
if (typeof result === 'string' || typeof result === 'undefined') {
|
|
||||||
return {creationDate: result, events: []};
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasOnlyStaleLabelingEventsSince) {
|
|
||||||
this.hasOnlyStaleLabelingEventsSince = hasOnlyStaleLabelingEventsSince;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getPullRequest) {
|
if (getPullRequest) {
|
||||||
|
|||||||
@@ -129,7 +129,6 @@ class IssuesProcessorBuilder {
|
|||||||
async p => (p === 1 ? this._issues : []),
|
async p => (p === 1 ? this._issues : []),
|
||||||
async () => [],
|
async () => [],
|
||||||
async () => new Date().toDateString(),
|
async () => new Date().toDateString(),
|
||||||
undefined,
|
|
||||||
async (): Promise<IPullRequest> => {
|
async (): Promise<IPullRequest> => {
|
||||||
return Promise.resolve({
|
return Promise.resolve({
|
||||||
number: 0,
|
number: 0,
|
||||||
|
|||||||
@@ -1,288 +0,0 @@
|
|||||||
import {Issue} from '../src/classes/issue';
|
|
||||||
import {IIssuesProcessorOptions} from '../src/interfaces/issues-processor-options';
|
|
||||||
import {IssuesProcessorMock} from './classes/issues-processor-mock';
|
|
||||||
import {DefaultProcessorOptions} from './constants/default-processor-options';
|
|
||||||
import {generateIssue} from './functions/generate-issue';
|
|
||||||
import {alwaysFalseStateMock} from './classes/state-mock';
|
|
||||||
import {IState} from '../src/interfaces/state/state';
|
|
||||||
import {IIssueEvent} from '../src/interfaces/issue-event';
|
|
||||||
import {IssuesProcessor} from '../src/classes/issues-processor';
|
|
||||||
|
|
||||||
describe('remove-stale-when-updated with stale label events', (): void => {
|
|
||||||
const markedStaleOn = '2025-01-01T00:00:00Z';
|
|
||||||
const updatedAt = '2025-01-01T00:01:00Z';
|
|
||||||
|
|
||||||
let options: IIssuesProcessorOptions;
|
|
||||||
|
|
||||||
beforeEach((): void => {
|
|
||||||
options = {
|
|
||||||
...DefaultProcessorOptions,
|
|
||||||
removeStaleWhenUpdated: true
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
const buildIssue = (): Issue =>
|
|
||||||
generateIssue(
|
|
||||||
options,
|
|
||||||
1,
|
|
||||||
'dummy-title',
|
|
||||||
updatedAt,
|
|
||||||
markedStaleOn,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
['Stale']
|
|
||||||
);
|
|
||||||
|
|
||||||
const buildEvents = (): IIssueEvent[] => [
|
|
||||||
{
|
|
||||||
event: 'labeled',
|
|
||||||
created_at: markedStaleOn,
|
|
||||||
label: {name: 'Stale'}
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
test('does not remove stale label when only stale label events occurred', async (): Promise<void> => {
|
|
||||||
expect.assertions(1);
|
|
||||||
const issue = buildIssue();
|
|
||||||
|
|
||||||
const processor = new IssuesProcessorMock(
|
|
||||||
options,
|
|
||||||
alwaysFalseStateMock,
|
|
||||||
async p => (p === 1 ? [issue] : []),
|
|
||||||
async () => [],
|
|
||||||
async () => ({creationDate: markedStaleOn, events: buildEvents()}),
|
|
||||||
async () => true
|
|
||||||
);
|
|
||||||
|
|
||||||
await processor.processIssues();
|
|
||||||
|
|
||||||
expect(processor.removedLabelIssues).toHaveLength(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('removes stale label when updates are not just stale label events', async (): Promise<void> => {
|
|
||||||
expect.assertions(1);
|
|
||||||
const issue = buildIssue();
|
|
||||||
|
|
||||||
const processor = new IssuesProcessorMock(
|
|
||||||
options,
|
|
||||||
alwaysFalseStateMock,
|
|
||||||
async p => (p === 1 ? [issue] : []),
|
|
||||||
async () => [],
|
|
||||||
async () => ({creationDate: markedStaleOn, events: buildEvents()}),
|
|
||||||
async () => false
|
|
||||||
);
|
|
||||||
|
|
||||||
await processor.processIssues();
|
|
||||||
|
|
||||||
expect(processor.removedLabelIssues).toHaveLength(1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
class TestIssuesProcessor extends IssuesProcessor {
|
|
||||||
constructor(
|
|
||||||
options: IIssuesProcessorOptions,
|
|
||||||
state: IState,
|
|
||||||
events: IIssueEvent[]
|
|
||||||
) {
|
|
||||||
super(options, state);
|
|
||||||
const client = {
|
|
||||||
rest: {
|
|
||||||
issues: {
|
|
||||||
listEvents: {
|
|
||||||
endpoint: {
|
|
||||||
merge: () => ({})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
paginate: {
|
|
||||||
iterator: async function* () {
|
|
||||||
yield {data: events};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
(this as any).client = client;
|
|
||||||
}
|
|
||||||
|
|
||||||
async callhasOnlyStaleLabelingEventsSince(
|
|
||||||
issue: Issue,
|
|
||||||
sinceDate: string,
|
|
||||||
staleLabel: string,
|
|
||||||
events: IIssueEvent[]
|
|
||||||
): Promise<boolean> {
|
|
||||||
return this.hasOnlyStaleLabelingEventsSince(
|
|
||||||
issue,
|
|
||||||
sinceDate,
|
|
||||||
staleLabel,
|
|
||||||
events
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
describe('hasOnlyStaleLabelingEventsSince', (): void => {
|
|
||||||
const staleLabel = 'Stale';
|
|
||||||
const sinceDate = '2025-01-01T00:00:00Z';
|
|
||||||
const originalRepo = process.env.GITHUB_REPOSITORY;
|
|
||||||
|
|
||||||
let options: IIssuesProcessorOptions;
|
|
||||||
|
|
||||||
beforeEach((): void => {
|
|
||||||
process.env.GITHUB_REPOSITORY = 'owner/repo';
|
|
||||||
options = {
|
|
||||||
...DefaultProcessorOptions,
|
|
||||||
staleIssueLabel: staleLabel,
|
|
||||||
removeStaleWhenUpdated: true
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach((): void => {
|
|
||||||
if (originalRepo === undefined) {
|
|
||||||
delete process.env.GITHUB_REPOSITORY;
|
|
||||||
} else {
|
|
||||||
process.env.GITHUB_REPOSITORY = originalRepo;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const buildIssue = (): Issue =>
|
|
||||||
generateIssue(
|
|
||||||
options,
|
|
||||||
1,
|
|
||||||
'dummy-title',
|
|
||||||
'2025-01-01T00:02:00Z',
|
|
||||||
sinceDate,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
[staleLabel]
|
|
||||||
);
|
|
||||||
|
|
||||||
test('returns true when only stale label events exist after the since date', async (): Promise<void> => {
|
|
||||||
expect.assertions(1);
|
|
||||||
const issue = buildIssue();
|
|
||||||
const events: IIssueEvent[] = [
|
|
||||||
// Event before the sinceDate should be ignored.
|
|
||||||
{
|
|
||||||
event: 'labeled',
|
|
||||||
created_at: '2024-12-31T23:59:00Z',
|
|
||||||
label: {name: staleLabel}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
event: 'labeled',
|
|
||||||
created_at: '2025-01-01T00:00:10Z',
|
|
||||||
label: {name: staleLabel}
|
|
||||||
}
|
|
||||||
];
|
|
||||||
const processor = new TestIssuesProcessor(
|
|
||||||
options,
|
|
||||||
alwaysFalseStateMock,
|
|
||||||
events
|
|
||||||
);
|
|
||||||
const result = await processor.callhasOnlyStaleLabelingEventsSince(
|
|
||||||
issue,
|
|
||||||
sinceDate,
|
|
||||||
staleLabel,
|
|
||||||
events
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(result).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('returns false when a non-stale label event exists after the since date', async (): Promise<void> => {
|
|
||||||
expect.assertions(1);
|
|
||||||
const issue = buildIssue();
|
|
||||||
const events: IIssueEvent[] = [
|
|
||||||
{
|
|
||||||
event: 'labeled',
|
|
||||||
created_at: '2025-01-01T00:00:10Z',
|
|
||||||
label: {name: 'other-label'}
|
|
||||||
}
|
|
||||||
];
|
|
||||||
const processor = new TestIssuesProcessor(
|
|
||||||
options,
|
|
||||||
alwaysFalseStateMock,
|
|
||||||
events
|
|
||||||
);
|
|
||||||
const result = await processor.callhasOnlyStaleLabelingEventsSince(
|
|
||||||
issue,
|
|
||||||
sinceDate,
|
|
||||||
staleLabel,
|
|
||||||
events
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(result).toBe(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('returns false when stale label is removed after the since date', async (): Promise<void> => {
|
|
||||||
expect.assertions(1);
|
|
||||||
const issue = buildIssue();
|
|
||||||
const events: IIssueEvent[] = [
|
|
||||||
{
|
|
||||||
event: 'unlabeled',
|
|
||||||
created_at: '2025-01-01T00:00:10Z',
|
|
||||||
label: {name: staleLabel}
|
|
||||||
}
|
|
||||||
];
|
|
||||||
const processor = new TestIssuesProcessor(
|
|
||||||
options,
|
|
||||||
alwaysFalseStateMock,
|
|
||||||
events
|
|
||||||
);
|
|
||||||
const result = await processor.callhasOnlyStaleLabelingEventsSince(
|
|
||||||
issue,
|
|
||||||
sinceDate,
|
|
||||||
staleLabel,
|
|
||||||
events
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(result).toBe(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('returns false when a non-label event exists after the since date', async (): Promise<void> => {
|
|
||||||
expect.assertions(1);
|
|
||||||
const issue = buildIssue();
|
|
||||||
const events: IIssueEvent[] = [
|
|
||||||
{
|
|
||||||
event: 'commented',
|
|
||||||
created_at: '2025-01-01T00:00:10Z',
|
|
||||||
label: {name: staleLabel}
|
|
||||||
}
|
|
||||||
];
|
|
||||||
const processor = new TestIssuesProcessor(
|
|
||||||
options,
|
|
||||||
alwaysFalseStateMock,
|
|
||||||
events
|
|
||||||
);
|
|
||||||
const result = await processor.callhasOnlyStaleLabelingEventsSince(
|
|
||||||
issue,
|
|
||||||
sinceDate,
|
|
||||||
staleLabel,
|
|
||||||
events
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(result).toBe(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('includes events that occur exactly at the since date boundary', async (): Promise<void> => {
|
|
||||||
expect.assertions(1);
|
|
||||||
const issue = buildIssue();
|
|
||||||
const events: IIssueEvent[] = [
|
|
||||||
{
|
|
||||||
event: 'labeled',
|
|
||||||
created_at: sinceDate,
|
|
||||||
label: {name: staleLabel}
|
|
||||||
}
|
|
||||||
];
|
|
||||||
const processor = new TestIssuesProcessor(
|
|
||||||
options,
|
|
||||||
alwaysFalseStateMock,
|
|
||||||
events
|
|
||||||
);
|
|
||||||
const result = await processor.callhasOnlyStaleLabelingEventsSince(
|
|
||||||
issue,
|
|
||||||
sinceDate,
|
|
||||||
staleLabel,
|
|
||||||
events
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(result).toBe(true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
54961
dist/index.js
vendored
54961
dist/index.js
vendored
File diff suppressed because one or more lines are too long
56
package-lock.json
generated
56
package-lock.json
generated
@@ -92,13 +92,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@actions/cache/node_modules/@actions/http-client": {
|
"node_modules/@actions/cache/node_modules/@actions/http-client": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-3.0.2.tgz",
|
||||||
"integrity": "sha512-SbGS8c/vySbNO3kjFgSW77n83C4MQx/Yoe+b1hAdpuvfHxnkHzDq2pWljUpAA56Si1Gae/7zjeZsV0CYjmLo/w==",
|
"integrity": "sha512-JP38FYYpyqvUsz+Igqlc/JG6YO9PaKuvqjM3iGvaLqFnJ7TFmcLyy2IDrY0bI0qCQug8E9K+elv5ZNfw62ZJzA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"tunnel": "^0.0.6",
|
"tunnel": "^0.0.6",
|
||||||
"undici": "^5.28.5"
|
"undici": "^6.23.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@actions/cache/node_modules/@actions/io": {
|
"node_modules/@actions/cache/node_modules/@actions/io": {
|
||||||
@@ -115,6 +115,15 @@
|
|||||||
"semver": "bin/semver.js"
|
"semver": "bin/semver.js"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@actions/cache/node_modules/undici": {
|
||||||
|
"version": "6.23.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/undici/-/undici-6.23.0.tgz",
|
||||||
|
"integrity": "sha512-VfQPToRA5FZs/qJxLIinmU59u0r7LXqoJkCzinq3ckNJp3vKEh7jTWN589YQ5+aoAC/TGRLyJLCPKcLQbM8r9g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18.17"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@actions/core": {
|
"node_modules/@actions/core": {
|
||||||
"version": "1.11.1",
|
"version": "1.11.1",
|
||||||
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.11.1.tgz",
|
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.11.1.tgz",
|
||||||
@@ -148,13 +157,22 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@actions/github/node_modules/@actions/http-client": {
|
"node_modules/@actions/github/node_modules/@actions/http-client": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-3.0.2.tgz",
|
||||||
"integrity": "sha512-SbGS8c/vySbNO3kjFgSW77n83C4MQx/Yoe+b1hAdpuvfHxnkHzDq2pWljUpAA56Si1Gae/7zjeZsV0CYjmLo/w==",
|
"integrity": "sha512-JP38FYYpyqvUsz+Igqlc/JG6YO9PaKuvqjM3iGvaLqFnJ7TFmcLyy2IDrY0bI0qCQug8E9K+elv5ZNfw62ZJzA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"tunnel": "^0.0.6",
|
"tunnel": "^0.0.6",
|
||||||
"undici": "^5.28.5"
|
"undici": "^6.23.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@actions/github/node_modules/@actions/http-client/node_modules/undici": {
|
||||||
|
"version": "6.23.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/undici/-/undici-6.23.0.tgz",
|
||||||
|
"integrity": "sha512-VfQPToRA5FZs/qJxLIinmU59u0r7LXqoJkCzinq3ckNJp3vKEh7jTWN589YQ5+aoAC/TGRLyJLCPKcLQbM8r9g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18.17"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@actions/glob": {
|
"node_modules/@actions/glob": {
|
||||||
@@ -1137,10 +1155,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": {
|
"node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": {
|
||||||
"version": "3.14.1",
|
"version": "3.14.2",
|
||||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
|
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz",
|
||||||
"integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
|
"integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"argparse": "^1.0.7",
|
"argparse": "^1.0.7",
|
||||||
"esprima": "^4.0.0"
|
"esprima": "^4.0.0"
|
||||||
@@ -3909,9 +3928,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/fast-xml-parser": {
|
"node_modules/fast-xml-parser": {
|
||||||
"version": "5.3.3",
|
"version": "5.3.4",
|
||||||
"resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.3.4.tgz",
|
||||||
"integrity": "sha512-2O3dkPAAC6JavuMm8+4+pgTk+5hoAs+CjZ+sWcQLkX9+/tHRuTkQh/Oaifr8qDmZ8iEHb771Ea6G8CdwkrgvYA==",
|
"integrity": "sha512-EFd6afGmXlCx8H8WTZHhAoDaWaGyuIBoZJ2mknrNxug+aZKjkp0a0dlars9Izl+jF+7Gu1/5f/2h68cQpe0IiA==",
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "github",
|
"type": "github",
|
||||||
@@ -5631,10 +5650,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/lodash": {
|
"node_modules/lodash": {
|
||||||
"version": "4.17.21",
|
"version": "4.17.23",
|
||||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz",
|
||||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
|
"integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==",
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/lodash.deburr": {
|
"node_modules/lodash.deburr": {
|
||||||
"version": "4.1.0",
|
"version": "4.1.0",
|
||||||
|
|||||||
@@ -608,7 +608,7 @@ export class IssuesProcessor {
|
|||||||
async getLabelCreationDate(
|
async getLabelCreationDate(
|
||||||
issue: Issue,
|
issue: Issue,
|
||||||
label: string
|
label: string
|
||||||
): Promise<{creationDate?: string; events: IIssueEvent[]}> {
|
): Promise<string | undefined> {
|
||||||
const issueLogger: IssueLogger = new IssueLogger(issue);
|
const issueLogger: IssueLogger = new IssueLogger(issue);
|
||||||
|
|
||||||
issueLogger.info(`Checking for label on this $$type`);
|
issueLogger.info(`Checking for label on this $$type`);
|
||||||
@@ -623,7 +623,6 @@ export class IssuesProcessor {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const events: IIssueEvent[] = await this.client.paginate(options);
|
const events: IIssueEvent[] = await this.client.paginate(options);
|
||||||
|
|
||||||
const reversedEvents = events.reverse();
|
const reversedEvents = events.reverse();
|
||||||
|
|
||||||
const staleLabeledEvent = reversedEvents.find(
|
const staleLabeledEvent = reversedEvents.find(
|
||||||
@@ -634,51 +633,10 @@ export class IssuesProcessor {
|
|||||||
|
|
||||||
if (!staleLabeledEvent) {
|
if (!staleLabeledEvent) {
|
||||||
// Must be old rather than labeled
|
// Must be old rather than labeled
|
||||||
return {creationDate: undefined, events};
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {creationDate: staleLabeledEvent.created_at, events};
|
return staleLabeledEvent.created_at;
|
||||||
}
|
|
||||||
|
|
||||||
protected async hasOnlyStaleLabelingEventsSince(
|
|
||||||
issue: Issue,
|
|
||||||
sinceDate: string,
|
|
||||||
staleLabel: string,
|
|
||||||
events: IIssueEvent[]
|
|
||||||
): Promise<boolean> {
|
|
||||||
const issueLogger: IssueLogger = new IssueLogger(issue);
|
|
||||||
|
|
||||||
issueLogger.info(
|
|
||||||
`Checking if only stale label added events on $$type since: ${LoggerService.cyan(
|
|
||||||
sinceDate
|
|
||||||
)}`
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!sinceDate) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const sinceTimestamp = new Date(sinceDate).getTime();
|
|
||||||
if (Number.isNaN(sinceTimestamp)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const relevantEvents = events.filter(event => {
|
|
||||||
const eventTimestamp = new Date(event.created_at).getTime();
|
|
||||||
return !Number.isNaN(eventTimestamp) && eventTimestamp >= sinceTimestamp;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (relevantEvents.length === 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return relevantEvents.every(event => {
|
|
||||||
if (event.event !== 'labeled') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return cleanLabel(event.label.name) === cleanLabel(staleLabel);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async getPullRequest(issue: Issue): Promise<IPullRequest | undefined | void> {
|
async getPullRequest(issue: Issue): Promise<IPullRequest | undefined | void> {
|
||||||
@@ -733,11 +691,8 @@ export class IssuesProcessor {
|
|||||||
closeLabel?: string
|
closeLabel?: string
|
||||||
) {
|
) {
|
||||||
const issueLogger: IssueLogger = new IssueLogger(issue);
|
const issueLogger: IssueLogger = new IssueLogger(issue);
|
||||||
const {creationDate, events} = await this.getLabelCreationDate(
|
const markedStaleOn: string =
|
||||||
issue,
|
(await this.getLabelCreationDate(issue, staleLabel)) || issue.updated_at;
|
||||||
staleLabel
|
|
||||||
);
|
|
||||||
const markedStaleOn: string = creationDate || issue.updated_at;
|
|
||||||
issueLogger.info(
|
issueLogger.info(
|
||||||
`$$type marked stale on: ${LoggerService.cyan(markedStaleOn)}`
|
`$$type marked stale on: ${LoggerService.cyan(markedStaleOn)}`
|
||||||
);
|
);
|
||||||
@@ -789,33 +744,12 @@ export class IssuesProcessor {
|
|||||||
|
|
||||||
// The issue.updated_at and markedStaleOn are not always exactly in sync (they can be off by a second or 2)
|
// The issue.updated_at and markedStaleOn are not always exactly in sync (they can be off by a second or 2)
|
||||||
// isDateMoreRecentThan makes sure they are not the same date within a certain tolerance (15 seconds in this case)
|
// isDateMoreRecentThan makes sure they are not the same date within a certain tolerance (15 seconds in this case)
|
||||||
let issueHasUpdateSinceStale = isDateMoreRecentThan(
|
const issueHasUpdateSinceStale = isDateMoreRecentThan(
|
||||||
new Date(issue.updated_at),
|
new Date(issue.updated_at),
|
||||||
new Date(markedStaleOn),
|
new Date(markedStaleOn),
|
||||||
15
|
15
|
||||||
);
|
);
|
||||||
|
|
||||||
// Check if the only update was the stale label being added
|
|
||||||
if (
|
|
||||||
issueHasUpdateSinceStale &&
|
|
||||||
shouldRemoveStaleWhenUpdated &&
|
|
||||||
!issue.markedStaleThisRun
|
|
||||||
) {
|
|
||||||
const onlyStaleLabelAdded = await this.hasOnlyStaleLabelingEventsSince(
|
|
||||||
issue,
|
|
||||||
markedStaleOn,
|
|
||||||
staleLabel,
|
|
||||||
events
|
|
||||||
);
|
|
||||||
|
|
||||||
if (onlyStaleLabelAdded) {
|
|
||||||
issueHasUpdateSinceStale = false;
|
|
||||||
issueLogger.info(
|
|
||||||
`Ignoring $$type update since only the stale label was added`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
issueLogger.info(
|
issueLogger.info(
|
||||||
`$$type has been updated since it was marked stale: ${LoggerService.cyan(
|
`$$type has been updated since it was marked stale: ${LoggerService.cyan(
|
||||||
issueHasUpdateSinceStale
|
issueHasUpdateSinceStale
|
||||||
|
|||||||
Reference in New Issue
Block a user