mirror of
https://github.com/actions/stale.git
synced 2025-12-11 04:32:53 +00:00
feat(statistics): display some stats in the logs (#337)
* test: add more coverage * docs: reorder and enhance typo * docs(contributing): add more information about the npm scripts * feat(statistics): add simple statistics * feat(statistics): add more stats * refactor(issues-processor): remove some options from the constructor it should have been only useful for the tests * feat(statistics): add stats for new stale or undo stale issues * chore(rebase): handle rebase conflicts
This commit is contained in:
committed by
GitHub
parent
63ae8ac024
commit
419a53bc05
@@ -52,7 +52,8 @@ describe('Issue', (): void => {
|
||||
exemptPrAssignees: '',
|
||||
exemptAllAssignees: false,
|
||||
exemptAllIssueAssignees: undefined,
|
||||
exemptAllPrAssignees: undefined
|
||||
exemptAllPrAssignees: undefined,
|
||||
enableStatistics: false
|
||||
};
|
||||
issueInterface = {
|
||||
title: 'dummy-title',
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
import {context, getOctokit} from '@actions/github';
|
||||
import {GitHub} from '@actions/github/lib/utils';
|
||||
import {GetResponseTypeFromEndpointMethod} from '@octokit/types';
|
||||
import {IssueType} from '../enums/issue-type';
|
||||
import {getHumanizedDate} from '../functions/dates/get-humanized-date';
|
||||
import {isDateMoreRecentThan} from '../functions/dates/is-date-more-recent-than';
|
||||
import {isValidDate} from '../functions/dates/is-valid-date';
|
||||
import {getIssueType} from '../functions/get-issue-type';
|
||||
import {isLabeled} from '../functions/is-labeled';
|
||||
import {isPullRequest} from '../functions/is-pull-request';
|
||||
import {shouldMarkWhenStale} from '../functions/should-mark-when-stale';
|
||||
@@ -20,6 +18,7 @@ import {Issue} from './issue';
|
||||
import {IssueLogger} from './loggers/issue-logger';
|
||||
import {Logger} from './loggers/logger';
|
||||
import {Milestones} from './milestones';
|
||||
import {Statistics} from './statistics';
|
||||
|
||||
/***
|
||||
* Handle processing of issues for staleness/closure.
|
||||
@@ -34,6 +33,7 @@ export class IssuesProcessor {
|
||||
}
|
||||
|
||||
private readonly _logger: Logger = new Logger();
|
||||
private readonly _statistics: Statistics | undefined;
|
||||
private _operationsLeft = 0;
|
||||
readonly client: InstanceType<typeof GitHub>;
|
||||
readonly options: IIssuesProcessorOptions;
|
||||
@@ -42,61 +42,38 @@ export class IssuesProcessor {
|
||||
readonly deletedBranchIssues: Issue[] = [];
|
||||
readonly removedLabelIssues: Issue[] = [];
|
||||
|
||||
constructor(
|
||||
options: IIssuesProcessorOptions,
|
||||
getActor?: () => Promise<string>,
|
||||
getIssues?: (page: number) => Promise<Issue[]>,
|
||||
listIssueComments?: (
|
||||
issueNumber: number,
|
||||
sinceDate: string
|
||||
) => Promise<IComment[]>,
|
||||
getLabelCreationDate?: (
|
||||
issue: Issue,
|
||||
label: string
|
||||
) => Promise<string | undefined>
|
||||
) {
|
||||
constructor(options: IIssuesProcessorOptions) {
|
||||
this.options = options;
|
||||
this._operationsLeft = options.operationsPerRun;
|
||||
this.client = getOctokit(options.repoToken);
|
||||
|
||||
if (getActor) {
|
||||
this._getActor = getActor;
|
||||
}
|
||||
|
||||
if (getIssues) {
|
||||
this._getIssues = getIssues;
|
||||
}
|
||||
|
||||
if (listIssueComments) {
|
||||
this._listIssueComments = listIssueComments;
|
||||
}
|
||||
|
||||
if (getLabelCreationDate) {
|
||||
this._getLabelCreationDate = getLabelCreationDate;
|
||||
}
|
||||
this._operationsLeft = this.options.operationsPerRun;
|
||||
this.client = getOctokit(this.options.repoToken);
|
||||
|
||||
if (this.options.debugOnly) {
|
||||
this._logger.warning(
|
||||
'Executing in debug mode. Debug output will be written but no issues will be processed.'
|
||||
);
|
||||
}
|
||||
|
||||
if (this.options.enableStatistics) {
|
||||
this._statistics = new Statistics(this.options);
|
||||
}
|
||||
}
|
||||
|
||||
async processIssues(page = 1): Promise<number> {
|
||||
// get the next batch of issues
|
||||
const issues: Issue[] = await this._getIssues(page);
|
||||
this._operationsLeft -= 1;
|
||||
|
||||
const actor: string = await this._getActor();
|
||||
const issues: Issue[] = await this.getIssues(page);
|
||||
const actor: string = await this.getActor();
|
||||
|
||||
if (issues.length <= 0) {
|
||||
this._logger.info('---');
|
||||
this._statistics?.setOperationsLeft(this._operationsLeft).logStats();
|
||||
this._logger.info('No more issues found to process. Exiting.');
|
||||
|
||||
return this._operationsLeft;
|
||||
}
|
||||
|
||||
for (const issue of issues.values()) {
|
||||
const issueLogger: IssueLogger = new IssueLogger(issue);
|
||||
this._statistics?.incrementProcessedIssuesCount();
|
||||
|
||||
issueLogger.info(`Found this $$type last updated ${issue.updated_at}`);
|
||||
|
||||
@@ -116,7 +93,6 @@ export class IssuesProcessor {
|
||||
const skipMessage = issue.isPullRequest
|
||||
? this.options.skipStalePrMessage
|
||||
: this.options.skipStaleIssueMessage;
|
||||
const issueType: IssueType = getIssueType(issue.isPullRequest);
|
||||
const daysBeforeStale: number = issue.isPullRequest
|
||||
? this._getDaysBeforePrStale()
|
||||
: this._getDaysBeforeIssueStale();
|
||||
@@ -238,7 +214,7 @@ export class IssuesProcessor {
|
||||
)
|
||||
) {
|
||||
issueLogger.info(
|
||||
`Skipping ${issueType} because it does not have any of the required labels`
|
||||
`Skipping $$type because it does not have any of the required labels`
|
||||
);
|
||||
continue; // don't process issues without any of the required labels
|
||||
}
|
||||
@@ -282,7 +258,6 @@ export class IssuesProcessor {
|
||||
issueLogger.info(`Found a stale $$type`);
|
||||
await this._processStaleIssue(
|
||||
issue,
|
||||
issueType,
|
||||
staleLabel,
|
||||
actor,
|
||||
closeMessage,
|
||||
@@ -302,10 +277,108 @@ export class IssuesProcessor {
|
||||
return this.processIssues(page + 1);
|
||||
}
|
||||
|
||||
// grab comments for an issue since a given date
|
||||
async listIssueComments(
|
||||
issueNumber: number,
|
||||
sinceDate: string
|
||||
): Promise<IComment[]> {
|
||||
// find any comments since date on the given issue
|
||||
try {
|
||||
this._operationsLeft -= 1;
|
||||
this._statistics?.incrementFetchedIssuesCommentsCount();
|
||||
const comments = await this.client.issues.listComments({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issueNumber,
|
||||
since: sinceDate
|
||||
});
|
||||
return comments.data;
|
||||
} catch (error) {
|
||||
this._logger.error(`List issue comments error: ${error.message}`);
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
}
|
||||
|
||||
// get the actor from the GitHub token or context
|
||||
async getActor(): Promise<string> {
|
||||
let actor;
|
||||
|
||||
try {
|
||||
this._operationsLeft -= 1;
|
||||
actor = await this.client.users.getAuthenticated();
|
||||
} catch (error) {
|
||||
return context.actor;
|
||||
}
|
||||
|
||||
return actor.data.login;
|
||||
}
|
||||
|
||||
// grab issues from github in batches of 100
|
||||
async getIssues(page: number): Promise<Issue[]> {
|
||||
// generate type for response
|
||||
const endpoint = this.client.issues.listForRepo;
|
||||
type OctoKitIssueList = GetResponseTypeFromEndpointMethod<typeof endpoint>;
|
||||
|
||||
try {
|
||||
this._operationsLeft -= 1;
|
||||
this._statistics?.incrementFetchedIssuesCount();
|
||||
const issueResult: OctoKitIssueList = await this.client.issues.listForRepo(
|
||||
{
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
state: 'open',
|
||||
per_page: 100,
|
||||
direction: this.options.ascending ? 'asc' : 'desc',
|
||||
page
|
||||
}
|
||||
);
|
||||
|
||||
return issueResult.data.map(
|
||||
(issue: Readonly<IIssue>): Issue => new Issue(this.options, issue)
|
||||
);
|
||||
} catch (error) {
|
||||
this._logger.error(`Get issues for repo error: ${error.message}`);
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
}
|
||||
|
||||
// returns the creation date of a given label on an issue (or nothing if no label existed)
|
||||
///see https://developer.github.com/v3/activity/events/
|
||||
async getLabelCreationDate(
|
||||
issue: Issue,
|
||||
label: string
|
||||
): Promise<string | undefined> {
|
||||
const issueLogger: IssueLogger = new IssueLogger(issue);
|
||||
|
||||
issueLogger.info(`Checking for label on $$type`);
|
||||
|
||||
this._operationsLeft -= 1;
|
||||
this._statistics?.incrementFetchedIssuesEventsCount();
|
||||
const options = this.client.issues.listEvents.endpoint.merge({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
per_page: 100,
|
||||
issue_number: issue.number
|
||||
});
|
||||
|
||||
const events: IIssueEvent[] = await this.client.paginate(options);
|
||||
const reversedEvents = events.reverse();
|
||||
|
||||
const staleLabeledEvent = reversedEvents.find(
|
||||
event => event.event === 'labeled' && event.label.name === label
|
||||
);
|
||||
|
||||
if (!staleLabeledEvent) {
|
||||
// Must be old rather than labeled
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return staleLabeledEvent.created_at;
|
||||
}
|
||||
|
||||
// handle all of the stale issue logic when we find a stale issue
|
||||
private async _processStaleIssue(
|
||||
issue: Issue,
|
||||
issueType: IssueType,
|
||||
staleLabel: string,
|
||||
actor: string,
|
||||
closeMessage?: string,
|
||||
@@ -313,7 +386,7 @@ export class IssuesProcessor {
|
||||
) {
|
||||
const issueLogger: IssueLogger = new IssueLogger(issue);
|
||||
const markedStaleOn: string =
|
||||
(await this._getLabelCreationDate(issue, staleLabel)) || issue.updated_at;
|
||||
(await this.getLabelCreationDate(issue, staleLabel)) || issue.updated_at;
|
||||
issueLogger.info(`$$type marked stale on: ${markedStaleOn}`);
|
||||
|
||||
const issueHasComments: boolean = await this._hasCommentsSince(
|
||||
@@ -381,7 +454,7 @@ export class IssuesProcessor {
|
||||
}
|
||||
|
||||
// find any comments since the date
|
||||
const comments = await this._listIssueComments(issue.number, sinceDate);
|
||||
const comments = await this.listIssueComments(issue.number, sinceDate);
|
||||
|
||||
const filteredComments = comments.filter(
|
||||
comment => comment.user.type === 'User' && comment.user.login !== actor
|
||||
@@ -395,65 +468,6 @@ export class IssuesProcessor {
|
||||
return filteredComments.length > 0;
|
||||
}
|
||||
|
||||
// grab comments for an issue since a given date
|
||||
private async _listIssueComments(
|
||||
issueNumber: number,
|
||||
sinceDate: string
|
||||
): Promise<IComment[]> {
|
||||
// find any comments since date on the given issue
|
||||
try {
|
||||
const comments = await this.client.issues.listComments({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issueNumber,
|
||||
since: sinceDate
|
||||
});
|
||||
return comments.data;
|
||||
} catch (error) {
|
||||
this._logger.error(`List issue comments error: ${error.message}`);
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
}
|
||||
|
||||
// get the actor from the GitHub token or context
|
||||
private async _getActor(): Promise<string> {
|
||||
let actor;
|
||||
try {
|
||||
actor = await this.client.users.getAuthenticated();
|
||||
} catch (error) {
|
||||
return context.actor;
|
||||
}
|
||||
|
||||
return actor.data.login;
|
||||
}
|
||||
|
||||
// grab issues from github in batches 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: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
state: 'open',
|
||||
per_page: 100,
|
||||
direction: this.options.ascending ? 'asc' : 'desc',
|
||||
page
|
||||
}
|
||||
);
|
||||
|
||||
return issueResult.data.map(
|
||||
(issue: Readonly<IIssue>): Issue => new Issue(this.options, issue)
|
||||
);
|
||||
} catch (error) {
|
||||
this._logger.error(`Get issues for repo error: ${error.message}`);
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
}
|
||||
|
||||
// Mark an issue as stale with a comment and a label
|
||||
private async _markStale(
|
||||
issue: Issue,
|
||||
@@ -464,11 +478,8 @@ export class IssuesProcessor {
|
||||
const issueLogger: IssueLogger = new IssueLogger(issue);
|
||||
|
||||
issueLogger.info(`Marking $$type as stale`);
|
||||
|
||||
this.staleIssues.push(issue);
|
||||
|
||||
this._operationsLeft -= 2;
|
||||
|
||||
// if the issue is being marked stale, the updated date should be changed to right now
|
||||
// so that close calculations work correctly
|
||||
const newUpdatedAtDate: Date = new Date();
|
||||
@@ -480,6 +491,8 @@ export class IssuesProcessor {
|
||||
|
||||
if (!skipMessage) {
|
||||
try {
|
||||
this._operationsLeft -= 1;
|
||||
this._statistics?.incrementAddedComment();
|
||||
await this.client.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
@@ -492,6 +505,9 @@ export class IssuesProcessor {
|
||||
}
|
||||
|
||||
try {
|
||||
this._operationsLeft -= 1;
|
||||
this._statistics?.incrementAddedLabel();
|
||||
this._statistics?.incrementStaleIssuesCount();
|
||||
await this.client.issues.addLabels({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
@@ -512,17 +528,16 @@ export class IssuesProcessor {
|
||||
const issueLogger: IssueLogger = new IssueLogger(issue);
|
||||
|
||||
issueLogger.info(`Closing $$type for being stale`);
|
||||
|
||||
this.closedIssues.push(issue);
|
||||
|
||||
this._operationsLeft -= 1;
|
||||
|
||||
if (this.options.debugOnly) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (closeMessage) {
|
||||
try {
|
||||
this._operationsLeft -= 1;
|
||||
this._statistics?.incrementAddedComment();
|
||||
await this.client.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
@@ -536,6 +551,8 @@ export class IssuesProcessor {
|
||||
|
||||
if (closeLabel) {
|
||||
try {
|
||||
this._operationsLeft -= 1;
|
||||
this._statistics?.incrementAddedLabel();
|
||||
await this.client.issues.addLabels({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
@@ -548,6 +565,8 @@ export class IssuesProcessor {
|
||||
}
|
||||
|
||||
try {
|
||||
this._operationsLeft -= 1;
|
||||
this._statistics?.incrementClosedIssuesCount();
|
||||
await this.client.issues.update({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
@@ -561,11 +580,16 @@ export class IssuesProcessor {
|
||||
|
||||
private async _getPullRequest(
|
||||
issue: Issue
|
||||
): Promise<IPullRequest | undefined> {
|
||||
): Promise<IPullRequest | undefined | void> {
|
||||
const issueLogger: IssueLogger = new IssueLogger(issue);
|
||||
this._operationsLeft -= 1;
|
||||
|
||||
if (this.options.debugOnly) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
this._operationsLeft -= 1;
|
||||
this._statistics?.incrementFetchedPullRequestsCount();
|
||||
const pullRequest = await this.client.pulls.get({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
@@ -584,10 +608,6 @@ export class IssuesProcessor {
|
||||
|
||||
issueLogger.info(`Delete branch from closed $$type - ${issue.title}`);
|
||||
|
||||
if (this.options.debugOnly) {
|
||||
return;
|
||||
}
|
||||
|
||||
const pullRequest = await this._getPullRequest(issue);
|
||||
|
||||
if (!pullRequest) {
|
||||
@@ -597,12 +617,16 @@ export class IssuesProcessor {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.options.debugOnly) {
|
||||
return;
|
||||
}
|
||||
|
||||
const branch = pullRequest.head.ref;
|
||||
issueLogger.info(`Deleting branch ${branch} from closed $$type`);
|
||||
|
||||
this._operationsLeft -= 1;
|
||||
|
||||
try {
|
||||
this._operationsLeft -= 1;
|
||||
this._statistics?.incrementDeletedBranchesCount();
|
||||
await this.client.git.deleteRef({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
@@ -620,17 +644,16 @@ export class IssuesProcessor {
|
||||
const issueLogger: IssueLogger = new IssueLogger(issue);
|
||||
|
||||
issueLogger.info(`Removing label "${label}" from $$type`);
|
||||
|
||||
this.removedLabelIssues.push(issue);
|
||||
|
||||
this._operationsLeft -= 1;
|
||||
|
||||
// @todo remove the debug only to be able to test the code below
|
||||
if (this.options.debugOnly) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
this._operationsLeft -= 1;
|
||||
this._statistics?.incrementDeletedLabelsCount();
|
||||
await this.client.issues.removeLabel({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
@@ -642,40 +665,6 @@ export class IssuesProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
// returns the creation date of a given label on an issue (or nothing if no label existed)
|
||||
///see https://developer.github.com/v3/activity/events/
|
||||
private async _getLabelCreationDate(
|
||||
issue: Issue,
|
||||
label: string
|
||||
): Promise<string | undefined> {
|
||||
const issueLogger: IssueLogger = new IssueLogger(issue);
|
||||
|
||||
issueLogger.info(`Checking for label on $$type`);
|
||||
|
||||
this._operationsLeft -= 1;
|
||||
|
||||
const options = this.client.issues.listEvents.endpoint.merge({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
per_page: 100,
|
||||
issue_number: issue.number
|
||||
});
|
||||
|
||||
const events: IIssueEvent[] = await this.client.paginate(options);
|
||||
const reversedEvents = events.reverse();
|
||||
|
||||
const staleLabeledEvent = reversedEvents.find(
|
||||
event => event.event === 'labeled' && event.label.name === label
|
||||
);
|
||||
|
||||
if (!staleLabeledEvent) {
|
||||
// Must be old rather than labeled
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return staleLabeledEvent.created_at;
|
||||
}
|
||||
|
||||
private _getDaysBeforeIssueStale(): number {
|
||||
return isNaN(this.options.daysBeforeIssueStale)
|
||||
? this.options.daysBeforeStale
|
||||
@@ -724,7 +713,8 @@ export class IssuesProcessor {
|
||||
`The $$type is no longer stale. Removing the stale label...`
|
||||
);
|
||||
|
||||
return this._removeLabel(issue, staleLabel);
|
||||
await this._removeLabel(issue, staleLabel);
|
||||
this._statistics?.incrementUndoStaleIssuesCount();
|
||||
}
|
||||
|
||||
private async _removeCloseLabel(
|
||||
@@ -748,7 +738,8 @@ export class IssuesProcessor {
|
||||
`The $$type has a close label "${closeLabel}". Removing the close label...`
|
||||
);
|
||||
|
||||
return this._removeLabel(issue, closeLabel);
|
||||
await this._removeLabel(issue, closeLabel);
|
||||
this._statistics?.incrementDeletedCloseLabelsCount();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
200
src/classes/statistics.ts
Normal file
200
src/classes/statistics.ts
Normal file
@@ -0,0 +1,200 @@
|
||||
import {IIssuesProcessorOptions} from '../interfaces/issues-processor-options';
|
||||
import {Logger} from './loggers/logger';
|
||||
|
||||
export class Statistics {
|
||||
private readonly _logger: Logger = new Logger();
|
||||
private readonly _options: IIssuesProcessorOptions;
|
||||
private _processedIssuesCount = 0;
|
||||
private _staleIssuesCount = 0;
|
||||
private _undoStaleIssuesCount = 0;
|
||||
private _operationsCount = 0;
|
||||
private _closedIssuesCount = 0;
|
||||
private _deletedLabelsCount = 0;
|
||||
private _deletedCloseLabelsCount = 0;
|
||||
private _deletedBranchesCount = 0;
|
||||
private _addedLabelsCount = 0;
|
||||
private _addedCommentsCount = 0;
|
||||
private _fetchedIssuesCount = 0;
|
||||
private _fetchedIssuesEventsCount = 0;
|
||||
private _fetchedIssuesCommentsCount = 0;
|
||||
private _fetchedPullRequestsCount = 0;
|
||||
|
||||
constructor(options: IIssuesProcessorOptions) {
|
||||
this._options = options;
|
||||
}
|
||||
|
||||
incrementProcessedIssuesCount(increment: Readonly<number> = 1): Statistics {
|
||||
this._processedIssuesCount += increment;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
incrementStaleIssuesCount(increment: Readonly<number> = 1): Statistics {
|
||||
this._staleIssuesCount += increment;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
incrementUndoStaleIssuesCount(increment: Readonly<number> = 1): Statistics {
|
||||
this._undoStaleIssuesCount += increment;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
setOperationsLeft(operationsLeft: Readonly<number>): Statistics {
|
||||
this._operationsCount = this._options.operationsPerRun - operationsLeft;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
incrementClosedIssuesCount(increment: Readonly<number> = 1): Statistics {
|
||||
this._closedIssuesCount += increment;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
incrementDeletedLabelsCount(increment: Readonly<number> = 1): Statistics {
|
||||
this._deletedLabelsCount += increment;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
incrementDeletedCloseLabelsCount(
|
||||
increment: Readonly<number> = 1
|
||||
): Statistics {
|
||||
this._deletedCloseLabelsCount += increment;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
incrementDeletedBranchesCount(increment: Readonly<number> = 1): Statistics {
|
||||
this._deletedBranchesCount += increment;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
incrementAddedLabel(increment: Readonly<number> = 1): Statistics {
|
||||
this._addedLabelsCount += increment;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
incrementAddedComment(increment: Readonly<number> = 1): Statistics {
|
||||
this._addedCommentsCount += increment;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
incrementFetchedIssuesCount(increment: Readonly<number> = 1): Statistics {
|
||||
this._fetchedIssuesCount += increment;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
incrementFetchedIssuesEventsCount(
|
||||
increment: Readonly<number> = 1
|
||||
): Statistics {
|
||||
this._fetchedIssuesEventsCount += increment;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
incrementFetchedIssuesCommentsCount(
|
||||
increment: Readonly<number> = 1
|
||||
): Statistics {
|
||||
this._fetchedIssuesCommentsCount += increment;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
incrementFetchedPullRequestsCount(
|
||||
increment: Readonly<number> = 1
|
||||
): Statistics {
|
||||
this._fetchedPullRequestsCount += increment;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
logStats(): Statistics {
|
||||
this._logger.info('Statistics');
|
||||
this._logProcessedIssuesCount();
|
||||
this._logStaleIssuesCount();
|
||||
this._logUndoStaleIssuesCount();
|
||||
this._logOperationsCount();
|
||||
this._logClosedIssuesCount();
|
||||
this._logDeletedLabelsCount();
|
||||
this._logDeletedCloseLabelsCount();
|
||||
this._logDeletedBranchesCount();
|
||||
this._logAddedLabelsCount();
|
||||
this._logAddedCommentsCount();
|
||||
this._logFetchedIssuesCount();
|
||||
this._logFetchedIssuesEventsCount();
|
||||
this._logFetchedIssuesCommentsCount();
|
||||
this._logFetchedPullRequestsCount();
|
||||
this._logger.info('---');
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
private _logProcessedIssuesCount(): void {
|
||||
this._logCount('Processed issues/PRs', this._processedIssuesCount);
|
||||
}
|
||||
|
||||
private _logStaleIssuesCount(): void {
|
||||
this._logCount('New stale issues/PRs', this._staleIssuesCount);
|
||||
}
|
||||
|
||||
private _logUndoStaleIssuesCount(): void {
|
||||
this._logCount('No longer stale issues/PRs', this._undoStaleIssuesCount);
|
||||
}
|
||||
|
||||
private _logOperationsCount(): void {
|
||||
this._logCount('Operations performed', this._operationsCount);
|
||||
}
|
||||
|
||||
private _logClosedIssuesCount(): void {
|
||||
this._logCount('Closed issues', this._closedIssuesCount);
|
||||
}
|
||||
|
||||
private _logDeletedLabelsCount(): void {
|
||||
this._logCount('Deleted labels', this._deletedLabelsCount);
|
||||
}
|
||||
|
||||
private _logDeletedCloseLabelsCount(): void {
|
||||
this._logCount('Deleted close labels', this._deletedCloseLabelsCount);
|
||||
}
|
||||
|
||||
private _logDeletedBranchesCount(): void {
|
||||
this._logCount('Deleted branches', this._deletedBranchesCount);
|
||||
}
|
||||
|
||||
private _logAddedLabelsCount(): void {
|
||||
this._logCount('Added labels', this._addedLabelsCount);
|
||||
}
|
||||
|
||||
private _logAddedCommentsCount(): void {
|
||||
this._logCount('Added comments', this._addedCommentsCount);
|
||||
}
|
||||
|
||||
private _logFetchedIssuesCount(): void {
|
||||
this._logCount('Fetched issues', this._fetchedIssuesCount);
|
||||
}
|
||||
|
||||
private _logFetchedIssuesEventsCount(): void {
|
||||
this._logCount('Fetched issues events', this._fetchedIssuesEventsCount);
|
||||
}
|
||||
|
||||
private _logFetchedIssuesCommentsCount(): void {
|
||||
this._logCount('Fetched issues comments', this._fetchedIssuesCommentsCount);
|
||||
}
|
||||
|
||||
private _logFetchedPullRequestsCount(): void {
|
||||
this._logCount('Fetched pull requests', this._fetchedPullRequestsCount);
|
||||
}
|
||||
|
||||
private _logCount(name: Readonly<string>, count: Readonly<number>): void {
|
||||
if (count > 0) {
|
||||
this._logger.info(`${name}: ${count}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
import {getIssueType} from './get-issue-type';
|
||||
|
||||
describe('getIssueType()', (): void => {
|
||||
let isPullRequest: boolean;
|
||||
|
||||
describe('when the issue is a not pull request', (): void => {
|
||||
beforeEach((): void => {
|
||||
isPullRequest = false;
|
||||
});
|
||||
|
||||
it('should return that the issue is really an issue', (): void => {
|
||||
expect.assertions(1);
|
||||
|
||||
const result = getIssueType(isPullRequest);
|
||||
|
||||
expect(result).toStrictEqual('issue');
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the issue is a pull request', (): void => {
|
||||
beforeEach((): void => {
|
||||
isPullRequest = true;
|
||||
});
|
||||
|
||||
it('should return that the issue is a pull request', (): void => {
|
||||
expect.assertions(1);
|
||||
|
||||
const result = getIssueType(isPullRequest);
|
||||
|
||||
expect(result).toStrictEqual('pr');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,5 +0,0 @@
|
||||
import {IssueType} from '../enums/issue-type';
|
||||
|
||||
export function getIssueType(isPullRequest: Readonly<boolean>): IssueType {
|
||||
return isPullRequest ? IssueType.PullRequest : IssueType.Issue;
|
||||
}
|
||||
@@ -42,4 +42,5 @@ export interface IIssuesProcessorOptions {
|
||||
exemptAllAssignees: boolean;
|
||||
exemptAllIssueAssignees: boolean | undefined;
|
||||
exemptAllPrAssignees: boolean | undefined;
|
||||
enableStatistics: boolean;
|
||||
}
|
||||
|
||||
@@ -68,7 +68,8 @@ function _getAndValidateArgs(): IIssuesProcessorOptions {
|
||||
exemptPrAssignees: core.getInput('exempt-pr-assignees'),
|
||||
exemptAllAssignees: core.getInput('exempt-all-assignees') === 'true',
|
||||
exemptAllIssueAssignees: _toOptionalBoolean('exempt-all-issue-assignees'),
|
||||
exemptAllPrAssignees: _toOptionalBoolean('exempt-all-pr-assignees')
|
||||
exemptAllPrAssignees: _toOptionalBoolean('exempt-all-pr-assignees'),
|
||||
enableStatistics: core.getInput('enable-statistics') === 'true'
|
||||
};
|
||||
|
||||
for (const numberInput of [
|
||||
|
||||
Reference in New Issue
Block a user