Compare commits

...

16 Commits

Author SHA1 Message Date
Ross Brodbeck
1e5e734da7 Update to latest actions and octokit libraries (#124)
Upgrade to latest libraries but use "any" for the client until I figure out how to use the right type
2020-07-24 08:44:53 -04:00
Ross Brodbeck
5420e6bbac Update eslint config to latest (#123) 2020-07-24 08:17:50 -04:00
Harshit Pant
fbaa974a12 Add skip-stale-pr-message and skip-stale-issue-message (#119)
This introduces two new flags `skip-stale-issue-message` and `skip-stale-pr-message` which would skip the message addition if these are set to true.

They are backward compatible as empty `stale-issue-message` or `stale-pr-message` will take precedence over them
2020-07-24 08:08:48 -04:00
dependabot[bot]
213e2e3dbb Bump @types/node from 12.12.35 to 14.0.25 (#122)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 12.12.35 to 14.0.25.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-07-24 08:00:11 -04:00
dependabot[bot]
d54efb59cb Bump typescript from 3.8.3 to 3.9.7 (#120)
Bumps [typescript](https://github.com/Microsoft/TypeScript) from 3.8.3 to 3.9.7.
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Commits](https://github.com/Microsoft/TypeScript/compare/v3.8.3...v3.9.7)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-07-24 07:59:57 -04:00
dependabot[bot]
0c5c86b836 Bump @typescript-eslint/parser from 2.28.0 to 3.7.0 (#116)
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 2.28.0 to 3.7.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v3.7.0/packages/parser)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-07-23 14:10:40 -04:00
dependabot[bot]
ade4f65ff5 Bump @types/semver from 6.2.1 to 7.3.1 (#110)
Bumps [@types/semver](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/semver) from 6.2.1 to 7.3.1.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/semver)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-07-20 08:04:53 -04:00
dependabot[bot]
1200f63335 Bump semver from 6.3.0 to 7.3.2 (#111)
Bumps [semver](https://github.com/npm/node-semver) from 6.3.0 to 7.3.2.
- [Release notes](https://github.com/npm/node-semver/releases)
- [Changelog](https://github.com/npm/node-semver/blob/master/CHANGELOG.md)
- [Commits](https://github.com/npm/node-semver/compare/v6.3.0...v7.3.2)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-07-20 08:04:44 -04:00
dependabot[bot]
321a0c1996 Bump eslint-plugin-jest from 22.21.0 to 23.18.0 (#112)
Bumps [eslint-plugin-jest](https://github.com/jest-community/eslint-plugin-jest) from 22.21.0 to 23.18.0.
- [Release notes](https://github.com/jest-community/eslint-plugin-jest/releases)
- [Changelog](https://github.com/jest-community/eslint-plugin-jest/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jest-community/eslint-plugin-jest/compare/v22.21.0...v23.18.0)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-07-20 08:00:09 -04:00
dependabot[bot]
6599f03bfe Bump @types/jest from 24.9.1 to 26.0.5 (#113)
Bumps [@types/jest](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/jest) from 24.9.1 to 26.0.5.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/jest)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-07-20 07:59:53 -04:00
dependabot[bot]
facad6de84 Bump jest-circus from 24.9.0 to 26.1.0 (#109)
Bumps [jest-circus](https://github.com/facebook/jest/tree/HEAD/packages/jest-circus) from 24.9.0 to 26.1.0.
- [Release notes](https://github.com/facebook/jest/releases)
- [Changelog](https://github.com/facebook/jest/blob/master/CHANGELOG.md)
- [Commits](https://github.com/facebook/jest/commits/v26.1.0/packages/jest-circus)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-07-20 07:58:36 -04:00
Ross Brodbeck
2ede1ed234 Create dependabot.yml 2020-07-20 07:49:47 -04:00
dependabot[bot]
c95554e7b3 Bump lodash from 4.17.15 to 4.17.19 (#108)
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.15 to 4.17.19.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.15...4.17.19)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-07-20 07:48:55 -04:00
Ross Brodbeck
93883857f8 Update test.yml 2020-07-13 16:22:33 -04:00
Phillip Johnsen
f111c4f385 Allow for issues/PRs to be closed after manually being marked as stale (#103)
Previously this action would stop and skip all issues or pull requests
it found if no `stale-issue-message | stale-pr-message` option had
been configured.

Configuring `days-before-stale: -1` will activate that behaviour.
2020-07-13 16:20:45 -04:00
Phillip Johnsen
c2daa6ff62 Avoid changing default options in tests (#102)
Primarily because changing the default options shared amongst tests will
affect other tests.
2020-07-13 16:18:51 -04:00
10 changed files with 4149 additions and 21877 deletions

View File

@@ -1,6 +1,6 @@
{
"plugins": ["jest", "@typescript-eslint"],
"extends": ["plugin:github/es6"],
"extends": ["plugin:github/recommended"],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 9,
@@ -16,11 +16,10 @@
"@typescript-eslint/no-require-imports": "error",
"@typescript-eslint/array-type": "error",
"@typescript-eslint/await-thenable": "error",
"@typescript-eslint/ban-ts-ignore": "error",
"@typescript-eslint/ban-ts-comment": "error",
"camelcase": "off",
"@typescript-eslint/class-name-casing": "error",
"@typescript-eslint/consistent-type-assertions": "error",
"@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-empty-interface": "error",
"@typescript-eslint/no-explicit-any": "off",
@@ -30,7 +29,6 @@
"@typescript-eslint/no-misused-new": "error",
"@typescript-eslint/no-namespace": "error",
"@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-type-assertion": "error",
"@typescript-eslint/no-useless-constructor": "error",
@@ -38,7 +36,6 @@
"@typescript-eslint/prefer-for-of": "warn",
"@typescript-eslint/prefer-function-type": "warn",
"@typescript-eslint/prefer-includes": "error",
"@typescript-eslint/prefer-interface": "error",
"@typescript-eslint/prefer-string-starts-ends-with": "error",
"@typescript-eslint/promise-function-async": "error",
"@typescript-eslint/require-array-sort-compare": "error",

9
.github/dependabot.yml vendored Normal file
View 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'

View File

@@ -3,7 +3,7 @@ on: # rebuild any PRs and main branch changes
pull_request:
push:
branches:
- master
- main
- 'releases/*'
jobs:

View File

@@ -31,7 +31,7 @@ function generateIssue(
};
}
const DefaultProcessorOptions: IssueProcessorOptions = {
const DefaultProcessorOptions: IssueProcessorOptions = Object.freeze({
repoToken: 'none',
staleIssueMessage: 'This issue is stale',
stalePrMessage: 'This PR is stale',
@@ -47,8 +47,10 @@ const DefaultProcessorOptions: IssueProcessorOptions = {
operationsPerRun: 100,
debugOnly: true,
removeStaleWhenUpdated: false,
ascending: false
};
ascending: false,
skipStaleIssueMessage: false,
skipStalePrMessage: false
});
test('empty issue list results in 1 operation', async () => {
const processor = new IssueProcessor(
@@ -109,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);
});
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 () => {
// issue should be from 2 days ago so it will be
// stale but not close-able, based on default settings
@@ -183,6 +210,60 @@ test('processing a stale PR will close it', async () => {
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 () => {
const TestIssueList: Issue[] = [
generateIssue(
@@ -517,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;
const processor = new IssueProcessor(
@@ -547,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;
const processor = new IssueProcessor(
@@ -577,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.daysBeforeClose = 1; // closes after 6 days
@@ -609,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.daysBeforeClose = 1; // closes after 6 days
@@ -640,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.daysBeforeClose = 20; // closes after 25 days
@@ -658,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.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);
});

View File

@@ -14,7 +14,7 @@ inputs:
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:
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
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.'
@@ -46,6 +46,12 @@ inputs:
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:
using: 'node12'
main: 'dist/index.js'

22685
dist/index.js vendored

File diff suppressed because it is too large Load Diff

2950
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -26,24 +26,24 @@
"license": "MIT",
"dependencies": {
"@actions/core": "^1.2.4",
"@actions/github": "^2.2.0",
"@octokit/rest": "^16.43.1",
"semver": "^6.1.1"
"@actions/github": "^4.0.0",
"@octokit/rest": "^18.0.2",
"semver": "^7.3.2"
},
"devDependencies": {
"@types/semver": "^6.0.0",
"@types/jest": "^24.0.23",
"@types/node": "^12.7.12",
"@typescript-eslint/parser": "^2.8.0",
"@types/semver": "^7.3.1",
"@types/jest": "^26.0.5",
"@types/node": "^14.0.25",
"@typescript-eslint/parser": "^3.7.0",
"@zeit/ncc": "^0.20.5",
"eslint": "^5.16.0",
"eslint-plugin-github": "^2.0.0",
"eslint-plugin-jest": "^22.21.0",
"eslint-plugin-github": "^4.0.1",
"eslint-plugin-jest": "^23.18.0",
"jest": "^24.9.0",
"jest-circus": "^24.9.0",
"jest-circus": "^26.1.0",
"js-yaml": "^3.13.1",
"prettier": "^1.19.1",
"ts-jest": "^24.2.0",
"typescript": "^3.6.4"
"typescript": "^3.9.7"
}
}

View File

@@ -1,8 +1,6 @@
import * as core from '@actions/core';
import * as github from '@actions/github';
import {Octokit} from '@octokit/rest';
type OctoKitIssueList = Octokit.Response<Octokit.IssuesListForRepoResponse>;
import {context, getOctokit} from '@actions/github';
import {GetResponseTypeFromEndpointMethod} from '@octokit/types';
export interface Issue {
title: string;
@@ -50,15 +48,17 @@ export interface IssueProcessorOptions {
removeStaleWhenUpdated: boolean;
debugOnly: boolean;
ascending: boolean;
skipStaleIssueMessage: boolean;
skipStalePrMessage: boolean;
}
/***
* Handle processing of issues for staleness/closure.
*/
export class IssueProcessor {
readonly client: github.GitHub;
readonly client: any; // need to make this the correct type
readonly options: IssueProcessorOptions;
private operationsLeft: number = 0;
private operationsLeft = 0;
readonly staleIssues: Issue[] = [];
readonly closedIssues: Issue[] = [];
@@ -78,7 +78,7 @@ export class IssueProcessor {
) {
this.options = options;
this.operationsLeft = options.operationsPerRun;
this.client = new github.GitHub(options.repoToken);
this.client = getOctokit(options.repoToken);
if (getIssues) {
this.getIssues = getIssues;
@@ -99,7 +99,7 @@ export class IssueProcessor {
}
}
async processIssues(page: number = 1): Promise<number> {
async processIssues(page = 1): Promise<number> {
// get the next batch of issues
const issues: Issue[] = await this.getIssues(page);
this.operationsLeft -= 1;
@@ -129,9 +129,13 @@ export class IssueProcessor {
const exemptLabels = IssueProcessor.parseCommaSeparatedString(
isPr ? this.options.exemptPrLabels : this.options.exemptIssueLabels
);
const skipMessage = isPr
? this.options.skipStalePrMessage
: this.options.skipStaleIssueMessage;
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`);
continue;
}
@@ -165,11 +169,11 @@ export class IssueProcessor {
);
// 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`
);
await this.markStale(issue, staleMessage, staleLabel);
await this.markStale(issue, staleMessage, staleLabel, skipMessage);
isStale = true; // this issue is now considered stale
}
@@ -262,12 +266,11 @@ export class IssueProcessor {
const filteredComments = comments.filter(
comment =>
comment.user.type === 'User' &&
comment.user.login !== github.context.actor
comment.user.type === 'User' && comment.user.login !== context.actor
);
core.info(
`Comments not made by ${github.context.actor} or another bot: ${filteredComments.length}`
`Comments not made by ${context.actor} or another bot: ${filteredComments.length}`
);
// if there are any user comments returned
@@ -282,8 +285,8 @@ export class IssueProcessor {
// find any comments since date on the given issue
try {
const comments = await this.client.issues.listComments({
owner: github.context.repo.owner,
repo: github.context.repo.repo,
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issueNumber,
since: sinceDate
});
@@ -296,11 +299,15 @@ export class IssueProcessor {
// grab issues from github in baches of 100
private async getIssues(page: number): Promise<Issue[]> {
// generate type for response
const endpoint = this.client.issues.listForRepo;
type OctoKitIssueList = GetResponseTypeFromEndpointMethod<typeof endpoint>;
try {
const issueResult: OctoKitIssueList = await this.client.issues.listForRepo(
{
owner: github.context.repo.owner,
repo: github.context.repo.repo,
owner: context.repo.owner,
repo: context.repo.repo,
state: 'open',
labels: this.options.onlyLabels,
per_page: 100,
@@ -319,7 +326,8 @@ export class IssueProcessor {
private async markStale(
issue: Issue,
staleMessage: string,
staleLabel: string
staleLabel: string,
skipMessage: boolean
): Promise<void> {
core.info(`Marking issue #${issue.number} - ${issue.title} as stale`);
@@ -336,21 +344,23 @@ export class IssueProcessor {
return;
}
try {
await this.client.issues.createComment({
owner: github.context.repo.owner,
repo: github.context.repo.repo,
issue_number: issue.number,
body: staleMessage
});
} catch (error) {
core.error(`Error creating a comment: ${error.message}`);
if (!skipMessage) {
try {
await this.client.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue.number,
body: staleMessage
});
} catch (error) {
core.error(`Error creating a comment: ${error.message}`);
}
}
try {
await this.client.issues.addLabels({
owner: github.context.repo.owner,
repo: github.context.repo.repo,
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue.number,
labels: [staleLabel]
});
@@ -376,8 +386,8 @@ export class IssueProcessor {
if (closeMessage) {
try {
await this.client.issues.createComment({
owner: github.context.repo.owner,
repo: github.context.repo.repo,
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue.number,
body: closeMessage
});
@@ -388,8 +398,8 @@ export class IssueProcessor {
try {
await this.client.issues.update({
owner: github.context.repo.owner,
repo: github.context.repo.repo,
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue.number,
state: 'closed'
});
@@ -414,8 +424,8 @@ export class IssueProcessor {
try {
await this.client.issues.removeLabel({
owner: github.context.repo.owner,
repo: github.context.repo.repo,
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue.number,
name: encodeURIComponent(label) // A label can have a "?" in the name
});
@@ -435,8 +445,8 @@ export class IssueProcessor {
this.operationsLeft -= 1;
const options = this.client.issues.listEvents.endpoint.merge({
owner: github.context.repo.owner,
repo: github.context.repo.repo,
owner: context.repo.owner,
repo: context.repo.repo,
per_page: 100,
issue_number: issue.number
});

View File

@@ -38,7 +38,9 @@ function getAndValidateArgs(): IssueProcessorOptions {
core.getInput('remove-stale-when-updated') === 'false'
),
debugOnly: core.getInput('debug-only') === 'true',
ascending: core.getInput('ascending') === '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 [