mirror of
https://github.com/actions/stale.git
synced 2025-12-25 17:58:17 +00:00
Compare commits
18 Commits
handle_api
...
update_esl
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cd01f0a002 | ||
|
|
fbaa974a12 | ||
|
|
213e2e3dbb | ||
|
|
d54efb59cb | ||
|
|
0c5c86b836 | ||
|
|
ade4f65ff5 | ||
|
|
1200f63335 | ||
|
|
321a0c1996 | ||
|
|
6599f03bfe | ||
|
|
facad6de84 | ||
|
|
2ede1ed234 | ||
|
|
c95554e7b3 | ||
|
|
93883857f8 | ||
|
|
f111c4f385 | ||
|
|
c2daa6ff62 | ||
|
|
32507178a3 | ||
|
|
e169e4e149 | ||
|
|
d7468118d7 |
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"plugins": ["jest", "@typescript-eslint"],
|
"plugins": ["jest", "@typescript-eslint"],
|
||||||
"extends": ["plugin:github/es6"],
|
"extends": ["plugin:github/recommended"],
|
||||||
"parser": "@typescript-eslint/parser",
|
"parser": "@typescript-eslint/parser",
|
||||||
"parserOptions": {
|
"parserOptions": {
|
||||||
"ecmaVersion": 9,
|
"ecmaVersion": 9,
|
||||||
@@ -16,11 +16,10 @@
|
|||||||
"@typescript-eslint/no-require-imports": "error",
|
"@typescript-eslint/no-require-imports": "error",
|
||||||
"@typescript-eslint/array-type": "error",
|
"@typescript-eslint/array-type": "error",
|
||||||
"@typescript-eslint/await-thenable": "error",
|
"@typescript-eslint/await-thenable": "error",
|
||||||
"@typescript-eslint/ban-ts-ignore": "error",
|
"@typescript-eslint/ban-ts-comment": "error",
|
||||||
"camelcase": "off",
|
"camelcase": "off",
|
||||||
"@typescript-eslint/class-name-casing": "error",
|
"@typescript-eslint/consistent-type-assertions": "error",
|
||||||
"@typescript-eslint/func-call-spacing": ["error", "never"],
|
"@typescript-eslint/func-call-spacing": ["error", "never"],
|
||||||
"@typescript-eslint/generic-type-naming": ["error", "^[A-Z][A-Za-z]*$"],
|
|
||||||
"@typescript-eslint/no-array-constructor": "error",
|
"@typescript-eslint/no-array-constructor": "error",
|
||||||
"@typescript-eslint/no-empty-interface": "error",
|
"@typescript-eslint/no-empty-interface": "error",
|
||||||
"@typescript-eslint/no-explicit-any": "off",
|
"@typescript-eslint/no-explicit-any": "off",
|
||||||
@@ -30,7 +29,6 @@
|
|||||||
"@typescript-eslint/no-misused-new": "error",
|
"@typescript-eslint/no-misused-new": "error",
|
||||||
"@typescript-eslint/no-namespace": "error",
|
"@typescript-eslint/no-namespace": "error",
|
||||||
"@typescript-eslint/no-non-null-assertion": "warn",
|
"@typescript-eslint/no-non-null-assertion": "warn",
|
||||||
"@typescript-eslint/no-object-literal-type-assertion": "error",
|
|
||||||
"@typescript-eslint/no-unnecessary-qualifier": "error",
|
"@typescript-eslint/no-unnecessary-qualifier": "error",
|
||||||
"@typescript-eslint/no-unnecessary-type-assertion": "error",
|
"@typescript-eslint/no-unnecessary-type-assertion": "error",
|
||||||
"@typescript-eslint/no-useless-constructor": "error",
|
"@typescript-eslint/no-useless-constructor": "error",
|
||||||
@@ -38,7 +36,6 @@
|
|||||||
"@typescript-eslint/prefer-for-of": "warn",
|
"@typescript-eslint/prefer-for-of": "warn",
|
||||||
"@typescript-eslint/prefer-function-type": "warn",
|
"@typescript-eslint/prefer-function-type": "warn",
|
||||||
"@typescript-eslint/prefer-includes": "error",
|
"@typescript-eslint/prefer-includes": "error",
|
||||||
"@typescript-eslint/prefer-interface": "error",
|
|
||||||
"@typescript-eslint/prefer-string-starts-ends-with": "error",
|
"@typescript-eslint/prefer-string-starts-ends-with": "error",
|
||||||
"@typescript-eslint/promise-function-async": "error",
|
"@typescript-eslint/promise-function-async": "error",
|
||||||
"@typescript-eslint/require-array-sort-compare": "error",
|
"@typescript-eslint/require-array-sort-compare": "error",
|
||||||
|
|||||||
9
.github/dependabot.yml
vendored
Normal file
9
.github/dependabot.yml
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
version: 2
|
||||||
|
updates:
|
||||||
|
# Enable version updates for npm
|
||||||
|
- package-ecosystem: 'npm'
|
||||||
|
# Look for `package.json` and `lock` files in the `root` directory
|
||||||
|
directory: '/'
|
||||||
|
# Check the npm registry for updates every day (weekdays)
|
||||||
|
schedule:
|
||||||
|
interval: 'daily'
|
||||||
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
@@ -3,7 +3,7 @@ on: # rebuild any PRs and main branch changes
|
|||||||
pull_request:
|
pull_request:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- master
|
- main
|
||||||
- 'releases/*'
|
- 'releases/*'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
|||||||
@@ -31,10 +31,12 @@ function generateIssue(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const DefaultProcessorOptions: IssueProcessorOptions = {
|
const DefaultProcessorOptions: IssueProcessorOptions = Object.freeze({
|
||||||
repoToken: 'none',
|
repoToken: 'none',
|
||||||
staleIssueMessage: 'This issue is stale',
|
staleIssueMessage: 'This issue is stale',
|
||||||
stalePrMessage: 'This PR is stale',
|
stalePrMessage: 'This PR is stale',
|
||||||
|
closeIssueMessage: 'This issue is being closed',
|
||||||
|
closePrMessage: 'This PR is being closed',
|
||||||
daysBeforeStale: 1,
|
daysBeforeStale: 1,
|
||||||
daysBeforeClose: 30,
|
daysBeforeClose: 30,
|
||||||
staleIssueLabel: 'Stale',
|
staleIssueLabel: 'Stale',
|
||||||
@@ -44,8 +46,11 @@ const DefaultProcessorOptions: IssueProcessorOptions = {
|
|||||||
onlyLabels: '',
|
onlyLabels: '',
|
||||||
operationsPerRun: 100,
|
operationsPerRun: 100,
|
||||||
debugOnly: true,
|
debugOnly: true,
|
||||||
removeStaleWhenUpdated: false
|
removeStaleWhenUpdated: false,
|
||||||
};
|
ascending: false,
|
||||||
|
skipStaleIssueMessage: false,
|
||||||
|
skipStalePrMessage: false
|
||||||
|
});
|
||||||
|
|
||||||
test('empty issue list results in 1 operation', async () => {
|
test('empty issue list results in 1 operation', async () => {
|
||||||
const processor = new IssueProcessor(
|
const processor = new IssueProcessor(
|
||||||
@@ -106,6 +111,31 @@ test('processing an issue with no label will make it stale and not close it if d
|
|||||||
expect(processor.closedIssues.length).toEqual(0);
|
expect(processor.closedIssues.length).toEqual(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('processing an issue with no label will not make it stale if days-before-stale is set to -1', async () => {
|
||||||
|
const TestIssueList: Issue[] = [
|
||||||
|
generateIssue(1, 'An issue with no label', '2020-01-01T17:00:00Z')
|
||||||
|
];
|
||||||
|
|
||||||
|
const opts = {
|
||||||
|
...DefaultProcessorOptions,
|
||||||
|
staleIssueMessage: '',
|
||||||
|
daysBeforeStale: -1
|
||||||
|
};
|
||||||
|
|
||||||
|
const processor = new IssueProcessor(
|
||||||
|
opts,
|
||||||
|
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 () => {
|
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
|
// issue should be from 2 days ago so it will be
|
||||||
// stale but not close-able, based on default settings
|
// stale but not close-able, based on default settings
|
||||||
@@ -180,6 +210,60 @@ test('processing a stale PR will close it', async () => {
|
|||||||
expect(processor.closedIssues.length).toEqual(1);
|
expect(processor.closedIssues.length).toEqual(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('processing a stale issue 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', false, [
|
||||||
|
'Stale'
|
||||||
|
])
|
||||||
|
];
|
||||||
|
|
||||||
|
const opts = {
|
||||||
|
...DefaultProcessorOptions,
|
||||||
|
daysBeforeStale: -1,
|
||||||
|
staleIssueMessage: ''
|
||||||
|
};
|
||||||
|
|
||||||
|
const processor = new IssueProcessor(
|
||||||
|
opts,
|
||||||
|
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, [
|
||||||
|
'Stale'
|
||||||
|
])
|
||||||
|
];
|
||||||
|
|
||||||
|
const opts = {
|
||||||
|
...DefaultProcessorOptions,
|
||||||
|
daysBeforeStale: -1,
|
||||||
|
stalePrMessage: ''
|
||||||
|
};
|
||||||
|
|
||||||
|
const processor = new IssueProcessor(
|
||||||
|
opts,
|
||||||
|
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 () => {
|
test('closed issues will not be marked stale', async () => {
|
||||||
const TestIssueList: Issue[] = [
|
const TestIssueList: Issue[] = [
|
||||||
generateIssue(
|
generateIssue(
|
||||||
@@ -514,7 +598,7 @@ test('stale label should be removed if a comment was added to a stale issue', as
|
|||||||
)
|
)
|
||||||
];
|
];
|
||||||
|
|
||||||
const opts = DefaultProcessorOptions;
|
const opts = {...DefaultProcessorOptions};
|
||||||
opts.removeStaleWhenUpdated = true;
|
opts.removeStaleWhenUpdated = true;
|
||||||
|
|
||||||
const processor = new IssueProcessor(
|
const processor = new IssueProcessor(
|
||||||
@@ -544,7 +628,7 @@ test('stale label should not be removed if a comment was added by the bot (and t
|
|||||||
)
|
)
|
||||||
];
|
];
|
||||||
|
|
||||||
const opts = DefaultProcessorOptions;
|
const opts = {...DefaultProcessorOptions};
|
||||||
opts.removeStaleWhenUpdated = true;
|
opts.removeStaleWhenUpdated = true;
|
||||||
|
|
||||||
const processor = new IssueProcessor(
|
const processor = new IssueProcessor(
|
||||||
@@ -574,7 +658,7 @@ test('stale issues should not be closed until after the closed number of days',
|
|||||||
)
|
)
|
||||||
];
|
];
|
||||||
|
|
||||||
const opts = DefaultProcessorOptions;
|
const opts = {...DefaultProcessorOptions};
|
||||||
opts.daysBeforeStale = 5; // stale after 5 days
|
opts.daysBeforeStale = 5; // stale after 5 days
|
||||||
opts.daysBeforeClose = 1; // closes after 6 days
|
opts.daysBeforeClose = 1; // closes after 6 days
|
||||||
|
|
||||||
@@ -606,7 +690,7 @@ test('stale issues should be closed if the closed nubmer of days (additive) is a
|
|||||||
)
|
)
|
||||||
];
|
];
|
||||||
|
|
||||||
const opts = DefaultProcessorOptions;
|
const opts = {...DefaultProcessorOptions};
|
||||||
opts.daysBeforeStale = 5; // stale after 5 days
|
opts.daysBeforeStale = 5; // stale after 5 days
|
||||||
opts.daysBeforeClose = 1; // closes after 6 days
|
opts.daysBeforeClose = 1; // closes after 6 days
|
||||||
|
|
||||||
@@ -637,7 +721,7 @@ test('stale issues should not be closed until after the closed number of days (l
|
|||||||
)
|
)
|
||||||
];
|
];
|
||||||
|
|
||||||
const opts = DefaultProcessorOptions;
|
const opts = {...DefaultProcessorOptions};
|
||||||
opts.daysBeforeStale = 5; // stale after 5 days
|
opts.daysBeforeStale = 5; // stale after 5 days
|
||||||
opts.daysBeforeClose = 20; // closes after 25 days
|
opts.daysBeforeClose = 20; // closes after 25 days
|
||||||
|
|
||||||
@@ -655,3 +739,157 @@ test('stale issues should not be closed until after the closed number of days (l
|
|||||||
expect(processor.removedLabelIssues.length).toEqual(0);
|
expect(processor.removedLabelIssues.length).toEqual(0);
|
||||||
expect(processor.staleIssues.length).toEqual(1);
|
expect(processor.staleIssues.length).toEqual(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('skips stale message on issues when skip-stale-issue-message is set', async () => {
|
||||||
|
let lastUpdate = new Date();
|
||||||
|
lastUpdate.setDate(lastUpdate.getDate() - 10);
|
||||||
|
const TestIssueList: Issue[] = [
|
||||||
|
generateIssue(
|
||||||
|
1,
|
||||||
|
'An issue that should be marked stale but not closed',
|
||||||
|
lastUpdate.toString(),
|
||||||
|
false
|
||||||
|
)
|
||||||
|
];
|
||||||
|
|
||||||
|
const opts = {...DefaultProcessorOptions};
|
||||||
|
opts.daysBeforeStale = 5; // stale after 5 days
|
||||||
|
opts.daysBeforeClose = 20; // closes after 25 days
|
||||||
|
opts.skipStaleIssueMessage = true;
|
||||||
|
|
||||||
|
const processor = new IssueProcessor(
|
||||||
|
opts,
|
||||||
|
async p => (p == 1 ? TestIssueList : []),
|
||||||
|
async (num, dt) => [],
|
||||||
|
async (issue, label) => new Date().toDateString()
|
||||||
|
);
|
||||||
|
|
||||||
|
// for sake of testing, mocking private function
|
||||||
|
const markSpy = jest.spyOn(processor as any, 'markStale');
|
||||||
|
|
||||||
|
await processor.processIssues(1);
|
||||||
|
|
||||||
|
// issue should be staled
|
||||||
|
expect(processor.closedIssues.length).toEqual(0);
|
||||||
|
expect(processor.removedLabelIssues.length).toEqual(0);
|
||||||
|
expect(processor.staleIssues.length).toEqual(1);
|
||||||
|
|
||||||
|
// comment should not be created
|
||||||
|
expect(markSpy).toHaveBeenCalledWith(
|
||||||
|
TestIssueList[0],
|
||||||
|
opts.staleIssueMessage,
|
||||||
|
opts.staleIssueLabel,
|
||||||
|
// this option is skipMessage
|
||||||
|
true
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('skips stale message on prs when skip-stale-pr-message is set', async () => {
|
||||||
|
let lastUpdate = new Date();
|
||||||
|
lastUpdate.setDate(lastUpdate.getDate() - 10);
|
||||||
|
const TestIssueList: Issue[] = [
|
||||||
|
generateIssue(
|
||||||
|
1,
|
||||||
|
'An issue that should be marked stale but not closed',
|
||||||
|
lastUpdate.toString(),
|
||||||
|
true
|
||||||
|
)
|
||||||
|
];
|
||||||
|
|
||||||
|
const opts = {...DefaultProcessorOptions};
|
||||||
|
opts.daysBeforeStale = 5; // stale after 5 days
|
||||||
|
opts.daysBeforeClose = 20; // closes after 25 days
|
||||||
|
opts.skipStalePrMessage = true;
|
||||||
|
|
||||||
|
const processor = new IssueProcessor(
|
||||||
|
opts,
|
||||||
|
async p => (p == 1 ? TestIssueList : []),
|
||||||
|
async (num, dt) => [],
|
||||||
|
async (issue, label) => new Date().toDateString()
|
||||||
|
);
|
||||||
|
|
||||||
|
// for sake of testing, mocking private function
|
||||||
|
const markSpy = jest.spyOn(processor as any, 'markStale');
|
||||||
|
|
||||||
|
await processor.processIssues(1);
|
||||||
|
|
||||||
|
// issue should be staled
|
||||||
|
expect(processor.closedIssues.length).toEqual(0);
|
||||||
|
expect(processor.removedLabelIssues.length).toEqual(0);
|
||||||
|
expect(processor.staleIssues.length).toEqual(1);
|
||||||
|
|
||||||
|
// comment should not be created
|
||||||
|
expect(markSpy).toHaveBeenCalledWith(
|
||||||
|
TestIssueList[0],
|
||||||
|
opts.stalePrMessage,
|
||||||
|
opts.stalePrLabel,
|
||||||
|
// this option is skipMessage
|
||||||
|
true
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('not providing state takes precedence over skipStaleIssueMessage', async () => {
|
||||||
|
let lastUpdate = new Date();
|
||||||
|
lastUpdate.setDate(lastUpdate.getDate() - 10);
|
||||||
|
const TestIssueList: Issue[] = [
|
||||||
|
generateIssue(
|
||||||
|
1,
|
||||||
|
'An issue that should be marked stale but not closed',
|
||||||
|
lastUpdate.toString(),
|
||||||
|
false
|
||||||
|
)
|
||||||
|
];
|
||||||
|
|
||||||
|
const opts = {...DefaultProcessorOptions};
|
||||||
|
opts.daysBeforeStale = 5; // stale after 5 days
|
||||||
|
opts.daysBeforeClose = 20; // closes after 25 days
|
||||||
|
opts.skipStalePrMessage = true;
|
||||||
|
opts.staleIssueMessage = '';
|
||||||
|
|
||||||
|
const processor = new IssueProcessor(
|
||||||
|
opts,
|
||||||
|
async p => (p == 1 ? TestIssueList : []),
|
||||||
|
async (num, dt) => [],
|
||||||
|
async (issue, label) => new Date().toDateString()
|
||||||
|
);
|
||||||
|
|
||||||
|
await processor.processIssues(1);
|
||||||
|
|
||||||
|
// issue should be staled
|
||||||
|
expect(processor.closedIssues.length).toEqual(0);
|
||||||
|
expect(processor.removedLabelIssues.length).toEqual(0);
|
||||||
|
expect(processor.staleIssues.length).toEqual(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('not providing stalePrMessage takes precedence over skipStalePrMessage', async () => {
|
||||||
|
let lastUpdate = new Date();
|
||||||
|
lastUpdate.setDate(lastUpdate.getDate() - 10);
|
||||||
|
const TestIssueList: Issue[] = [
|
||||||
|
generateIssue(
|
||||||
|
1,
|
||||||
|
'An issue that should be marked stale but not closed',
|
||||||
|
lastUpdate.toString(),
|
||||||
|
true
|
||||||
|
)
|
||||||
|
];
|
||||||
|
|
||||||
|
const opts = {...DefaultProcessorOptions};
|
||||||
|
opts.daysBeforeStale = 5; // stale after 5 days
|
||||||
|
opts.daysBeforeClose = 20; // closes after 25 days
|
||||||
|
opts.skipStalePrMessage = true;
|
||||||
|
opts.stalePrMessage = '';
|
||||||
|
|
||||||
|
const processor = new IssueProcessor(
|
||||||
|
opts,
|
||||||
|
async p => (p == 1 ? TestIssueList : []),
|
||||||
|
async (num, dt) => [],
|
||||||
|
async (issue, label) => new Date().toDateString()
|
||||||
|
);
|
||||||
|
|
||||||
|
await processor.processIssues(1);
|
||||||
|
|
||||||
|
// issue should be staled
|
||||||
|
expect(processor.closedIssues.length).toEqual(0);
|
||||||
|
expect(processor.removedLabelIssues.length).toEqual(0);
|
||||||
|
expect(processor.staleIssues.length).toEqual(0);
|
||||||
|
});
|
||||||
|
|||||||
15
action.yml
15
action.yml
@@ -9,8 +9,12 @@ inputs:
|
|||||||
description: 'The message to post on the issue when tagging it. If none provided, will not mark issues stale.'
|
description: 'The message to post on the issue when tagging it. If none provided, will not mark issues stale.'
|
||||||
stale-pr-message:
|
stale-pr-message:
|
||||||
description: 'The message to post on the pr when tagging it. If none provided, will not mark pull requests stale.'
|
description: 'The message to post on the pr when tagging it. If none provided, will not mark pull requests stale.'
|
||||||
|
close-issue-message:
|
||||||
|
description: 'The message to post on the issue when closing it. If none provided, will not comment when closing an issue.'
|
||||||
|
close-pr-message:
|
||||||
|
description: 'The message to post on the pr when closing it. If none provided, will not comment when closing a pull requests.'
|
||||||
days-before-stale:
|
days-before-stale:
|
||||||
description: 'The number of days old an issue can be before marking it stale.'
|
description: 'The number of days old an issue can be before marking it stale. Set to -1 to never mark issues or pull requests as stale automatically.'
|
||||||
default: 60
|
default: 60
|
||||||
days-before-close:
|
days-before-close:
|
||||||
description: 'The number of days to wait to close an issue or pull request after it being marked stale. Set to -1 to never close stale issues.'
|
description: 'The number of days to wait to close an issue or pull request after it being marked stale. Set to -1 to never close stale issues.'
|
||||||
@@ -39,6 +43,15 @@ inputs:
|
|||||||
debug-only:
|
debug-only:
|
||||||
description: 'Run the processor in debug mode without actually performing any operations on live issues.'
|
description: 'Run the processor in debug mode without actually performing any operations on live issues.'
|
||||||
default: false
|
default: false
|
||||||
|
ascending:
|
||||||
|
description: 'The order to get issues or pull requests. Defaults to false, which is descending'
|
||||||
|
default: false
|
||||||
|
skip-stale-pr-message:
|
||||||
|
description: 'Skip adding stale message when marking a pull request as stale.'
|
||||||
|
default: false
|
||||||
|
skip-stale-issue-message:
|
||||||
|
description: 'Skip adding stale message when marking an issue as stale.'
|
||||||
|
default: false
|
||||||
runs:
|
runs:
|
||||||
using: 'node12'
|
using: 'node12'
|
||||||
main: 'dist/index.js'
|
main: 'dist/index.js'
|
||||||
|
|||||||
119
dist/index.js
vendored
119
dist/index.js
vendored
@@ -3499,6 +3499,25 @@ function checkMode (stat, options) {
|
|||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
||||||
|
}) : (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
o[k2] = m[k];
|
||||||
|
}));
|
||||||
|
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||||
|
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||||
|
}) : function(o, v) {
|
||||||
|
o["default"] = v;
|
||||||
|
});
|
||||||
|
var __importStar = (this && this.__importStar) || function (mod) {
|
||||||
|
if (mod && mod.__esModule) return mod;
|
||||||
|
var result = {};
|
||||||
|
if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||||
|
__setModuleDefault(result, mod);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||||
return new (P || (P = Promise))(function (resolve, reject) {
|
return new (P || (P = Promise))(function (resolve, reject) {
|
||||||
@@ -3508,13 +3527,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|||||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
var __importStar = (this && this.__importStar) || function (mod) {
|
|
||||||
if (mod && mod.__esModule) return mod;
|
|
||||||
var result = {};
|
|
||||||
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
|
||||||
result["default"] = mod;
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
const core = __importStar(__webpack_require__(470));
|
const core = __importStar(__webpack_require__(470));
|
||||||
const IssueProcessor_1 = __webpack_require__(656);
|
const IssueProcessor_1 = __webpack_require__(656);
|
||||||
@@ -3536,6 +3548,8 @@ function getAndValidateArgs() {
|
|||||||
repoToken: core.getInput('repo-token', { required: true }),
|
repoToken: core.getInput('repo-token', { required: true }),
|
||||||
staleIssueMessage: core.getInput('stale-issue-message'),
|
staleIssueMessage: core.getInput('stale-issue-message'),
|
||||||
stalePrMessage: core.getInput('stale-pr-message'),
|
stalePrMessage: core.getInput('stale-pr-message'),
|
||||||
|
closeIssueMessage: core.getInput('close-issue-message'),
|
||||||
|
closePrMessage: core.getInput('close-pr-message'),
|
||||||
daysBeforeStale: parseInt(core.getInput('days-before-stale', { required: true })),
|
daysBeforeStale: parseInt(core.getInput('days-before-stale', { required: true })),
|
||||||
daysBeforeClose: parseInt(core.getInput('days-before-close', { required: true })),
|
daysBeforeClose: parseInt(core.getInput('days-before-close', { required: true })),
|
||||||
staleIssueLabel: core.getInput('stale-issue-label', { required: true }),
|
staleIssueLabel: core.getInput('stale-issue-label', { required: true }),
|
||||||
@@ -3545,7 +3559,10 @@ function getAndValidateArgs() {
|
|||||||
onlyLabels: core.getInput('only-labels'),
|
onlyLabels: core.getInput('only-labels'),
|
||||||
operationsPerRun: parseInt(core.getInput('operations-per-run', { required: true })),
|
operationsPerRun: parseInt(core.getInput('operations-per-run', { required: true })),
|
||||||
removeStaleWhenUpdated: !(core.getInput('remove-stale-when-updated') === 'false'),
|
removeStaleWhenUpdated: !(core.getInput('remove-stale-when-updated') === 'false'),
|
||||||
debugOnly: core.getInput('debug-only') === 'true'
|
debugOnly: core.getInput('debug-only') === 'true',
|
||||||
|
ascending: core.getInput('ascending') === 'true',
|
||||||
|
skipStalePrMessage: core.getInput('skip-stale-pr-message') === 'true',
|
||||||
|
skipStaleIssueMessage: core.getInput('skip-stale-issue-message') === 'true'
|
||||||
};
|
};
|
||||||
for (const numberInput of [
|
for (const numberInput of [
|
||||||
'days-before-stale',
|
'days-before-stale',
|
||||||
@@ -8603,6 +8620,25 @@ if (process.platform === 'linux') {
|
|||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
||||||
|
}) : (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
o[k2] = m[k];
|
||||||
|
}));
|
||||||
|
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||||
|
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||||
|
}) : function(o, v) {
|
||||||
|
o["default"] = v;
|
||||||
|
});
|
||||||
|
var __importStar = (this && this.__importStar) || function (mod) {
|
||||||
|
if (mod && mod.__esModule) return mod;
|
||||||
|
var result = {};
|
||||||
|
if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||||
|
__setModuleDefault(result, mod);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||||
return new (P || (P = Promise))(function (resolve, reject) {
|
return new (P || (P = Promise))(function (resolve, reject) {
|
||||||
@@ -8612,14 +8648,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|||||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
var __importStar = (this && this.__importStar) || function (mod) {
|
|
||||||
if (mod && mod.__esModule) return mod;
|
|
||||||
var result = {};
|
|
||||||
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
|
||||||
result["default"] = mod;
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.IssueProcessor = void 0;
|
||||||
const core = __importStar(__webpack_require__(470));
|
const core = __importStar(__webpack_require__(470));
|
||||||
const github = __importStar(__webpack_require__(469));
|
const github = __importStar(__webpack_require__(469));
|
||||||
/***
|
/***
|
||||||
@@ -8663,12 +8693,19 @@ class IssueProcessor {
|
|||||||
const staleMessage = isPr
|
const staleMessage = isPr
|
||||||
? this.options.stalePrMessage
|
? this.options.stalePrMessage
|
||||||
: this.options.staleIssueMessage;
|
: this.options.staleIssueMessage;
|
||||||
|
const closeMessage = isPr
|
||||||
|
? this.options.closePrMessage
|
||||||
|
: this.options.closeIssueMessage;
|
||||||
const staleLabel = isPr
|
const staleLabel = isPr
|
||||||
? this.options.stalePrLabel
|
? this.options.stalePrLabel
|
||||||
: this.options.staleIssueLabel;
|
: this.options.staleIssueLabel;
|
||||||
const exemptLabels = IssueProcessor.parseCommaSeparatedString(isPr ? this.options.exemptPrLabels : this.options.exemptIssueLabels);
|
const exemptLabels = IssueProcessor.parseCommaSeparatedString(isPr ? this.options.exemptPrLabels : this.options.exemptIssueLabels);
|
||||||
|
const skipMessage = isPr
|
||||||
|
? this.options.skipStalePrMessage
|
||||||
|
: this.options.skipStaleIssueMessage;
|
||||||
const issueType = isPr ? 'pr' : 'issue';
|
const issueType = isPr ? 'pr' : 'issue';
|
||||||
if (!staleMessage) {
|
const shouldMarkWhenStale = this.options.daysBeforeStale > -1;
|
||||||
|
if (!staleMessage && shouldMarkWhenStale) {
|
||||||
core.info(`Skipping ${issueType} due to empty stale message`);
|
core.info(`Skipping ${issueType} due to empty stale message`);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -8689,15 +8726,15 @@ class IssueProcessor {
|
|||||||
// should this issue be marked stale?
|
// should this issue be marked stale?
|
||||||
const shouldBeStale = !IssueProcessor.updatedSince(issue.updated_at, this.options.daysBeforeStale);
|
const shouldBeStale = !IssueProcessor.updatedSince(issue.updated_at, this.options.daysBeforeStale);
|
||||||
// determine if this issue needs to be marked stale first
|
// determine if this issue needs to be marked stale first
|
||||||
if (!isStale && shouldBeStale) {
|
if (!isStale && shouldBeStale && shouldMarkWhenStale) {
|
||||||
core.info(`Marking ${issueType} stale because it was last updated on ${issue.updated_at} and it does not have a stale label`);
|
core.info(`Marking ${issueType} stale because it was last updated on ${issue.updated_at} and it does not have a stale label`);
|
||||||
yield this.markStale(issue, staleMessage, staleLabel);
|
yield this.markStale(issue, staleMessage, staleLabel, skipMessage);
|
||||||
isStale = true; // this issue is now considered stale
|
isStale = true; // this issue is now considered stale
|
||||||
}
|
}
|
||||||
// process the issue if it was marked stale
|
// process the issue if it was marked stale
|
||||||
if (isStale) {
|
if (isStale) {
|
||||||
core.info(`Found a stale ${issueType}`);
|
core.info(`Found a stale ${issueType}`);
|
||||||
yield this.processStaleIssue(issue, issueType, staleLabel);
|
yield this.processStaleIssue(issue, issueType, staleLabel, closeMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this.operationsLeft <= 0) {
|
if (this.operationsLeft <= 0) {
|
||||||
@@ -8709,7 +8746,7 @@ class IssueProcessor {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
// handle all of the stale issue logic when we find a stale issue
|
// handle all of the stale issue logic when we find a stale issue
|
||||||
processStaleIssue(issue, issueType, staleLabel) {
|
processStaleIssue(issue, issueType, staleLabel, closeMessage) {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
const markedStaleOn = (yield this.getLabelCreationDate(issue, staleLabel)) || issue.updated_at;
|
const markedStaleOn = (yield this.getLabelCreationDate(issue, staleLabel)) || issue.updated_at;
|
||||||
core.info(`Issue #${issue.number} marked stale on: ${markedStaleOn}`);
|
core.info(`Issue #${issue.number} marked stale on: ${markedStaleOn}`);
|
||||||
@@ -8728,7 +8765,7 @@ class IssueProcessor {
|
|||||||
}
|
}
|
||||||
if (!issueHasComments && !issueHasUpdate) {
|
if (!issueHasComments && !issueHasUpdate) {
|
||||||
core.info(`Closing ${issueType} because it was last updated on ${issue.updated_at}`);
|
core.info(`Closing ${issueType} because it was last updated on ${issue.updated_at}`);
|
||||||
yield this.closeIssue(issue);
|
yield this.closeIssue(issue, closeMessage);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
core.info(`Stale ${issueType} is not old enough to close yet (hasComments? ${issueHasComments}, hasUpdate? ${issueHasUpdate}`);
|
core.info(`Stale ${issueType} is not old enough to close yet (hasComments? ${issueHasComments}, hasUpdate? ${issueHasUpdate}`);
|
||||||
@@ -8780,6 +8817,7 @@ class IssueProcessor {
|
|||||||
state: 'open',
|
state: 'open',
|
||||||
labels: this.options.onlyLabels,
|
labels: this.options.onlyLabels,
|
||||||
per_page: 100,
|
per_page: 100,
|
||||||
|
direction: this.options.ascending ? 'asc' : 'desc',
|
||||||
page
|
page
|
||||||
});
|
});
|
||||||
return issueResult.data;
|
return issueResult.data;
|
||||||
@@ -8791,7 +8829,7 @@ class IssueProcessor {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
// Mark an issue as stale with a comment and a label
|
// Mark an issue as stale with a comment and a label
|
||||||
markStale(issue, staleMessage, staleLabel) {
|
markStale(issue, staleMessage, staleLabel, skipMessage) {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
core.info(`Marking issue #${issue.number} - ${issue.title} as stale`);
|
core.info(`Marking issue #${issue.number} - ${issue.title} as stale`);
|
||||||
this.staleIssues.push(issue);
|
this.staleIssues.push(issue);
|
||||||
@@ -8803,16 +8841,18 @@ class IssueProcessor {
|
|||||||
if (this.options.debugOnly) {
|
if (this.options.debugOnly) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
if (!skipMessage) {
|
||||||
yield this.client.issues.createComment({
|
try {
|
||||||
owner: github.context.repo.owner,
|
yield this.client.issues.createComment({
|
||||||
repo: github.context.repo.repo,
|
owner: github.context.repo.owner,
|
||||||
issue_number: issue.number,
|
repo: github.context.repo.repo,
|
||||||
body: staleMessage
|
issue_number: issue.number,
|
||||||
});
|
body: staleMessage
|
||||||
}
|
});
|
||||||
catch (error) {
|
}
|
||||||
core.error(`Error creating a comment: ${error.message}`);
|
catch (error) {
|
||||||
|
core.error(`Error creating a comment: ${error.message}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
yield this.client.issues.addLabels({
|
yield this.client.issues.addLabels({
|
||||||
@@ -8828,7 +8868,7 @@ class IssueProcessor {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
// Close an issue based on staleness
|
// Close an issue based on staleness
|
||||||
closeIssue(issue) {
|
closeIssue(issue, closeMessage) {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
core.info(`Closing issue #${issue.number} - ${issue.title} for being stale`);
|
core.info(`Closing issue #${issue.number} - ${issue.title} for being stale`);
|
||||||
this.closedIssues.push(issue);
|
this.closedIssues.push(issue);
|
||||||
@@ -8836,6 +8876,19 @@ class IssueProcessor {
|
|||||||
if (this.options.debugOnly) {
|
if (this.options.debugOnly) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (closeMessage) {
|
||||||
|
try {
|
||||||
|
yield this.client.issues.createComment({
|
||||||
|
owner: github.context.repo.owner,
|
||||||
|
repo: github.context.repo.repo,
|
||||||
|
issue_number: issue.number,
|
||||||
|
body: closeMessage
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
core.error(`Error creating a comment: ${error.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
yield this.client.issues.update({
|
yield this.client.issues.update({
|
||||||
owner: github.context.repo.owner,
|
owner: github.context.repo.owner,
|
||||||
|
|||||||
2667
package-lock.json
generated
2667
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
18
package.json
18
package.json
@@ -28,22 +28,22 @@
|
|||||||
"@actions/core": "^1.2.4",
|
"@actions/core": "^1.2.4",
|
||||||
"@actions/github": "^2.2.0",
|
"@actions/github": "^2.2.0",
|
||||||
"@octokit/rest": "^16.43.1",
|
"@octokit/rest": "^16.43.1",
|
||||||
"semver": "^6.1.1"
|
"semver": "^7.3.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/semver": "^6.0.0",
|
"@types/semver": "^7.3.1",
|
||||||
"@types/jest": "^24.0.23",
|
"@types/jest": "^26.0.5",
|
||||||
"@types/node": "^12.7.12",
|
"@types/node": "^14.0.25",
|
||||||
"@typescript-eslint/parser": "^2.8.0",
|
"@typescript-eslint/parser": "^3.7.0",
|
||||||
"@zeit/ncc": "^0.20.5",
|
"@zeit/ncc": "^0.20.5",
|
||||||
"eslint": "^5.16.0",
|
"eslint": "^5.16.0",
|
||||||
"eslint-plugin-github": "^2.0.0",
|
"eslint-plugin-github": "^4.0.1",
|
||||||
"eslint-plugin-jest": "^22.21.0",
|
"eslint-plugin-jest": "^23.18.0",
|
||||||
"jest": "^24.9.0",
|
"jest": "^24.9.0",
|
||||||
"jest-circus": "^24.9.0",
|
"jest-circus": "^26.1.0",
|
||||||
"js-yaml": "^3.13.1",
|
"js-yaml": "^3.13.1",
|
||||||
"prettier": "^1.19.1",
|
"prettier": "^1.19.1",
|
||||||
"ts-jest": "^24.2.0",
|
"ts-jest": "^24.2.0",
|
||||||
"typescript": "^3.6.4"
|
"typescript": "^3.9.7"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,6 +37,8 @@ export interface IssueProcessorOptions {
|
|||||||
repoToken: string;
|
repoToken: string;
|
||||||
staleIssueMessage: string;
|
staleIssueMessage: string;
|
||||||
stalePrMessage: string;
|
stalePrMessage: string;
|
||||||
|
closeIssueMessage: string;
|
||||||
|
closePrMessage: string;
|
||||||
daysBeforeStale: number;
|
daysBeforeStale: number;
|
||||||
daysBeforeClose: number;
|
daysBeforeClose: number;
|
||||||
staleIssueLabel: string;
|
staleIssueLabel: string;
|
||||||
@@ -47,6 +49,9 @@ export interface IssueProcessorOptions {
|
|||||||
operationsPerRun: number;
|
operationsPerRun: number;
|
||||||
removeStaleWhenUpdated: boolean;
|
removeStaleWhenUpdated: boolean;
|
||||||
debugOnly: boolean;
|
debugOnly: boolean;
|
||||||
|
ascending: boolean;
|
||||||
|
skipStaleIssueMessage: boolean;
|
||||||
|
skipStalePrMessage: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***
|
/***
|
||||||
@@ -55,7 +60,7 @@ export interface IssueProcessorOptions {
|
|||||||
export class IssueProcessor {
|
export class IssueProcessor {
|
||||||
readonly client: github.GitHub;
|
readonly client: github.GitHub;
|
||||||
readonly options: IssueProcessorOptions;
|
readonly options: IssueProcessorOptions;
|
||||||
private operationsLeft: number = 0;
|
private operationsLeft = 0;
|
||||||
|
|
||||||
readonly staleIssues: Issue[] = [];
|
readonly staleIssues: Issue[] = [];
|
||||||
readonly closedIssues: Issue[] = [];
|
readonly closedIssues: Issue[] = [];
|
||||||
@@ -96,7 +101,7 @@ export class IssueProcessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async processIssues(page: number = 1): Promise<number> {
|
async processIssues(page = 1): Promise<number> {
|
||||||
// get the next batch of issues
|
// get the next batch of issues
|
||||||
const issues: Issue[] = await this.getIssues(page);
|
const issues: Issue[] = await this.getIssues(page);
|
||||||
this.operationsLeft -= 1;
|
this.operationsLeft -= 1;
|
||||||
@@ -117,15 +122,22 @@ export class IssueProcessor {
|
|||||||
const staleMessage: string = isPr
|
const staleMessage: string = isPr
|
||||||
? this.options.stalePrMessage
|
? this.options.stalePrMessage
|
||||||
: this.options.staleIssueMessage;
|
: this.options.staleIssueMessage;
|
||||||
|
const closeMessage: string = isPr
|
||||||
|
? this.options.closePrMessage
|
||||||
|
: this.options.closeIssueMessage;
|
||||||
const staleLabel: string = isPr
|
const staleLabel: string = isPr
|
||||||
? this.options.stalePrLabel
|
? this.options.stalePrLabel
|
||||||
: this.options.staleIssueLabel;
|
: this.options.staleIssueLabel;
|
||||||
const exemptLabels = IssueProcessor.parseCommaSeparatedString(
|
const exemptLabels = IssueProcessor.parseCommaSeparatedString(
|
||||||
isPr ? this.options.exemptPrLabels : this.options.exemptIssueLabels
|
isPr ? this.options.exemptPrLabels : this.options.exemptIssueLabels
|
||||||
);
|
);
|
||||||
|
const skipMessage = isPr
|
||||||
|
? this.options.skipStalePrMessage
|
||||||
|
: this.options.skipStaleIssueMessage;
|
||||||
const issueType: string = isPr ? 'pr' : 'issue';
|
const issueType: string = isPr ? 'pr' : 'issue';
|
||||||
|
const shouldMarkWhenStale = this.options.daysBeforeStale > -1;
|
||||||
|
|
||||||
if (!staleMessage) {
|
if (!staleMessage && shouldMarkWhenStale) {
|
||||||
core.info(`Skipping ${issueType} due to empty stale message`);
|
core.info(`Skipping ${issueType} due to empty stale message`);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -159,18 +171,23 @@ export class IssueProcessor {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// determine if this issue needs to be marked stale first
|
// determine if this issue needs to be marked stale first
|
||||||
if (!isStale && shouldBeStale) {
|
if (!isStale && shouldBeStale && shouldMarkWhenStale) {
|
||||||
core.info(
|
core.info(
|
||||||
`Marking ${issueType} stale because it was last updated on ${issue.updated_at} and it does not have a stale label`
|
`Marking ${issueType} stale because it was last updated on ${issue.updated_at} and it does not have a stale label`
|
||||||
);
|
);
|
||||||
await this.markStale(issue, staleMessage, staleLabel);
|
await this.markStale(issue, staleMessage, staleLabel, skipMessage);
|
||||||
isStale = true; // this issue is now considered stale
|
isStale = true; // this issue is now considered stale
|
||||||
}
|
}
|
||||||
|
|
||||||
// process the issue if it was marked stale
|
// process the issue if it was marked stale
|
||||||
if (isStale) {
|
if (isStale) {
|
||||||
core.info(`Found a stale ${issueType}`);
|
core.info(`Found a stale ${issueType}`);
|
||||||
await this.processStaleIssue(issue, issueType, staleLabel);
|
await this.processStaleIssue(
|
||||||
|
issue,
|
||||||
|
issueType,
|
||||||
|
staleLabel,
|
||||||
|
closeMessage
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,7 +204,8 @@ export class IssueProcessor {
|
|||||||
private async processStaleIssue(
|
private async processStaleIssue(
|
||||||
issue: Issue,
|
issue: Issue,
|
||||||
issueType: string,
|
issueType: string,
|
||||||
staleLabel: string
|
staleLabel: string,
|
||||||
|
closeMessage?: string
|
||||||
) {
|
) {
|
||||||
const markedStaleOn: string =
|
const markedStaleOn: string =
|
||||||
(await this.getLabelCreationDate(issue, staleLabel)) || issue.updated_at;
|
(await this.getLabelCreationDate(issue, staleLabel)) || issue.updated_at;
|
||||||
@@ -224,7 +242,7 @@ export class IssueProcessor {
|
|||||||
core.info(
|
core.info(
|
||||||
`Closing ${issueType} because it was last updated on ${issue.updated_at}`
|
`Closing ${issueType} because it was last updated on ${issue.updated_at}`
|
||||||
);
|
);
|
||||||
await this.closeIssue(issue);
|
await this.closeIssue(issue, closeMessage);
|
||||||
} else {
|
} else {
|
||||||
core.info(
|
core.info(
|
||||||
`Stale ${issueType} is not old enough to close yet (hasComments? ${issueHasComments}, hasUpdate? ${issueHasUpdate}`
|
`Stale ${issueType} is not old enough to close yet (hasComments? ${issueHasComments}, hasUpdate? ${issueHasUpdate}`
|
||||||
@@ -292,6 +310,7 @@ export class IssueProcessor {
|
|||||||
state: 'open',
|
state: 'open',
|
||||||
labels: this.options.onlyLabels,
|
labels: this.options.onlyLabels,
|
||||||
per_page: 100,
|
per_page: 100,
|
||||||
|
direction: this.options.ascending ? 'asc' : 'desc',
|
||||||
page
|
page
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -306,7 +325,8 @@ export class IssueProcessor {
|
|||||||
private async markStale(
|
private async markStale(
|
||||||
issue: Issue,
|
issue: Issue,
|
||||||
staleMessage: string,
|
staleMessage: string,
|
||||||
staleLabel: string
|
staleLabel: string,
|
||||||
|
skipMessage: boolean
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
core.info(`Marking issue #${issue.number} - ${issue.title} as stale`);
|
core.info(`Marking issue #${issue.number} - ${issue.title} as stale`);
|
||||||
|
|
||||||
@@ -323,15 +343,17 @@ export class IssueProcessor {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
if (!skipMessage) {
|
||||||
await this.client.issues.createComment({
|
try {
|
||||||
owner: github.context.repo.owner,
|
await this.client.issues.createComment({
|
||||||
repo: github.context.repo.repo,
|
owner: github.context.repo.owner,
|
||||||
issue_number: issue.number,
|
repo: github.context.repo.repo,
|
||||||
body: staleMessage
|
issue_number: issue.number,
|
||||||
});
|
body: staleMessage
|
||||||
} catch (error) {
|
});
|
||||||
core.error(`Error creating a comment: ${error.message}`);
|
} catch (error) {
|
||||||
|
core.error(`Error creating a comment: ${error.message}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -347,7 +369,7 @@ export class IssueProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Close an issue based on staleness
|
// Close an issue based on staleness
|
||||||
private async closeIssue(issue: Issue): Promise<void> {
|
private async closeIssue(issue: Issue, closeMessage?: string): Promise<void> {
|
||||||
core.info(
|
core.info(
|
||||||
`Closing issue #${issue.number} - ${issue.title} for being stale`
|
`Closing issue #${issue.number} - ${issue.title} for being stale`
|
||||||
);
|
);
|
||||||
@@ -360,6 +382,19 @@ export class IssueProcessor {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (closeMessage) {
|
||||||
|
try {
|
||||||
|
await this.client.issues.createComment({
|
||||||
|
owner: github.context.repo.owner,
|
||||||
|
repo: github.context.repo.repo,
|
||||||
|
issue_number: issue.number,
|
||||||
|
body: closeMessage
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
core.error(`Error creating a comment: ${error.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await this.client.issues.update({
|
await this.client.issues.update({
|
||||||
owner: github.context.repo.owner,
|
owner: github.context.repo.owner,
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ function getAndValidateArgs(): IssueProcessorOptions {
|
|||||||
repoToken: core.getInput('repo-token', {required: true}),
|
repoToken: core.getInput('repo-token', {required: true}),
|
||||||
staleIssueMessage: core.getInput('stale-issue-message'),
|
staleIssueMessage: core.getInput('stale-issue-message'),
|
||||||
stalePrMessage: core.getInput('stale-pr-message'),
|
stalePrMessage: core.getInput('stale-pr-message'),
|
||||||
|
closeIssueMessage: core.getInput('close-issue-message'),
|
||||||
|
closePrMessage: core.getInput('close-pr-message'),
|
||||||
daysBeforeStale: parseInt(
|
daysBeforeStale: parseInt(
|
||||||
core.getInput('days-before-stale', {required: true})
|
core.getInput('days-before-stale', {required: true})
|
||||||
),
|
),
|
||||||
@@ -35,7 +37,10 @@ function getAndValidateArgs(): IssueProcessorOptions {
|
|||||||
removeStaleWhenUpdated: !(
|
removeStaleWhenUpdated: !(
|
||||||
core.getInput('remove-stale-when-updated') === 'false'
|
core.getInput('remove-stale-when-updated') === 'false'
|
||||||
),
|
),
|
||||||
debugOnly: core.getInput('debug-only') === 'true'
|
debugOnly: core.getInput('debug-only') === 'true',
|
||||||
|
ascending: core.getInput('ascending') === 'true',
|
||||||
|
skipStalePrMessage: core.getInput('skip-stale-pr-message') === 'true',
|
||||||
|
skipStaleIssueMessage: core.getInput('skip-stale-issue-message') === 'true'
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const numberInput of [
|
for (const numberInput of [
|
||||||
|
|||||||
Reference in New Issue
Block a user