mirror of
https://github.com/actions/stale.git
synced 2025-12-24 01:18:17 +00:00
Compare commits
1 Commits
rentziass/
...
remove
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9c1b1c6e11 |
2
.github/workflows/check-dist.yml
vendored
2
.github/workflows/check-dist.yml
vendored
@@ -24,7 +24,7 @@ jobs:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Set Node.js 16.x
|
||||
uses: actions/setup-node@v3
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 16.x
|
||||
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
# Changelog
|
||||
|
||||
# [6.0.0]
|
||||
# [5.1.1]
|
||||
|
||||
:warning: Breaking change :warning:
|
||||
|
||||
Issues/PRs default `close-issue-reason` is now `not_planned`([#789](https://github.com/actions/stale/issues/789))
|
||||
[Fix issue when days-before-close is more than days-before-stale](https://github.com/actions/stale/pull/775)
|
||||
|
||||
# [5.1.0]
|
||||
|
||||
|
||||
38
README.md
38
README.md
@@ -11,12 +11,11 @@ The configuration must be on the default branch and the default values will:
|
||||
## Recommended permissions
|
||||
|
||||
For the execution of this action, it must be able to fetch all issues and pull requests from your repository.
|
||||
In addition, based on the provided configuration, the action could require more permission(s) (e.g.: add label, remove label, comment, close, delete branch, etc.).
|
||||
In addition, based on the provided configuration, the action could require more permission(s) (e.g.: add label, remove label, comment, close, etc.).
|
||||
This can be achieved with the following [configuration in the action](https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#permissions) if the permissions are restricted:
|
||||
|
||||
```yaml
|
||||
permissions:
|
||||
contents: write # only for delete-branch option
|
||||
issues: write
|
||||
pull-requests: write
|
||||
```
|
||||
@@ -44,7 +43,7 @@ Every argument is optional.
|
||||
| [close-pr-message](#close-pr-message) | Comment on the staled PRs while closed | |
|
||||
| [stale-issue-label](#stale-issue-label) | Label to apply on staled issues | `Stale` |
|
||||
| [close-issue-label](#close-issue-label) | Label to apply on closed issues | |
|
||||
| [close-issue-reason](#close-issue-reason) | Reason to use when closing issues | `not_planned` |
|
||||
| [close-issue-reason](#close-issue-reason) | Reason to use when closing issues | |
|
||||
| [stale-pr-label](#stale-pr-label) | Label to apply on staled PRs | `Stale` |
|
||||
| [close-pr-label](#close-pr-label) | Label to apply on closed PRs | |
|
||||
| [exempt-issue-labels](#exempt-issue-labels) | Labels on issues exempted from stale | |
|
||||
@@ -82,7 +81,6 @@ Every argument is optional.
|
||||
| [ignore-updates](#ignore-updates) | Any update (update/comment) can reset the stale idle time on the issues/PRs | `false` |
|
||||
| [ignore-issue-updates](#ignore-issue-updates) | Override [ignore-updates](#ignore-updates) for issues only | |
|
||||
| [ignore-pr-updates](#ignore-pr-updates) | Override [ignore-updates](#ignore-updates) for PRs only | |
|
||||
| [include-only-assigned](#include-only-assigned) | Process only assigned issues | `false` |
|
||||
|
||||
### List of output options
|
||||
|
||||
@@ -226,7 +224,7 @@ Required Permission: `issues: write`
|
||||
|
||||
Specify the [reason](https://github.blog/changelog/2022-05-19-the-new-github-issues-may-19th-update/) used when closing issues. Valid values are `completed` and `not_planned`.
|
||||
|
||||
Default value: `not_planned`
|
||||
Default value: unset
|
||||
|
||||
#### stale-pr-label
|
||||
|
||||
@@ -398,7 +396,7 @@ Default value: unset
|
||||
If set to `true`, the stale workflow will automatically delete the GitHub branches related to the pull requests automatically closed by the stale workflow.
|
||||
|
||||
Default value: `false`
|
||||
Required Permission: `pull-requests: write` and `contents: write`
|
||||
Required Permission: `pull-requests: write`
|
||||
|
||||
#### exempt-milestones
|
||||
|
||||
@@ -518,12 +516,6 @@ Useful to override [ignore-updates](#ignore-updates) but only to ignore the upda
|
||||
|
||||
Default value: unset
|
||||
|
||||
#### include-only-assigned
|
||||
|
||||
If set to `true`, only the issues or the pull requests with an assignee will be marked as stale automatically.
|
||||
|
||||
Default value: `false`
|
||||
|
||||
### Usage
|
||||
|
||||
See also [action.yml](./action.yml) for a comprehensive list of all the options.
|
||||
@@ -540,7 +532,7 @@ jobs:
|
||||
stale:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/stale@v6
|
||||
- uses: actions/stale@v5
|
||||
with:
|
||||
stale-issue-message: 'Message to comment on stale issues. If none provided, will not mark issues stale'
|
||||
stale-pr-message: 'Message to comment on stale PRs. If none provided, will not mark PRs stale'
|
||||
@@ -558,7 +550,7 @@ jobs:
|
||||
stale:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/stale@v6
|
||||
- uses: actions/stale@v5
|
||||
with:
|
||||
stale-issue-message: 'This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days.'
|
||||
days-before-stale: 30
|
||||
@@ -577,7 +569,7 @@ jobs:
|
||||
stale:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/stale@v6
|
||||
- uses: actions/stale@v5
|
||||
with:
|
||||
stale-issue-message: 'This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days.'
|
||||
stale-pr-message: 'This PR is stale because it has been open 45 days with no activity. Remove stale label or comment or this will be closed in 10 days.'
|
||||
@@ -599,7 +591,7 @@ jobs:
|
||||
stale:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/stale@v6
|
||||
- uses: actions/stale@v5
|
||||
with:
|
||||
stale-issue-message: 'This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days.'
|
||||
stale-pr-message: 'This PR is stale because it has been open 45 days with no activity. Remove stale label or comment or this will be closed in 10 days.'
|
||||
@@ -623,7 +615,7 @@ jobs:
|
||||
stale:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/stale@v6
|
||||
- uses: actions/stale@v5
|
||||
with:
|
||||
stale-issue-message: 'Stale issue message'
|
||||
stale-pr-message: 'Stale pull request message'
|
||||
@@ -646,7 +638,7 @@ jobs:
|
||||
stale:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/stale@v6
|
||||
- uses: actions/stale@v5
|
||||
with:
|
||||
start-date: '2020-04-18T00:00:00Z' # ISO 8601 or RFC 2822
|
||||
```
|
||||
@@ -663,7 +655,7 @@ jobs:
|
||||
stale:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/stale@v6
|
||||
- uses: actions/stale@v5
|
||||
with:
|
||||
exempt-issue-milestones: 'future,alpha,beta'
|
||||
exempt-pr-milestones: 'bugfix,improvement'
|
||||
@@ -681,7 +673,7 @@ jobs:
|
||||
stale:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/stale@v6
|
||||
- uses: actions/stale@v5
|
||||
with:
|
||||
exempt-all-pr-milestones: true
|
||||
```
|
||||
@@ -698,7 +690,7 @@ jobs:
|
||||
stale:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/stale@v6
|
||||
- uses: actions/stale@v5
|
||||
with:
|
||||
any-of-labels: 'needs-more-info,needs-demo'
|
||||
# You can opt for 'only-labels' instead if your use-case requires all labels
|
||||
@@ -717,7 +709,7 @@ jobs:
|
||||
stale:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/stale@v6
|
||||
- uses: actions/stale@v5
|
||||
with:
|
||||
exempt-issue-assignees: 'marco,polo'
|
||||
exempt-pr-assignees: 'marco'
|
||||
@@ -735,7 +727,7 @@ jobs:
|
||||
stale:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/stale@v6
|
||||
- uses: actions/stale@v5
|
||||
with:
|
||||
exempt-all-pr-assignees: true
|
||||
```
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import {IIssuesProcessorOptions} from '../../src/interfaces/issues-processor-options';
|
||||
|
||||
// Default options for use in tests.
|
||||
// Mirrors the defaults defined in action.yml
|
||||
export const DefaultProcessorOptions: IIssuesProcessorOptions = Object.freeze({
|
||||
repoToken: 'none',
|
||||
staleIssueMessage: 'This issue is stale',
|
||||
@@ -53,6 +51,5 @@ export const DefaultProcessorOptions: IIssuesProcessorOptions = Object.freeze({
|
||||
ignoreIssueUpdates: undefined,
|
||||
ignorePrUpdates: undefined,
|
||||
exemptDraftPr: false,
|
||||
closeIssueReason: 'not_planned',
|
||||
includeOnlyAssigned: false
|
||||
closeIssueReason: ''
|
||||
});
|
||||
|
||||
@@ -2352,69 +2352,3 @@ test('processing a pull request to be stale with the "stalePrMessage" option set
|
||||
expect(processor.closedIssues).toHaveLength(0);
|
||||
expect(processor.statistics?.addedPullRequestsCommentsCount).toStrictEqual(0);
|
||||
});
|
||||
|
||||
test('processing an issue with the "includeOnlyAssigned" option and nonempty assignee list will stale the issue', async () => {
|
||||
const issueDate = new Date();
|
||||
issueDate.setDate(issueDate.getDate() - 2);
|
||||
|
||||
const opts: IIssuesProcessorOptions = {
|
||||
...DefaultProcessorOptions,
|
||||
staleIssueLabel: 'This issue is stale',
|
||||
includeOnlyAssigned: true
|
||||
};
|
||||
|
||||
const TestIssueList: Issue[] = [
|
||||
generateIssue(
|
||||
opts,
|
||||
1,
|
||||
'An issue with no label',
|
||||
issueDate.toDateString(),
|
||||
issueDate.toDateString(),
|
||||
false,
|
||||
[],
|
||||
false,
|
||||
false,
|
||||
undefined,
|
||||
['assignee1']
|
||||
)
|
||||
];
|
||||
const processor = new IssuesProcessorMock(
|
||||
opts,
|
||||
async p => (p === 1 ? TestIssueList : []),
|
||||
async () => [],
|
||||
async () => new Date().toDateString()
|
||||
);
|
||||
|
||||
// process our fake issue list
|
||||
await processor.processIssues(1);
|
||||
|
||||
expect(processor.staleIssues).toHaveLength(1);
|
||||
expect(processor.closedIssues).toHaveLength(0);
|
||||
});
|
||||
|
||||
test('processing an issue with the "includeOnlyAssigned" option set and no assignees will not stale the issue', async () => {
|
||||
const issueDate = new Date();
|
||||
issueDate.setDate(issueDate.getDate() - 2);
|
||||
|
||||
const opts: IIssuesProcessorOptions = {
|
||||
...DefaultProcessorOptions,
|
||||
staleIssueLabel: 'This issue is stale',
|
||||
includeOnlyAssigned: true
|
||||
};
|
||||
|
||||
const TestIssueList: Issue[] = [
|
||||
generateIssue(opts, 1, 'An issue with no label', issueDate.toDateString())
|
||||
];
|
||||
const processor = new IssuesProcessorMock(
|
||||
opts,
|
||||
async p => (p === 1 ? TestIssueList : []),
|
||||
async () => [],
|
||||
async () => new Date().toDateString()
|
||||
);
|
||||
|
||||
// process our fake issue list
|
||||
await processor.processIssues(1);
|
||||
|
||||
expect(processor.staleIssues).toHaveLength(0);
|
||||
expect(processor.closedIssues).toHaveLength(0);
|
||||
});
|
||||
|
||||
@@ -51,7 +51,7 @@ inputs:
|
||||
required: false
|
||||
close-issue-reason:
|
||||
description: 'The reason to use when closing an issue.'
|
||||
default: 'not_planned'
|
||||
default: ''
|
||||
required: false
|
||||
stale-pr-label:
|
||||
description: 'The label to apply when a pull request is stale.'
|
||||
@@ -196,10 +196,6 @@ inputs:
|
||||
description: 'Any update (update/comment) can reset the stale idle time on the pull requests. Override "ignore-updates" option regarding only the pull requests.'
|
||||
default: ''
|
||||
required: false
|
||||
include-only-assigned:
|
||||
description: 'Only the issues or the pull requests with an assignee will be marked as stale automatically.'
|
||||
default: 'false'
|
||||
required: false
|
||||
outputs:
|
||||
closed-issues-prs:
|
||||
description: 'List of all closed issues and pull requests.'
|
||||
|
||||
2110
dist/index.js
vendored
2110
dist/index.js
vendored
File diff suppressed because it is too large
Load Diff
11707
package-lock.json
generated
11707
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -38,7 +38,7 @@
|
||||
"author": "GitHub",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.10.0",
|
||||
"@actions/core": "^1.2.6",
|
||||
"@actions/github": "^5.0.1",
|
||||
"lodash.deburr": "^4.1.0",
|
||||
"semver": "^7.3.5"
|
||||
|
||||
@@ -62,8 +62,7 @@ describe('Issue', (): void => {
|
||||
ignoreIssueUpdates: undefined,
|
||||
ignorePrUpdates: undefined,
|
||||
exemptDraftPr: false,
|
||||
closeIssueReason: '',
|
||||
includeOnlyAssigned: false
|
||||
closeIssueReason: ''
|
||||
};
|
||||
issueInterface = {
|
||||
title: 'dummy-title',
|
||||
|
||||
@@ -221,14 +221,6 @@ export class IssuesProcessor {
|
||||
return; // Don't process locked issues
|
||||
}
|
||||
|
||||
if (this._isIncludeOnlyAssigned(issue)) {
|
||||
issueLogger.info(
|
||||
`Skipping this $$type because its assignees list is empty`
|
||||
);
|
||||
IssuesProcessor._endIssueProcessing(issue);
|
||||
return; // If the issue has an 'include-only-assigned' option set, process only issues with nonempty assignees list
|
||||
}
|
||||
|
||||
const onlyLabels: string[] = wordsToList(this._getOnlyLabels(issue));
|
||||
|
||||
if (onlyLabels.length > 0) {
|
||||
@@ -673,13 +665,8 @@ export class IssuesProcessor {
|
||||
issueLogger.info(`marked stale this run, so don't check for updates`);
|
||||
}
|
||||
|
||||
// The issue.updated_at and markedStaleOn are not always exactly in sync (they can be off by a second or 2)
|
||||
// isDateMoreRecentThan makes sure they are not the same date within a certain tolerance (15 seconds in this case)
|
||||
const issueHasUpdateSinceStale = isDateMoreRecentThan(
|
||||
new Date(issue.updated_at),
|
||||
new Date(markedStaleOn),
|
||||
15
|
||||
);
|
||||
const issueHasUpdateSinceStale =
|
||||
new Date(issue.updated_at) > new Date(markedStaleOn);
|
||||
|
||||
issueLogger.info(
|
||||
`$$type has been updated since it was marked stale: ${LoggerService.cyan(
|
||||
@@ -1025,10 +1012,6 @@ export class IssuesProcessor {
|
||||
return this.options.onlyLabels;
|
||||
}
|
||||
|
||||
private _isIncludeOnlyAssigned(issue: Issue): boolean {
|
||||
return this.options.includeOnlyAssigned && !issue.hasAssignees;
|
||||
}
|
||||
|
||||
private _getAnyOfLabels(issue: Issue): string {
|
||||
if (issue.isPullRequest) {
|
||||
if (this.options.anyOfPrLabels !== '') {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {isDateEqualTo, isDateMoreRecentThan} from './is-date-more-recent-than';
|
||||
import {isDateMoreRecentThan} from './is-date-more-recent-than';
|
||||
|
||||
describe('isDateMoreRecentThan()', (): void => {
|
||||
let date: Date;
|
||||
@@ -48,68 +48,4 @@ describe('isDateMoreRecentThan()', (): void => {
|
||||
expect(result).toStrictEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('date equality', (): void => {
|
||||
it('should correctly compare a before date outside tolerance', (): void => {
|
||||
const aDate = new Date('2022-09-09T13:00:00');
|
||||
const otherDate = new Date('2022-09-09T14:00:00');
|
||||
expect(isDateEqualTo(aDate, otherDate, 60)).toBe(false);
|
||||
});
|
||||
|
||||
it('should correctly compare a before date inside tolerance', (): void => {
|
||||
const aDate = new Date('2022-09-09T13:00:00');
|
||||
const otherDate = new Date('2022-09-09T13:00:42');
|
||||
expect(isDateEqualTo(aDate, otherDate, 60)).toBe(true);
|
||||
});
|
||||
|
||||
it('should correctly compare an after date outside tolerance', (): void => {
|
||||
const aDate = new Date('2022-09-09T13:00:00');
|
||||
const otherDate = new Date('2022-09-09T12:00:00');
|
||||
expect(isDateEqualTo(aDate, otherDate, 60)).toBe(false);
|
||||
});
|
||||
|
||||
it('should correctly compare an after date inside tolerance', (): void => {
|
||||
const aDate = new Date('2022-09-09T13:00:00');
|
||||
const otherDate = new Date('2022-09-09T12:59:42');
|
||||
expect(isDateEqualTo(aDate, otherDate, 60)).toBe(true);
|
||||
});
|
||||
|
||||
it('should correctly compare an exactly equal date', (): void => {
|
||||
const aDate = new Date('2022-09-09T13:00:00');
|
||||
const otherDate = new Date('2022-09-09T13:00:00');
|
||||
expect(isDateEqualTo(aDate, otherDate, 60)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('date comparison with tolerances', (): void => {
|
||||
it('should correctly compare a before date outside tolerance', (): void => {
|
||||
const aDate = new Date('2022-09-09T13:00:00');
|
||||
const otherDate = new Date('2022-09-09T14:00:00');
|
||||
expect(isDateMoreRecentThan(aDate, otherDate)).toBe(false);
|
||||
});
|
||||
|
||||
it('should correctly compare a before date inside tolerance', (): void => {
|
||||
const aDate = new Date('2022-09-09T13:00:00');
|
||||
const otherDate = new Date('2022-09-09T13:00:42');
|
||||
expect(isDateMoreRecentThan(aDate, otherDate, 60)).toBe(false); // considered equal here
|
||||
});
|
||||
|
||||
it('should correctly compare an after date outside tolerance', (): void => {
|
||||
const aDate = new Date('2022-09-09T13:00:00');
|
||||
const otherDate = new Date('2022-09-09T12:00:00');
|
||||
expect(isDateMoreRecentThan(aDate, otherDate, 60)).toBe(true);
|
||||
});
|
||||
|
||||
it('should correctly compare an after date inside tolerance', (): void => {
|
||||
const aDate = new Date('2022-09-09T13:00:00');
|
||||
const otherDate = new Date('2022-09-09T12:59:42');
|
||||
expect(isDateMoreRecentThan(aDate, otherDate, 60)).toBe(false); // considered equal here
|
||||
});
|
||||
|
||||
it('should correctly compare an exactly equal date', (): void => {
|
||||
const aDate = new Date('2022-09-09T13:00:00');
|
||||
const otherDate = new Date('2022-09-09T13:00:00');
|
||||
expect(isDateMoreRecentThan(aDate, otherDate, 60)).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,31 +1,6 @@
|
||||
/// returns false if the dates are equal within the `equalityToleranceInSeconds` number of seconds
|
||||
/// otherwise returns true if `comparedDate` is after `date`
|
||||
|
||||
export function isDateMoreRecentThan(
|
||||
date: Readonly<Date>,
|
||||
comparedDate: Readonly<Date>,
|
||||
equalityToleranceInSeconds = 0
|
||||
comparedDate: Readonly<Date>
|
||||
): boolean {
|
||||
if (equalityToleranceInSeconds > 0) {
|
||||
const areDatesEqual = isDateEqualTo(
|
||||
date,
|
||||
comparedDate,
|
||||
equalityToleranceInSeconds
|
||||
);
|
||||
|
||||
return !areDatesEqual && date > comparedDate;
|
||||
}
|
||||
|
||||
return date > comparedDate;
|
||||
}
|
||||
|
||||
export function isDateEqualTo(
|
||||
date: Date,
|
||||
otherDate: Date,
|
||||
toleranceInSeconds: number
|
||||
): boolean {
|
||||
const timestamp = date.getTime();
|
||||
const otherTimestamp = otherDate.getTime();
|
||||
const deltaInSeconds = Math.abs(timestamp - otherTimestamp) / 1000;
|
||||
return deltaInSeconds <= toleranceInSeconds;
|
||||
}
|
||||
|
||||
@@ -52,5 +52,4 @@ export interface IIssuesProcessorOptions {
|
||||
ignorePrUpdates: boolean | undefined;
|
||||
exemptDraftPr: boolean;
|
||||
closeIssueReason: string;
|
||||
includeOnlyAssigned: boolean;
|
||||
}
|
||||
|
||||
@@ -88,8 +88,7 @@ function _getAndValidateArgs(): IIssuesProcessorOptions {
|
||||
ignoreIssueUpdates: _toOptionalBoolean('ignore-issue-updates'),
|
||||
ignorePrUpdates: _toOptionalBoolean('ignore-pr-updates'),
|
||||
exemptDraftPr: core.getInput('exempt-draft-pr') === 'true',
|
||||
closeIssueReason: core.getInput('close-issue-reason'),
|
||||
includeOnlyAssigned: core.getInput('include-only-assigned') === 'true'
|
||||
closeIssueReason: core.getInput('close-issue-reason')
|
||||
};
|
||||
|
||||
for (const numberInput of [
|
||||
|
||||
Reference in New Issue
Block a user