feat(statistics): split the stats between issues and PRs (#364)

* docs(only-labels): enhance the docs and fix duplicate (#341)

* docs(only-labels): remove duplicated option and improve descriptions

a bad rebase happend

* docs(readme): use a multi-line array and remove the optional column

the option column was not helpful since each value is optional
the multi-line array will allow to have a better UI in small devices and basically in GitHub too due to the max-width

* style(readme): break line for the statistics

* docs(readme): add a better description for the ascending option

* docs(action): add missing punctuation

* build(deps-dev): bump @typescript-eslint/eslint-plugin (#342)

Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 4.15.2 to 4.16.1.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v4.16.1/packages/eslint-plugin)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* build(deps): bump @octokit/rest from 18.3.0 to 18.3.2 (#350)

Bumps [@octokit/rest](https://github.com/octokit/rest.js) from 18.3.0 to 18.3.2.
- [Release notes](https://github.com/octokit/rest.js/releases)
- [Commits](https://github.com/octokit/rest.js/compare/v18.3.0...v18.3.2)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* test: add more coverage for the stale label behaviour (#352) (#15)

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* test: add more coverage for the stale label behaviour (#352) (#17)

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* test(refactor): use toHaveLength

* feat(statistics): split the processed issues and prs

* feat(statistics): split the new stale issues and prs

* feat(statistics): split the no longer stale issues and prs

* chore(deps): undo upgrade of dependencies

* feat(statistics): split closed issues and prs

* feat(statistics): use the word "items" when something concern both issues and prs

* feat(statistics): split more stats by issues and prs

* feat(statistics): split more stats by issues and prs (final)

* chore(index): update it

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
This commit is contained in:
Geoffrey Testelin
2021-04-27 20:47:02 +02:00
committed by GitHub
parent 10eec4583b
commit 5e20aa8410
4 changed files with 841 additions and 303 deletions

View File

@@ -94,7 +94,7 @@ export class IssuesProcessor {
for (const issue of issues.values()) {
const issueLogger: IssueLogger = new IssueLogger(issue);
this._statistics?.incrementProcessedIssuesCount();
this._statistics?.incrementProcessedItemsCount(issue);
issueLogger.info(`Found this $$type last updated ${issue.updated_at}`);
@@ -320,7 +320,7 @@ export class IssuesProcessor {
// find any comments since date on the given issue
try {
this._operations.consumeOperation();
this._statistics?.incrementFetchedIssuesCommentsCount();
this._statistics?.incrementFetchedItemsCommentsCount();
const comments = await this.client.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
@@ -366,7 +366,7 @@ export class IssuesProcessor {
page
}
);
this._statistics?.incrementFetchedIssuesCount(issueResult.data.length);
this._statistics?.incrementFetchedItemsCount(issueResult.data.length);
return issueResult.data.map(
(issue: Readonly<IIssue>): Issue => new Issue(this.options, issue)
@@ -388,7 +388,7 @@ export class IssuesProcessor {
issueLogger.info(`Checking for label on $$type`);
this._operations.consumeOperation();
this._statistics?.incrementFetchedIssuesEventsCount();
this._statistics?.incrementFetchedItemsEventsCount();
const options = this.client.issues.listEvents.endpoint.merge({
owner: context.repo.owner,
repo: context.repo.repo,
@@ -526,7 +526,7 @@ export class IssuesProcessor {
if (!skipMessage) {
try {
this._operations.consumeOperation();
this._statistics?.incrementAddedComment();
this._statistics?.incrementAddedItemsComment(issue);
await this.client.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
@@ -540,8 +540,8 @@ export class IssuesProcessor {
try {
this._operations.consumeOperation();
this._statistics?.incrementAddedLabel();
this._statistics?.incrementStaleIssuesCount();
this._statistics?.incrementAddedItemsLabel(issue);
this._statistics?.incrementStaleItemsCount(issue);
await this.client.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
@@ -571,7 +571,7 @@ export class IssuesProcessor {
if (closeMessage) {
try {
this._operations.consumeOperation();
this._statistics?.incrementAddedComment();
this._statistics?.incrementAddedItemsComment(issue);
await this.client.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
@@ -586,7 +586,7 @@ export class IssuesProcessor {
if (closeLabel) {
try {
this._operations.consumeOperation();
this._statistics?.incrementAddedLabel();
this._statistics?.incrementAddedItemsLabel(issue);
await this.client.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
@@ -600,7 +600,7 @@ export class IssuesProcessor {
try {
this._operations.consumeOperation();
this._statistics?.incrementClosedIssuesCount();
this._statistics?.incrementClosedItemsCount(issue);
await this.client.issues.update({
owner: context.repo.owner,
repo: context.repo.repo,
@@ -673,7 +673,7 @@ export class IssuesProcessor {
}
}
// Remove a label from an issue
// Remove a label from an issue or a pull request
private async _removeLabel(issue: Issue, label: string): Promise<void> {
const issueLogger: IssueLogger = new IssueLogger(issue);
@@ -686,7 +686,7 @@ export class IssuesProcessor {
try {
this._operations.consumeOperation();
this._statistics?.incrementDeletedLabelsCount();
this._statistics?.incrementDeletedItemsLabelsCount(issue);
await this.client.issues.removeLabel({
owner: context.repo.owner,
repo: context.repo.repo,
@@ -747,7 +747,7 @@ export class IssuesProcessor {
);
await this._removeLabel(issue, staleLabel);
this._statistics?.incrementUndoStaleIssuesCount();
this._statistics?.incrementUndoStaleItemsCount(issue);
}
private async _removeCloseLabel(
@@ -772,7 +772,7 @@ export class IssuesProcessor {
);
await this._removeLabel(issue, closeLabel);
this._statistics?.incrementDeletedCloseLabelsCount();
this._statistics?.incrementDeletedCloseItemsLabelsCount(issue);
}
}
}

View File

@@ -1,39 +1,68 @@
import chalk from 'chalk';
import {Issue} from './issue';
import {Logger} from './loggers/logger';
interface IGroupValue {
name: string;
count: number;
}
export class Statistics {
private readonly _logger: Logger = new Logger();
private _processedIssuesCount = 0;
private _processedPullRequestsCount = 0;
private _staleIssuesCount = 0;
private _stalePullRequestsCount = 0;
private _undoStaleIssuesCount = 0;
private _undoStalePullRequestsCount = 0;
private _operationsCount = 0;
private _closedIssuesCount = 0;
private _deletedLabelsCount = 0;
private _deletedCloseLabelsCount = 0;
private _closedPullRequestsCount = 0;
private _deletedIssuesLabelsCount = 0;
private _deletedPullRequestsLabelsCount = 0;
private _deletedCloseIssuesLabelsCount = 0;
private _deletedClosePullRequestsLabelsCount = 0;
private _deletedBranchesCount = 0;
private _addedLabelsCount = 0;
private _addedCommentsCount = 0;
private _fetchedIssuesCount = 0;
private _fetchedIssuesEventsCount = 0;
private _fetchedIssuesCommentsCount = 0;
private _addedIssuesLabelsCount = 0;
private _addedPullRequestsLabelsCount = 0;
private _addedIssuesCommentsCount = 0;
private _addedPullRequestsCommentsCount = 0;
private _fetchedItemsCount = 0;
private _fetchedItemsEventsCount = 0;
private _fetchedItemsCommentsCount = 0;
private _fetchedPullRequestsCount = 0;
incrementProcessedIssuesCount(increment: Readonly<number> = 1): Statistics {
this._processedIssuesCount += increment;
incrementProcessedItemsCount(
issue: Readonly<Issue>,
increment: Readonly<number> = 1
): Statistics {
if (issue.isPullRequest) {
return this._incrementProcessedPullRequestsCount(increment);
}
return this;
return this._incrementProcessedIssuesCount(increment);
}
incrementStaleIssuesCount(increment: Readonly<number> = 1): Statistics {
this._staleIssuesCount += increment;
incrementStaleItemsCount(
issue: Readonly<Issue>,
increment: Readonly<number> = 1
): Statistics {
if (issue.isPullRequest) {
return this._incrementStalePullRequestsCount(increment);
}
return this;
return this._incrementStaleIssuesCount(increment);
}
incrementUndoStaleIssuesCount(increment: Readonly<number> = 1): Statistics {
this._undoStaleIssuesCount += increment;
incrementUndoStaleItemsCount(
issue: Readonly<Issue>,
increment: Readonly<number> = 1
): Statistics {
if (issue.isPullRequest) {
return this._incrementUndoStalePullRequestsCount(increment);
}
return this;
return this._incrementUndoStaleIssuesCount(increment);
}
setOperationsLeft(operationsLeft: Readonly<number>): Statistics {
@@ -42,24 +71,37 @@ export class Statistics {
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(
incrementClosedItemsCount(
issue: Readonly<Issue>,
increment: Readonly<number> = 1
): Statistics {
this._deletedCloseLabelsCount += increment;
if (issue.isPullRequest) {
return this._incrementClosedPullRequestsCount(increment);
}
return this;
return this._incrementClosedIssuesCount(increment);
}
incrementDeletedItemsLabelsCount(
issue: Readonly<Issue>,
increment: Readonly<number> = 1
): Statistics {
if (issue.isPullRequest) {
return this._incrementDeletedPullRequestsLabelsCount(increment);
}
return this._incrementDeletedIssuesLabelsCount(increment);
}
incrementDeletedCloseItemsLabelsCount(
issue: Readonly<Issue>,
increment: Readonly<number> = 1
): Statistics {
if (issue.isPullRequest) {
return this._incrementDeletedClosePullRequestsLabelsCount(increment);
}
return this._incrementDeletedCloseIssuesLabelsCount(increment);
}
incrementDeletedBranchesCount(increment: Readonly<number> = 1): Statistics {
@@ -68,36 +110,46 @@ export class Statistics {
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(
incrementAddedItemsLabel(
issue: Readonly<Issue>,
increment: Readonly<number> = 1
): Statistics {
this._fetchedIssuesEventsCount += increment;
if (issue.isPullRequest) {
return this._incrementAddedPullRequestsLabel(increment);
}
return this._incrementAddedIssuesLabel(increment);
}
incrementAddedItemsComment(
issue: Readonly<Issue>,
increment: Readonly<number> = 1
): Statistics {
if (issue.isPullRequest) {
return this._incrementAddedPullRequestsComment(increment);
}
return this._incrementAddedIssuesComment(increment);
}
incrementFetchedItemsCount(increment: Readonly<number> = 1): Statistics {
this._fetchedItemsCount += increment;
return this;
}
incrementFetchedIssuesCommentsCount(
incrementFetchedItemsEventsCount(
increment: Readonly<number> = 1
): Statistics {
this._fetchedIssuesCommentsCount += increment;
this._fetchedItemsEventsCount += increment;
return this;
}
incrementFetchedItemsCommentsCount(
increment: Readonly<number> = 1
): Statistics {
this._fetchedItemsCommentsCount += increment;
return this;
}
@@ -112,83 +164,357 @@ export class Statistics {
logStats(): Statistics {
this._logger.info(chalk.yellow.bold('Statistics:'));
this._logProcessedIssuesCount();
this._logStaleIssuesCount();
this._logUndoStaleIssuesCount();
this._logOperationsCount();
this._logClosedIssuesCount();
this._logDeletedLabelsCount();
this._logDeletedCloseLabelsCount();
this._logProcessedIssuesAndPullRequestsCount();
this._logStaleIssuesAndPullRequestsCount();
this._logUndoStaleIssuesAndPullRequestsCount();
this._logClosedIssuesAndPullRequestsCount();
this._logDeletedIssuesAndPullRequestsLabelsCount();
this._logDeletedCloseIssuesAndPullRequestsLabelsCount();
this._logDeletedBranchesCount();
this._logAddedLabelsCount();
this._logAddedCommentsCount();
this._logFetchedIssuesCount();
this._logFetchedIssuesEventsCount();
this._logFetchedIssuesCommentsCount();
this._logAddedIssuesAndPullRequestsLabelsCount();
this._logAddedIssuesAndPullRequestsCommentsCount();
this._logFetchedItemsCount();
this._logFetchedItemsEventsCount();
this._logFetchedItemsCommentsCount();
this._logFetchedPullRequestsCount();
this._logOperationsCount();
return this;
}
private _logProcessedIssuesCount(): void {
this._logCount('Processed issues/PRs', this._processedIssuesCount);
private _incrementProcessedIssuesCount(
increment: Readonly<number> = 1
): Statistics {
this._processedIssuesCount += increment;
return this;
}
private _logStaleIssuesCount(): void {
this._logCount('New stale issues/PRs', this._staleIssuesCount);
private _incrementProcessedPullRequestsCount(
increment: Readonly<number> = 1
): Statistics {
this._processedPullRequestsCount += increment;
return this;
}
private _logUndoStaleIssuesCount(): void {
this._logCount('No longer stale issues/PRs', this._undoStaleIssuesCount);
private _incrementStaleIssuesCount(
increment: Readonly<number> = 1
): Statistics {
this._staleIssuesCount += increment;
return this;
}
private _logOperationsCount(): void {
this._logCount('Operations performed', this._operationsCount);
private _incrementStalePullRequestsCount(
increment: Readonly<number> = 1
): Statistics {
this._stalePullRequestsCount += increment;
return this;
}
private _logClosedIssuesCount(): void {
this._logCount('Closed issues', this._closedIssuesCount);
private _incrementUndoStaleIssuesCount(
increment: Readonly<number> = 1
): Statistics {
this._undoStaleIssuesCount += increment;
return this;
}
private _logDeletedLabelsCount(): void {
this._logCount('Deleted labels', this._deletedLabelsCount);
private _incrementUndoStalePullRequestsCount(
increment: Readonly<number> = 1
): Statistics {
this._undoStalePullRequestsCount += increment;
return this;
}
private _logDeletedCloseLabelsCount(): void {
this._logCount('Deleted close labels', this._deletedCloseLabelsCount);
private _incrementClosedIssuesCount(
increment: Readonly<number> = 1
): Statistics {
this._closedIssuesCount += increment;
return this;
}
private _incrementClosedPullRequestsCount(
increment: Readonly<number> = 1
): Statistics {
this._closedPullRequestsCount += increment;
return this;
}
private _incrementDeletedIssuesLabelsCount(
increment: Readonly<number> = 1
): Statistics {
this._deletedIssuesLabelsCount += increment;
return this;
}
private _incrementDeletedPullRequestsLabelsCount(
increment: Readonly<number> = 1
): Statistics {
this._deletedPullRequestsLabelsCount += increment;
return this;
}
private _incrementDeletedCloseIssuesLabelsCount(
increment: Readonly<number> = 1
): Statistics {
this._deletedCloseIssuesLabelsCount += increment;
return this;
}
private _incrementDeletedClosePullRequestsLabelsCount(
increment: Readonly<number> = 1
): Statistics {
this._deletedClosePullRequestsLabelsCount += increment;
return this;
}
private _incrementAddedIssuesLabel(
increment: Readonly<number> = 1
): Statistics {
this._addedIssuesLabelsCount += increment;
return this;
}
private _incrementAddedPullRequestsLabel(
increment: Readonly<number> = 1
): Statistics {
this._addedPullRequestsLabelsCount += increment;
return this;
}
private _incrementAddedIssuesComment(
increment: Readonly<number> = 1
): Statistics {
this._addedIssuesCommentsCount += increment;
return this;
}
private _incrementAddedPullRequestsComment(
increment: Readonly<number> = 1
): Statistics {
this._addedPullRequestsCommentsCount += increment;
return this;
}
private _logProcessedIssuesAndPullRequestsCount(): void {
this._logGroup('Processed items', [
{
name: 'Processed issues',
count: this._processedIssuesCount
},
{
name: 'Processed PRs',
count: this._processedPullRequestsCount
}
]);
}
private _logStaleIssuesAndPullRequestsCount(): void {
this._logGroup('New stale items', [
{
name: 'New stale issues',
count: this._staleIssuesCount
},
{
name: 'New stale PRs',
count: this._stalePullRequestsCount
}
]);
}
private _logUndoStaleIssuesAndPullRequestsCount(): void {
this._logGroup('No longer stale items', [
{
name: 'No longer stale issues',
count: this._undoStaleIssuesCount
},
{
name: 'No longer stale PRs',
count: this._undoStalePullRequestsCount
}
]);
}
private _logClosedIssuesAndPullRequestsCount(): void {
this._logGroup('Closed items', [
{
name: 'Closed issues',
count: this._closedIssuesCount
},
{
name: 'Closed PRs',
count: this._closedPullRequestsCount
}
]);
}
private _logDeletedIssuesAndPullRequestsLabelsCount(): void {
this._logGroup('Deleted items labels', [
{
name: 'Deleted issues labels',
count: this._deletedIssuesLabelsCount
},
{
name: 'Deleted PRs labels',
count: this._deletedPullRequestsLabelsCount
}
]);
}
private _logDeletedCloseIssuesAndPullRequestsLabelsCount(): void {
this._logGroup('Deleted close items labels', [
{
name: 'Deleted close issues labels',
count: this._deletedCloseIssuesLabelsCount
},
{
name: 'Deleted close PRs labels',
count: this._deletedClosePullRequestsLabelsCount
}
]);
}
private _logDeletedBranchesCount(): void {
this._logCount('Deleted branches', this._deletedBranchesCount);
}
private _logAddedLabelsCount(): void {
this._logCount('Added labels', this._addedLabelsCount);
private _logAddedIssuesAndPullRequestsLabelsCount(): void {
this._logGroup('Added items labels', [
{
name: 'Added issues labels',
count: this._addedIssuesLabelsCount
},
{
name: 'Added PRs labels',
count: this._addedPullRequestsLabelsCount
}
]);
}
private _logAddedCommentsCount(): void {
this._logCount('Added comments', this._addedCommentsCount);
private _logAddedIssuesAndPullRequestsCommentsCount(): void {
this._logGroup('Added items comments', [
{
name: 'Added issues comments',
count: this._addedIssuesCommentsCount
},
{
name: 'Added PRs comments',
count: this._addedPullRequestsCommentsCount
}
]);
}
private _logFetchedIssuesCount(): void {
this._logCount('Fetched issues', this._fetchedIssuesCount);
private _logFetchedItemsCount(): void {
this._logCount('Fetched items', this._fetchedItemsCount);
}
private _logFetchedIssuesEventsCount(): void {
this._logCount('Fetched issues events', this._fetchedIssuesEventsCount);
private _logFetchedItemsEventsCount(): void {
this._logCount('Fetched items events', this._fetchedItemsEventsCount);
}
private _logFetchedIssuesCommentsCount(): void {
this._logCount('Fetched issues comments', this._fetchedIssuesCommentsCount);
private _logFetchedItemsCommentsCount(): void {
this._logCount('Fetched items comments', this._fetchedItemsCommentsCount);
}
private _logFetchedPullRequestsCount(): void {
this._logCount('Fetched pull requests', this._fetchedPullRequestsCount);
}
private _logOperationsCount(): void {
this._logCount('Operations performed', this._operationsCount);
}
private _logCount(name: Readonly<string>, count: Readonly<number>): void {
if (count > 0) {
this._logger.info(`${name}:`, chalk.cyan(count));
}
}
private _logGroup(groupName: Readonly<string>, values: IGroupValue[]): void {
if (this._isGroupValuesPartiallySet(values)) {
this._logCount(groupName, this._getGroupValuesTotalCount(values));
this._logGroupValues(values);
} else {
// Only one value will be display
for (const value of values) {
this._logCount(value.name, value.count);
}
}
}
/**
* @private
* @description
* If there is a least two elements with a valid count then it's partially set
* Useful to defined if we should display the values as a group or not
*
* @param {IGroupValue[]} values The list of group values to check
*/
private _isGroupValuesPartiallySet(values: IGroupValue[]): boolean {
return (
values
.map((value: Readonly<IGroupValue>): boolean => {
return value.count > 0;
})
.filter((isSet: Readonly<boolean>): boolean => isSet).length >= 2
);
}
private _getGroupValuesTotalCount(values: IGroupValue[]): number {
return values.reduce(
(count: Readonly<number>, value: Readonly<IGroupValue>): number => {
return count + value.count;
},
0
);
}
private _getAllGroupValuesSet(values: IGroupValue[]): IGroupValue[] {
return values.filter((value: Readonly<IGroupValue>): boolean => {
return value.count > 0;
});
}
private _logGroupValues(values: IGroupValue[]): void {
const onlyValuesSet: IGroupValue[] = this._getAllGroupValuesSet(values);
const longestValue: number = this._getLongestGroupValue(onlyValuesSet);
for (const [index, value] of onlyValuesSet.entries()) {
const prefix = index === onlyValuesSet.length - 1 ? '└──' : '├──';
this._logCount(
`${chalk.white(prefix)} ${value.name.padEnd(longestValue, ' ')}`,
value.count
);
}
}
private _getLongestGroupValue(values: IGroupValue[]): number {
return values.reduce(
(
longestValue: Readonly<number>,
value: Readonly<IGroupValue>
): number => {
return value.name.length > longestValue
? value.name.length
: longestValue;
},
0
);
}
}