Merge 3b2ef2f75f4679c82279f4e2ea455dac65612b8c into 3f3b0175e8c66fb49b9a6d5a0cd1f8436d4c3ab6
This commit is contained in:
commit
df57feac1f
@ -15,7 +15,8 @@ export function generateIssue(
|
||||
isClosed = false,
|
||||
isLocked = false,
|
||||
milestone: string | undefined = undefined,
|
||||
assignees: string[] = []
|
||||
assignees: string[] = [],
|
||||
userLogin: string | undefined = undefined
|
||||
): Issue {
|
||||
return new Issue(options, {
|
||||
number: id,
|
||||
@ -39,6 +40,10 @@ export function generateIssue(
|
||||
login: assignee,
|
||||
type: 'User'
|
||||
};
|
||||
})
|
||||
}),
|
||||
user: {
|
||||
login: userLogin ? userLogin : 'dummy-test-user',
|
||||
type: 'User'
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -6,6 +6,7 @@ import {IssuesProcessorMock} from './classes/issues-processor-mock';
|
||||
import {DefaultProcessorOptions} from './constants/default-processor-options';
|
||||
import {generateIssue} from './functions/generate-issue';
|
||||
import {alwaysFalseStateMock} from './classes/state-mock';
|
||||
import {isPullRequest} from '../src/functions/is-pull-request';
|
||||
|
||||
test('processing an issue with no label will make it stale and close it, if it is old enough only if days-before-close is set to 0', async () => {
|
||||
const opts: IIssuesProcessorOptions = {
|
||||
@ -2743,3 +2744,103 @@ test('processing an issue with the "includeOnlyAssigned" option set and no assig
|
||||
expect(processor.staleIssues).toHaveLength(0);
|
||||
expect(processor.closedIssues).toHaveLength(0);
|
||||
});
|
||||
|
||||
test('interpolate stale message on prs when there is placeholder', async () => {
|
||||
const opts = {...DefaultProcessorOptions};
|
||||
opts.daysBeforeStale = 5; // stale after 5 days
|
||||
opts.daysBeforeClose = 20; // closes after 25 days
|
||||
opts.stalePrMessage = 'Hello {author}, Please take care of this pr!';
|
||||
const lastUpdate = new Date();
|
||||
lastUpdate.setDate(lastUpdate.getDate() - 10);
|
||||
const loginUser = 'dummy-user';
|
||||
const TestIssueList: Issue[] = [
|
||||
generateIssue(
|
||||
opts,
|
||||
1,
|
||||
'An issue that should be marked stale but not closed.',
|
||||
lastUpdate.toString(),
|
||||
lastUpdate.toString(),
|
||||
true,
|
||||
[],
|
||||
false,
|
||||
false,
|
||||
undefined,
|
||||
[],
|
||||
loginUser
|
||||
)
|
||||
];
|
||||
const processor = new IssuesProcessorMock(
|
||||
opts,
|
||||
async p => (p === 1 ? TestIssueList : []),
|
||||
async () => [],
|
||||
async () => 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).toHaveLength(0);
|
||||
expect(processor.removedLabelIssues).toHaveLength(0);
|
||||
expect(processor.staleIssues).toHaveLength(1);
|
||||
|
||||
// comment should be created with placeholder replaced.
|
||||
expect(markSpy).toHaveBeenCalledWith(
|
||||
TestIssueList[0],
|
||||
'Hello @dummy-user, Please take care of this pr!',
|
||||
opts.stalePrLabel,
|
||||
false
|
||||
);
|
||||
});
|
||||
|
||||
test('interpolate stale message on issues when there is placeholder', async () => {
|
||||
const opts = {...DefaultProcessorOptions};
|
||||
opts.daysBeforeStale = 5; // stale after 5 days
|
||||
opts.daysBeforeClose = 20; // closes after 25 days
|
||||
opts.staleIssueMessage = 'Hello {author}, Please take care of this issue!';
|
||||
const lastUpdate = new Date();
|
||||
lastUpdate.setDate(lastUpdate.getDate() - 10);
|
||||
const loginUser = 'dummy-user';
|
||||
const TestIssueList: Issue[] = [
|
||||
generateIssue(
|
||||
opts,
|
||||
1,
|
||||
'An issue that should be marked stale but not closed',
|
||||
lastUpdate.toString(),
|
||||
lastUpdate.toString(),
|
||||
false,
|
||||
[],
|
||||
false,
|
||||
false,
|
||||
undefined,
|
||||
[],
|
||||
loginUser
|
||||
)
|
||||
];
|
||||
const processor = new IssuesProcessorMock(
|
||||
opts,
|
||||
async p => (p === 1 ? TestIssueList : []),
|
||||
async () => [],
|
||||
async () => 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).toHaveLength(0);
|
||||
expect(processor.removedLabelIssues).toHaveLength(0);
|
||||
expect(processor.staleIssues).toHaveLength(1);
|
||||
|
||||
// comment should be created with placeholder replaced.
|
||||
expect(markSpy).toHaveBeenCalledWith(
|
||||
TestIssueList[0],
|
||||
'Hello @dummy-user, Please take care of this issue!',
|
||||
opts.staleIssueLabel,
|
||||
false
|
||||
);
|
||||
});
|
||||
|
||||
@ -7,6 +7,7 @@ import {ILabel} from '../interfaces/label';
|
||||
import {IMilestone} from '../interfaces/milestone';
|
||||
import {IsoDateString} from '../types/iso-date-string';
|
||||
import {Operations} from './operations';
|
||||
import {IUser} from '../interfaces/user';
|
||||
|
||||
export class Issue implements IIssue {
|
||||
readonly title: string;
|
||||
@ -24,6 +25,7 @@ export class Issue implements IIssue {
|
||||
markedStaleThisRun: boolean;
|
||||
operations = new Operations();
|
||||
private readonly _options: IIssuesProcessorOptions;
|
||||
readonly user?: IUser | null;
|
||||
|
||||
constructor(
|
||||
options: Readonly<IIssuesProcessorOptions>,
|
||||
@ -43,6 +45,7 @@ export class Issue implements IIssue {
|
||||
this.assignees = issue.assignees || [];
|
||||
this.isStale = isLabeled(this, this.staleLabel);
|
||||
this.markedStaleThisRun = false;
|
||||
this.user = issue.user
|
||||
}
|
||||
|
||||
get isPullRequest(): boolean {
|
||||
|
||||
@ -212,12 +212,18 @@ export class IssuesProcessor {
|
||||
);
|
||||
|
||||
// calculate string based messages for this issue
|
||||
const staleMessage: string = issue.isPullRequest
|
||||
? this.options.stalePrMessage
|
||||
: this.options.staleIssueMessage;
|
||||
const closeMessage: string = issue.isPullRequest
|
||||
? this.options.closePrMessage
|
||||
: this.options.closeIssueMessage;
|
||||
const staleMessage: string = this._interpolatePlaceholders(
|
||||
issue,
|
||||
issue.isPullRequest
|
||||
? this.options.stalePrMessage
|
||||
: this.options.staleIssueMessage
|
||||
);
|
||||
const closeMessage: string = this._interpolatePlaceholders(
|
||||
issue,
|
||||
issue.isPullRequest
|
||||
? this.options.closePrMessage
|
||||
: this.options.closeIssueMessage
|
||||
);
|
||||
const staleLabel: string = issue.isPullRequest
|
||||
? this.options.stalePrLabel
|
||||
: this.options.staleIssueLabel;
|
||||
@ -1286,4 +1292,10 @@ export class IssuesProcessor {
|
||||
|
||||
return Option.RemoveStaleWhenUpdated;
|
||||
}
|
||||
|
||||
private _interpolatePlaceholders(issue: Issue, message: string) {
|
||||
return issue.user
|
||||
? message.replace('{author}', `@${issue.user?.login}`)
|
||||
: message;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,20 +1,22 @@
|
||||
import {IsoDateString} from '../types/iso-date-string';
|
||||
import {Assignee} from './assignee';
|
||||
import {ILabel} from './label';
|
||||
import {IMilestone} from './milestone';
|
||||
import {components} from '@octokit/openapi-types';
|
||||
export interface IIssue {
|
||||
title: string;
|
||||
number: number;
|
||||
created_at: IsoDateString;
|
||||
updated_at: IsoDateString;
|
||||
draft: boolean;
|
||||
labels: ILabel[];
|
||||
pull_request?: object | null;
|
||||
state: string;
|
||||
locked: boolean;
|
||||
milestone?: IMilestone | null;
|
||||
assignees?: Assignee[] | null;
|
||||
}
|
||||
|
||||
export type OctokitIssue = components['schemas']['issue'];
|
||||
import {IsoDateString} from '../types/iso-date-string';
|
||||
import {Assignee} from './assignee';
|
||||
import {ILabel} from './label';
|
||||
import {IMilestone} from './milestone';
|
||||
import {components} from '@octokit/openapi-types';
|
||||
import {IUser} from './user';
|
||||
|
||||
export interface IIssue {
|
||||
title: string;
|
||||
number: number;
|
||||
created_at: IsoDateString;
|
||||
updated_at: IsoDateString;
|
||||
labels: ILabel[];
|
||||
pull_request?: object | null;
|
||||
state: string;
|
||||
locked: boolean;
|
||||
milestone?: IMilestone | null;
|
||||
assignees?: Assignee[] | null;
|
||||
user?: IUser | null;
|
||||
}
|
||||
|
||||
export type OctokitIssue = components['schemas']['issue'];
|
||||
|
||||
@ -1,4 +1,8 @@
|
||||
import {components} from '@octokit/openapi-types';
|
||||
|
||||
export interface IUser {
|
||||
type: string | 'User';
|
||||
login: string;
|
||||
}
|
||||
|
||||
export type OctokitUser = components['schemas']['nullable-simple-user'];
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user