mirror of
https://github.com/actions/stale.git
synced 2026-01-01 12:58:18 +00:00
Compare commits
6 Commits
v6.0.1
...
johnsudol/
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fde7d4444e | ||
|
|
e27c9afd63 | ||
|
|
52086c38b6 | ||
|
|
65b52aff67 | ||
|
|
0d6f830071 | ||
|
|
b909bf8927 |
@@ -1,5 +1,9 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
# [6.0.1]
|
||||||
|
|
||||||
|
Update @actions/core to v1.10.0 ([#839](https://github.com/actions/stale/pull/839))
|
||||||
|
|
||||||
# [6.0.0]
|
# [6.0.0]
|
||||||
|
|
||||||
:warning: Breaking change :warning:
|
:warning: Breaking change :warning:
|
||||||
|
|||||||
@@ -246,8 +246,7 @@ Required Permission: `pull-requests: write`
|
|||||||
|
|
||||||
#### exempt-issue-labels
|
#### exempt-issue-labels
|
||||||
|
|
||||||
The label(s) that can exempt to automatically mark as stale the issues.
|
A comma separated list of labels, that prevent the issue from being marked as stale. (e.g: `question,bug,wip`)
|
||||||
It can be a comma separated list of labels (e.g: `question,bug`).
|
|
||||||
|
|
||||||
If unset (or an empty string), this option will not alter the stale workflow.
|
If unset (or an empty string), this option will not alter the stale workflow.
|
||||||
|
|
||||||
|
|||||||
@@ -1998,6 +1998,84 @@ test('processing an issue opened since 2 days and with the option "daysBeforeIss
|
|||||||
expect(processor.closedIssues).toHaveLength(0);
|
expect(processor.closedIssues).toHaveLength(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('processing an issue opened since 1 hour and with the option "daysBeforeIssueStale" at 0.1666666667 (4 hours) will not make it stale', async () => {
|
||||||
|
expect.assertions(2);
|
||||||
|
const opts: IIssuesProcessorOptions = {
|
||||||
|
...DefaultProcessorOptions,
|
||||||
|
daysBeforeStale: 10,
|
||||||
|
daysBeforeIssueStale: 0.1666666667
|
||||||
|
};
|
||||||
|
const issueDate = new Date();
|
||||||
|
issueDate.setHours(issueDate.getHours() - 1);
|
||||||
|
const TestIssueList: Issue[] = [
|
||||||
|
generateIssue(opts, 1, 'An issue with no label', issueDate.toISOString())
|
||||||
|
];
|
||||||
|
const processor = new IssuesProcessorMock(
|
||||||
|
opts,
|
||||||
|
async p => (p === 1 ? TestIssueList : []),
|
||||||
|
async () => [],
|
||||||
|
async () => new Date().toISOString()
|
||||||
|
);
|
||||||
|
|
||||||
|
// process our fake issue list
|
||||||
|
await processor.processIssues(1);
|
||||||
|
|
||||||
|
expect(processor.staleIssues).toHaveLength(0);
|
||||||
|
expect(processor.closedIssues).toHaveLength(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('processing an issue opened since 4 hours and with the option "daysBeforeIssueStale" at 0.1666666667 (4 hours) will make it stale', async () => {
|
||||||
|
expect.assertions(2);
|
||||||
|
const opts: IIssuesProcessorOptions = {
|
||||||
|
...DefaultProcessorOptions,
|
||||||
|
daysBeforeStale: 10,
|
||||||
|
daysBeforeIssueStale: 0.1666666667
|
||||||
|
};
|
||||||
|
const issueDate = new Date();
|
||||||
|
issueDate.setHours(issueDate.getHours() - 4);
|
||||||
|
const TestIssueList: Issue[] = [
|
||||||
|
generateIssue(opts, 1, 'An issue with no label', issueDate.toISOString())
|
||||||
|
];
|
||||||
|
const processor = new IssuesProcessorMock(
|
||||||
|
opts,
|
||||||
|
async p => (p === 1 ? TestIssueList : []),
|
||||||
|
async () => [],
|
||||||
|
async () => new Date().toISOString()
|
||||||
|
);
|
||||||
|
|
||||||
|
// process our fake issue list
|
||||||
|
await processor.processIssues(1);
|
||||||
|
|
||||||
|
expect(processor.staleIssues).toHaveLength(1);
|
||||||
|
expect(processor.closedIssues).toHaveLength(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('processing an issue opened since 5 hours and with the option "daysBeforeIssueStale" at 0.1666666667 (4 hours) will make it stale', async () => {
|
||||||
|
expect.assertions(2);
|
||||||
|
const opts: IIssuesProcessorOptions = {
|
||||||
|
...DefaultProcessorOptions,
|
||||||
|
daysBeforeStale: 10,
|
||||||
|
daysBeforeIssueStale: 0.1666666667
|
||||||
|
};
|
||||||
|
const issueDate = new Date();
|
||||||
|
issueDate.setHours(issueDate.getHours() - 5);
|
||||||
|
const TestIssueList: Issue[] = [
|
||||||
|
generateIssue(opts, 1, 'An issue with no label', issueDate.toISOString())
|
||||||
|
];
|
||||||
|
const processor = new IssuesProcessorMock(
|
||||||
|
opts,
|
||||||
|
async p => (p === 1 ? TestIssueList : []),
|
||||||
|
async () => [],
|
||||||
|
async () => new Date().toISOString()
|
||||||
|
);
|
||||||
|
|
||||||
|
// process our fake issue list
|
||||||
|
await processor.processIssues(1);
|
||||||
|
|
||||||
|
expect(processor.staleIssues).toHaveLength(1);
|
||||||
|
expect(processor.closedIssues).toHaveLength(0);
|
||||||
|
});
|
||||||
|
|
||||||
test('processing a pull request opened since 2 days and with the option "daysBeforePrStale" at 3 will not make it stale', async () => {
|
test('processing a pull request opened since 2 days and with the option "daysBeforePrStale" at 3 will not make it stale', async () => {
|
||||||
expect.assertions(2);
|
expect.assertions(2);
|
||||||
const opts: IIssuesProcessorOptions = {
|
const opts: IIssuesProcessorOptions = {
|
||||||
@@ -2097,6 +2175,105 @@ test('processing a pull request opened since 2 days and with the option "daysBef
|
|||||||
expect(processor.closedIssues).toHaveLength(0);
|
expect(processor.closedIssues).toHaveLength(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('processing a pull request opened since 1 hour and with the option "daysBeforePrStale" at 0.1666666667 (4 hours) will not make it stale', async () => {
|
||||||
|
expect.assertions(2);
|
||||||
|
const opts: IIssuesProcessorOptions = {
|
||||||
|
...DefaultProcessorOptions,
|
||||||
|
daysBeforeStale: 10,
|
||||||
|
daysBeforePrStale: 0.1666666667
|
||||||
|
};
|
||||||
|
const issueDate = new Date();
|
||||||
|
issueDate.setHours(issueDate.getHours() - 1);
|
||||||
|
const TestIssueList: Issue[] = [
|
||||||
|
generateIssue(
|
||||||
|
opts,
|
||||||
|
1,
|
||||||
|
'A pull request with no label',
|
||||||
|
issueDate.toISOString(),
|
||||||
|
issueDate.toISOString(),
|
||||||
|
true
|
||||||
|
)
|
||||||
|
];
|
||||||
|
const processor = new IssuesProcessorMock(
|
||||||
|
opts,
|
||||||
|
async p => (p === 1 ? TestIssueList : []),
|
||||||
|
async () => [],
|
||||||
|
async () => new Date().toISOString()
|
||||||
|
);
|
||||||
|
|
||||||
|
// process our fake issue list
|
||||||
|
await processor.processIssues(1);
|
||||||
|
|
||||||
|
expect(processor.staleIssues).toHaveLength(0);
|
||||||
|
expect(processor.closedIssues).toHaveLength(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('processing a pull request opened since 4 hours and with the option "daysBeforePrStale" at 0.1666666667 (4 hours) will make it stale', async () => {
|
||||||
|
expect.assertions(2);
|
||||||
|
const opts: IIssuesProcessorOptions = {
|
||||||
|
...DefaultProcessorOptions,
|
||||||
|
daysBeforeStale: 10,
|
||||||
|
daysBeforePrStale: 0.1666666667
|
||||||
|
};
|
||||||
|
const issueDate = new Date();
|
||||||
|
issueDate.setHours(issueDate.getHours() - 4);
|
||||||
|
const TestIssueList: Issue[] = [
|
||||||
|
generateIssue(
|
||||||
|
opts,
|
||||||
|
1,
|
||||||
|
'A pull request with no label',
|
||||||
|
issueDate.toISOString(),
|
||||||
|
issueDate.toISOString(),
|
||||||
|
true
|
||||||
|
)
|
||||||
|
];
|
||||||
|
const processor = new IssuesProcessorMock(
|
||||||
|
opts,
|
||||||
|
async p => (p === 1 ? TestIssueList : []),
|
||||||
|
async () => [],
|
||||||
|
async () => new Date().toISOString()
|
||||||
|
);
|
||||||
|
|
||||||
|
// process our fake issue list
|
||||||
|
await processor.processIssues(1);
|
||||||
|
|
||||||
|
expect(processor.staleIssues).toHaveLength(1);
|
||||||
|
expect(processor.closedIssues).toHaveLength(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('processing a pull request opened since 5 hours and with the option "daysBeforePrStale" at 0.1666666667 (4 hours) will make it stale', async () => {
|
||||||
|
expect.assertions(2);
|
||||||
|
const opts: IIssuesProcessorOptions = {
|
||||||
|
...DefaultProcessorOptions,
|
||||||
|
daysBeforeStale: 10,
|
||||||
|
daysBeforePrStale: 0.1666666667
|
||||||
|
};
|
||||||
|
const issueDate = new Date();
|
||||||
|
issueDate.setHours(issueDate.getHours() - 5);
|
||||||
|
const TestIssueList: Issue[] = [
|
||||||
|
generateIssue(
|
||||||
|
opts,
|
||||||
|
1,
|
||||||
|
'A pull request with no label',
|
||||||
|
issueDate.toISOString(),
|
||||||
|
issueDate.toISOString(),
|
||||||
|
true
|
||||||
|
)
|
||||||
|
];
|
||||||
|
const processor = new IssuesProcessorMock(
|
||||||
|
opts,
|
||||||
|
async p => (p === 1 ? TestIssueList : []),
|
||||||
|
async () => [],
|
||||||
|
async () => new Date().toISOString()
|
||||||
|
);
|
||||||
|
|
||||||
|
// process our fake issue list
|
||||||
|
await processor.processIssues(1);
|
||||||
|
|
||||||
|
expect(processor.staleIssues).toHaveLength(1);
|
||||||
|
expect(processor.closedIssues).toHaveLength(0);
|
||||||
|
});
|
||||||
|
|
||||||
test('processing a previously closed issue with a close label will remove the close label', async () => {
|
test('processing a previously closed issue with a close label will remove the close label', async () => {
|
||||||
expect.assertions(1);
|
expect.assertions(1);
|
||||||
const opts: IIssuesProcessorOptions = {
|
const opts: IIssuesProcessorOptions = {
|
||||||
|
|||||||
26
dist/index.js
vendored
26
dist/index.js
vendored
@@ -381,7 +381,7 @@ class IssuesProcessor {
|
|||||||
this.options = options;
|
this.options = options;
|
||||||
this.client = github_1.getOctokit(this.options.repoToken);
|
this.client = github_1.getOctokit(this.options.repoToken);
|
||||||
this.operations = new stale_operations_1.StaleOperations(this.options);
|
this.operations = new stale_operations_1.StaleOperations(this.options);
|
||||||
this._logger.info(logger_service_1.LoggerService.yellow(`Starting the stale action process...`));
|
this._logger.info(logger_service_1.LoggerService.yellow(`Starting the stale action process... logging`));
|
||||||
if (this.options.debugOnly) {
|
if (this.options.debugOnly) {
|
||||||
this._logger.warning(logger_service_1.LoggerService.yellowBright(`Executing in debug mode!`));
|
this._logger.warning(logger_service_1.LoggerService.yellowBright(`Executing in debug mode!`));
|
||||||
this._logger.warning(logger_service_1.LoggerService.yellowBright(`The debug output will be written but no issues/PRs will be processed.`));
|
this._logger.warning(logger_service_1.LoggerService.yellowBright(`The debug output will be written but no issues/PRs will be processed.`));
|
||||||
@@ -526,14 +526,15 @@ class IssuesProcessor {
|
|||||||
issueLogger.info(`This $$type has a stale label`);
|
issueLogger.info(`This $$type has a stale label`);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
issueLogger.info(`This $$type hasn't a stale label`);
|
issueLogger.info(`This $$type doesn't have a stale label`);
|
||||||
}
|
}
|
||||||
const exemptLabels = words_to_list_1.wordsToList(issue.isPullRequest
|
const exemptLabels = words_to_list_1.wordsToList(issue.isPullRequest
|
||||||
? this.options.exemptPrLabels
|
? this.options.exemptPrLabels
|
||||||
: this.options.exemptIssueLabels);
|
: this.options.exemptIssueLabels);
|
||||||
if (exemptLabels.some((exemptLabel) => is_labeled_1.isLabeled(issue, exemptLabel))) {
|
if (exemptLabels.some((exemptLabel) => is_labeled_1.isLabeled(issue, exemptLabel))) {
|
||||||
if (issue.isStale) {
|
if (issue.isStale) {
|
||||||
issueLogger.info(`An exempt label was added after the stale label.`);
|
// issueLogger.info(`An exempt label was added after the stale label.`);
|
||||||
|
issueLogger.info(`This $$type has an exempt label, removing the stale label.`);
|
||||||
yield this._removeStaleLabel(issue, staleLabel);
|
yield this._removeStaleLabel(issue, staleLabel);
|
||||||
}
|
}
|
||||||
issueLogger.info(`Skipping this $$type because it has an exempt label`);
|
issueLogger.info(`Skipping this $$type because it has an exempt label`);
|
||||||
@@ -2183,9 +2184,9 @@ function _getAndValidateArgs() {
|
|||||||
stalePrMessage: core.getInput('stale-pr-message'),
|
stalePrMessage: core.getInput('stale-pr-message'),
|
||||||
closeIssueMessage: core.getInput('close-issue-message'),
|
closeIssueMessage: core.getInput('close-issue-message'),
|
||||||
closePrMessage: core.getInput('close-pr-message'),
|
closePrMessage: core.getInput('close-pr-message'),
|
||||||
daysBeforeStale: parseInt(core.getInput('days-before-stale', { required: true })),
|
daysBeforeStale: parseFloat(core.getInput('days-before-stale', { required: true })),
|
||||||
daysBeforeIssueStale: parseInt(core.getInput('days-before-issue-stale')),
|
daysBeforeIssueStale: parseFloat(core.getInput('days-before-issue-stale')),
|
||||||
daysBeforePrStale: parseInt(core.getInput('days-before-pr-stale')),
|
daysBeforePrStale: parseFloat(core.getInput('days-before-pr-stale')),
|
||||||
daysBeforeClose: parseInt(core.getInput('days-before-close', { required: true })),
|
daysBeforeClose: parseInt(core.getInput('days-before-close', { required: true })),
|
||||||
daysBeforeIssueClose: parseInt(core.getInput('days-before-issue-close')),
|
daysBeforeIssueClose: parseInt(core.getInput('days-before-issue-close')),
|
||||||
daysBeforePrClose: parseInt(core.getInput('days-before-pr-close')),
|
daysBeforePrClose: parseInt(core.getInput('days-before-pr-close')),
|
||||||
@@ -2233,11 +2234,14 @@ function _getAndValidateArgs() {
|
|||||||
closeIssueReason: core.getInput('close-issue-reason'),
|
closeIssueReason: core.getInput('close-issue-reason'),
|
||||||
includeOnlyAssigned: core.getInput('include-only-assigned') === 'true'
|
includeOnlyAssigned: core.getInput('include-only-assigned') === 'true'
|
||||||
};
|
};
|
||||||
for (const numberInput of [
|
for (const numberInput of ['days-before-stale']) {
|
||||||
'days-before-stale',
|
if (isNaN(parseFloat(core.getInput(numberInput)))) {
|
||||||
'days-before-close',
|
const errorMessage = `Option "${numberInput}" did not parse to a valid float`;
|
||||||
'operations-per-run'
|
core.setFailed(errorMessage);
|
||||||
]) {
|
throw new Error(errorMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const numberInput of ['days-before-close', 'operations-per-run']) {
|
||||||
if (isNaN(parseInt(core.getInput(numberInput)))) {
|
if (isNaN(parseInt(core.getInput(numberInput)))) {
|
||||||
const errorMessage = `Option "${numberInput}" did not parse to a valid integer`;
|
const errorMessage = `Option "${numberInput}" did not parse to a valid integer`;
|
||||||
core.setFailed(errorMessage);
|
core.setFailed(errorMessage);
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ export class IssuesProcessor {
|
|||||||
this.operations = new StaleOperations(this.options);
|
this.operations = new StaleOperations(this.options);
|
||||||
|
|
||||||
this._logger.info(
|
this._logger.info(
|
||||||
LoggerService.yellow(`Starting the stale action process...`)
|
LoggerService.yellow(`Starting the stale action process... logging`)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (this.options.debugOnly) {
|
if (this.options.debugOnly) {
|
||||||
@@ -323,7 +323,7 @@ export class IssuesProcessor {
|
|||||||
if (issue.isStale) {
|
if (issue.isStale) {
|
||||||
issueLogger.info(`This $$type has a stale label`);
|
issueLogger.info(`This $$type has a stale label`);
|
||||||
} else {
|
} else {
|
||||||
issueLogger.info(`This $$type hasn't a stale label`);
|
issueLogger.info(`This $$type doesn't have a stale label`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const exemptLabels: string[] = wordsToList(
|
const exemptLabels: string[] = wordsToList(
|
||||||
@@ -338,7 +338,10 @@ export class IssuesProcessor {
|
|||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
if (issue.isStale) {
|
if (issue.isStale) {
|
||||||
issueLogger.info(`An exempt label was added after the stale label.`);
|
// issueLogger.info(`An exempt label was added after the stale label.`);
|
||||||
|
issueLogger.info(
|
||||||
|
`This $$type has an exempt label, removing the stale label.`
|
||||||
|
);
|
||||||
await this._removeStaleLabel(issue, staleLabel);
|
await this._removeStaleLabel(issue, staleLabel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
20
src/main.ts
20
src/main.ts
@@ -28,11 +28,11 @@ function _getAndValidateArgs(): IIssuesProcessorOptions {
|
|||||||
stalePrMessage: core.getInput('stale-pr-message'),
|
stalePrMessage: core.getInput('stale-pr-message'),
|
||||||
closeIssueMessage: core.getInput('close-issue-message'),
|
closeIssueMessage: core.getInput('close-issue-message'),
|
||||||
closePrMessage: core.getInput('close-pr-message'),
|
closePrMessage: core.getInput('close-pr-message'),
|
||||||
daysBeforeStale: parseInt(
|
daysBeforeStale: parseFloat(
|
||||||
core.getInput('days-before-stale', {required: true})
|
core.getInput('days-before-stale', {required: true})
|
||||||
),
|
),
|
||||||
daysBeforeIssueStale: parseInt(core.getInput('days-before-issue-stale')),
|
daysBeforeIssueStale: parseFloat(core.getInput('days-before-issue-stale')),
|
||||||
daysBeforePrStale: parseInt(core.getInput('days-before-pr-stale')),
|
daysBeforePrStale: parseFloat(core.getInput('days-before-pr-stale')),
|
||||||
daysBeforeClose: parseInt(
|
daysBeforeClose: parseInt(
|
||||||
core.getInput('days-before-close', {required: true})
|
core.getInput('days-before-close', {required: true})
|
||||||
),
|
),
|
||||||
@@ -92,11 +92,15 @@ function _getAndValidateArgs(): IIssuesProcessorOptions {
|
|||||||
includeOnlyAssigned: core.getInput('include-only-assigned') === 'true'
|
includeOnlyAssigned: core.getInput('include-only-assigned') === 'true'
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const numberInput of [
|
for (const numberInput of ['days-before-stale']) {
|
||||||
'days-before-stale',
|
if (isNaN(parseFloat(core.getInput(numberInput)))) {
|
||||||
'days-before-close',
|
const errorMessage = `Option "${numberInput}" did not parse to a valid float`;
|
||||||
'operations-per-run'
|
core.setFailed(errorMessage);
|
||||||
]) {
|
throw new Error(errorMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const numberInput of ['days-before-close', 'operations-per-run']) {
|
||||||
if (isNaN(parseInt(core.getInput(numberInput)))) {
|
if (isNaN(parseInt(core.getInput(numberInput)))) {
|
||||||
const errorMessage = `Option "${numberInput}" did not parse to a valid integer`;
|
const errorMessage = `Option "${numberInput}" did not parse to a valid integer`;
|
||||||
core.setFailed(errorMessage);
|
core.setFailed(errorMessage);
|
||||||
|
|||||||
Reference in New Issue
Block a user