Skip to content

Commit

Permalink
Feature: Added intervals
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexSim93 committed Mar 3, 2024
1 parent 5ff16f6 commit f2cc4df
Show file tree
Hide file tree
Showing 13 changed files with 272 additions and 37 deletions.
76 changes: 44 additions & 32 deletions README.md

Large diffs are not rendered by default.

9 changes: 9 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,15 @@ inputs:
description: "Amount of items in lists"
required: false
default: "5"
REVIEW_TIME_INTERVALS:
description: "Intervals for determining review times distribution"
required: false
APPROVAL_TIME_INTERVALS:
description: "Intervals for determining approval times distribution"
required: false
MERGE_TIME_INTERVALS:
description: "Intervals for determining merge times distribution"
required: false
PERIOD_SPLIT_UNIT:
description: "Unit for time segmentation. Can take values: 'years', 'quarters', 'months', 'none'"
required: false
Expand Down
112 changes: 109 additions & 3 deletions build/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "pull-request-analytics-action",
"version": "2.1.0",
"version": "2.2.0",
"description": "Generates detailed PR analytics reports within GitHub, focusing on review efficiency and team performance.",
"main": "build/index.js",
"scripts": {
Expand Down
3 changes: 3 additions & 0 deletions src/converters/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ export type Collection = {
median?: TimelinePoints;
percentile?: TimelinePoints;
average?: TimelinePoints;
reviewTimeIntervals?: { [key: string]: number };
approvalTimeIntervals?: { [key: string]: number };
mergeTimeIntervals?: { [key: string]: number };
timeInDraft?: number[];
timeToReviewRequest?: number[];
timeToReview?: number[];
Expand Down
19 changes: 19 additions & 0 deletions src/converters/utils/calculations/calcIntervals.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
export const calcIntervals = (
values: number[] | undefined,
intervals: [number, number][] | undefined
) => {
const initial = intervals?.reduce(
(acc, interval) => ({ ...acc, [`${interval?.[0]}-${interval?.[1]}`]: 0 }),
{}
);
return values
?.map((value) => value)
.reduce((acc, value) => {
const interval = intervals?.find(
(interval) => value >= interval[0] && value < interval[1]
);
if (!interval) return acc;
const key = `${interval?.[0]}-${interval?.[1]}`;
return { ...acc, [key]: (acc[key] || 0) + 1 };
}, initial as Record<string, number>);
};
2 changes: 2 additions & 0 deletions src/converters/utils/calculations/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
export { prepareIntervals } from './prepareIntervals';
export { calcIntervals } from './calcIntervals';
export { calcPercentileValue } from "./calcPercentileValue";
export { getApproveTime } from "./getApproveTime";
export { calcWeekendMinutes } from "./calcWeekendMinutes";
Expand Down
14 changes: 14 additions & 0 deletions src/converters/utils/calculations/prepareIntervals.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export const prepareIntervals = (numbers: number[]): [number, number][] => {
return numbers.length > 0
? numbers
.slice()
.concat(Infinity)
.sort((a, b) => a - b)
.map((point, index, arr) => {
if (index === 0) {
return [0, point];
}
return [arr[index - 1], point];
})
: [];
};
26 changes: 26 additions & 0 deletions src/converters/utils/preparePullRequestStats.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,39 @@
import { getMultipleValuesInput } from "../../common/utils";
import { Collection } from "../types";
import {
calcAverageValue,
calcIntervals,
calcMedianValue,
calcPercentileValue,
prepareIntervals,
} from "./calculations";

export const preparePullRequestStats = (collection: Collection) => {
const reviewIntervals = prepareIntervals(
getMultipleValuesInput("REVIEW_TIME_INTERVALS").map((el) => parseFloat(el))
);
const approvalIntervals = prepareIntervals(
getMultipleValuesInput("APPROVAL_TIME_INTERVALS").map((el) =>
parseFloat(el)
)
);
const mergeIntervals = prepareIntervals(
getMultipleValuesInput("MERGE_TIME_INTERVALS").map((el) => parseFloat(el))
);
return {
...collection,
reviewTimeIntervals: calcIntervals(
collection.timeToReview?.map((el) => el / 60),
reviewIntervals
),
approvalTimeIntervals: calcIntervals(
collection.timeToApprove?.map((el) => el / 60),
approvalIntervals
),
mergeTimeIntervals: calcIntervals(
collection.timeToMerge?.map((el) => el / 60),
mergeIntervals
),
median: {
timeToReview: calcMedianValue(collection.timeToReview),
timeToApprove: calcMedianValue(collection.timeToApprove),
Expand Down
3 changes: 3 additions & 0 deletions src/view/utils/createConfigParamsCode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ ${[
"ASSIGNEES",
"LABELS",
"SHOW_STATS_TYPES",
"REVIEW_TIME_INTERVALS",
"APPROVAL_TIME_INTERVALS",
"MERGE_TIME_INTERVALS",
"TOP_LIST_AMOUNT",
"AGGREGATE_VALUE_METHODS",
"PERCENTILE",
Expand Down
2 changes: 1 addition & 1 deletion src/view/utils/createDiscussionsPieChart.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createPieChart } from ".";
import { createPieChart } from "./common";
import { Collection } from "../../converters/types";

export const createDiscussionsPieChart = (
Expand Down
4 changes: 4 additions & 0 deletions src/view/utils/createTimelineContent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { createTimelineGanttBar } from "./createTimelineGanttBar";
import { createTimelineTable } from "./createTimelineTable";
import { StatsType } from "./types";
import { formatMinutesDuration } from "./formatMinutesDuration";
import { createTimelinePieChart } from "./createTimelinePieChart";

type Type = "timeToReview" | "timeToApprove" | "timeToMerge";

Expand Down Expand Up @@ -63,6 +64,9 @@ ${pullRequestTimelineBar}

return `
${timeline}
${createTimelinePieChart(data, users, date, "reviewTimeIntervals")}
${createTimelinePieChart(data, users, date, "approvalTimeIntervals")}
${createTimelinePieChart(data, users, date, "mergeTimeIntervals")}
${problematicList}
`;
};
37 changes: 37 additions & 0 deletions src/view/utils/createTimelinePieChart.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { createPieChart } from "./common";
import { Collection } from "../../converters/types";

const titleMap = {
reviewTimeIntervals: "Review time",
approvalTimeIntervals: "Approval time",
mergeTimeIntervals: "Merge time",
};

export const createTimelinePieChart = (
data: Record<string, Record<string, Collection>>,
users: string[],
date: string,
key: "reviewTimeIntervals" | "approvalTimeIntervals" | "mergeTimeIntervals"
) => {
return users
.map((user) => ({
user,
values: data[user][date]?.[key],
}))
.filter(
(types) =>
types.values && Object.values(types.values).some((value) => value)
)
.map((data) => {
const values = Object.entries(data.values!)
.filter(([key, value]) => value)
.reduce((acc, value) => {
return {
...acc,
[`${value[0].replace("-Infinity", "+")} hours`]: value[1],
};
}, {});
return createPieChart(`${titleMap[key]} ${data.user} ${date}`, values);
})
.join("\n");
};

0 comments on commit f2cc4df

Please sign in to comment.