Skip to content

Commit a7e9082

Browse files
authored
feat: change script to support more than 1 git repository gf-589 (#590)
* feat: script should support more than 1 local git repository gf-589 (#589) * feat: script should support more than 1 local git repository gf-589 (#589) - moved helpers into src/libs/helpers - changed functions to arrow functions
1 parent 33d95b3 commit a7e9082

File tree

8 files changed

+90
-26
lines changed

8 files changed

+90
-26
lines changed

apps/frontend/src/pages/project/libs/components/setup-analytics-modal/setup-analytics-modal.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ const SetupAnalyticsModal = ({
5757
const apiKey = project.apiKey as string;
5858
const userId = String(authenticatedUser.id);
5959

60-
return `npx @git-fit/analytics@latest track ${apiKey} ${userId} <project-path>`;
60+
return `npx @git-fit/analytics@latest track ${apiKey} ${userId} <project-path-1> <project-path-2> ...`;
6161
}, [hasProjectApiKey, hasAuthenticatedUser, project, authenticatedUser]);
6262

6363
const { control, errors, handleSubmit, handleValueSet } = useAppForm({
@@ -233,8 +233,9 @@ const SetupAnalyticsModal = ({
233233
Prepare the script.
234234
</span>
235235
<p className={styles["list-item-text"]}>
236-
Copy the command below and replace &lt;project-path&gt;
237-
placeholder with your local repository&apos;s path:
236+
Copy the command below and replace &lt;project-path-1&gt;,
237+
&lt;project-path-2&gt;, ... placeholder with your local
238+
repositories paths:
238239
</p>
239240
<Input
240241
control={control}

scripts/analytics/src/libs/modules/analytics-cli/base-analytics-cli.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import pm2 from "pm2";
44

55
import { executeCommand } from "~/libs/helpers/helpers.js";
66
import { type Logger } from "~/libs/modules/logger/logger.js";
7+
import { EMPTY_LENGTH } from "~/modules/analytics/libs/constants/constants.js";
78
import { type AuthAnalyticsService } from "~/modules/auth-analytics/auth-analytics.js";
89

910
type Constructor = {
@@ -46,10 +47,10 @@ class BaseAnalyticsCli {
4647

4748
private setupCommands(): void {
4849
this.program
49-
.command("track <apiKey> <userId> <repoPath>")
50+
.command("track <apiKey> <userId> <repoPaths...>")
5051
.description("Start the background job for collecting statistics")
51-
.action(async (apiKey: string, userId: string, repoPath: string) => {
52-
if (!apiKey || !userId || !repoPath) {
52+
.action(async (apiKey: string, userId: string, repoPaths: string[]) => {
53+
if (!apiKey || !userId || repoPaths.length === EMPTY_LENGTH) {
5354
this.logger.error("Not all command arguments are provided.");
5455

5556
return;
@@ -80,7 +81,7 @@ class BaseAnalyticsCli {
8081

8182
pm2.start(
8283
{
83-
args: [apiKey, userId, repoPath],
84+
args: [apiKey, userId, ...repoPaths],
8485
autorestart: false,
8586
error: `${project.projectName}-err.log`,
8687
name: project.projectName,

scripts/analytics/src/libs/modules/analytics-cli/init-analytics-cli.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,15 @@ import {
1010
CRON_SCHEDULE,
1111
} from "./libs/constants/constants.js";
1212

13-
const [apiKey, userId, repoPath] = process.argv.slice(ARGUMENT_START_INDEX) as [
14-
string,
15-
string,
16-
string,
17-
];
13+
const [apiKey, userId, ...repoPaths] = process.argv.slice(
14+
ARGUMENT_START_INDEX,
15+
) as [string, string, string];
1816

1917
const analyticsService = new AnalyticsService({
2018
analyticsApi,
2119
apiKey,
2220
gitService,
23-
repoPath,
21+
repoPaths,
2422
userId,
2523
});
2624

scripts/analytics/src/modules/analytics/analytics.service.ts

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
EMPTY_LENGTH,
99
FIRST_ARRAY_INDEX,
1010
} from "./libs/constants/constants.js";
11+
import { mergeStats } from "./libs/helpers/helpers.js";
1112
import {
1213
type ActivityLogCreateItemRequestDto,
1314
type CommitStatistics,
@@ -17,37 +18,37 @@ type Constructor = {
1718
analyticsApi: typeof analyticsApi;
1819
apiKey: string;
1920
gitService: GITService;
20-
repoPath: string;
21+
repoPaths: string[];
2122
userId: string;
2223
};
2324

2425
class AnalyticsService {
2526
private analyticsApi: typeof analyticsApi;
2627
private apiKey: string;
2728
private gitService: GITService;
28-
private repoPath: string;
29+
private repoPaths: string[];
2930
private userId: string;
3031

3132
public constructor({
3233
analyticsApi,
3334
apiKey,
3435
gitService,
35-
repoPath,
36+
repoPaths,
3637
userId,
3738
}: Constructor) {
3839
this.analyticsApi = analyticsApi;
3940
this.apiKey = apiKey;
4041
this.gitService = gitService;
41-
this.repoPath = repoPath;
42+
this.repoPaths = repoPaths;
4243
this.userId = userId;
4344
}
4445

45-
private async collectStatsByRepository(): Promise<
46-
ActivityLogCreateItemRequestDto[]
47-
> {
46+
private async collectStatsByRepository(
47+
repoPath: string,
48+
): Promise<ActivityLogCreateItemRequestDto[]> {
4849
const stats: ActivityLogCreateItemRequestDto[] = [];
4950
const shortLogResult = await executeCommand(
50-
this.gitService.getShortLogCommand(this.repoPath, "midnight"),
51+
this.gitService.getShortLogCommand(repoPath, "midnight"),
5152
);
5253

5354
const commitItems: CommitStatistics[] = [];
@@ -77,15 +78,21 @@ class AnalyticsService {
7778
return stats;
7879
}
7980

80-
private async fetchRepository(): Promise<void> {
81-
await executeCommand(this.gitService.getFetchCommand(this.repoPath));
82-
logger.info(`Fetched latest updates for repo at path: ${this.repoPath}`);
81+
private async fetchRepository(repoPath: string): Promise<void> {
82+
await executeCommand(this.gitService.getFetchCommand(repoPath));
83+
logger.info(`Fetched latest updates for repo at path: ${repoPath}`);
8384
}
8485

8586
public async collectAndSendStats(): Promise<void> {
8687
try {
87-
await this.fetchRepository();
88-
const stats = await this.collectStatsByRepository();
88+
const statsAll = [];
89+
90+
for (const repoPath of this.repoPaths) {
91+
await this.fetchRepository(repoPath);
92+
statsAll.push(...(await this.collectStatsByRepository(repoPath)));
93+
}
94+
95+
const stats = mergeStats(statsAll);
8996

9097
if (
9198
stats[FIRST_ARRAY_INDEX] &&
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { mergeStats } from "./merge-stats/merge-stats.helper.js";
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
const mergeArrayItems = <T>(
2+
items: T[],
3+
compareFunction: (item1: T, item2: T) => boolean,
4+
mergeFunction: (mergedItem: T, item: T) => void,
5+
): T[] => {
6+
const mergedItems: T[] = [];
7+
8+
for (const item of items) {
9+
const mergedItem = mergedItems.find((mergedItem) =>
10+
compareFunction(mergedItem, item),
11+
);
12+
13+
if (mergedItem) {
14+
mergeFunction(mergedItem, item);
15+
} else {
16+
mergedItems.push(item);
17+
}
18+
}
19+
20+
return mergedItems;
21+
};
22+
23+
export { mergeArrayItems };
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { type ActivityLogCreateItemRequestDto } from "../../types/types.js";
2+
import { mergeArrayItems } from "../merge-array-items/merge-array-items.helper.js";
3+
4+
const mergeStatsItems = (
5+
items: ActivityLogCreateItemRequestDto["items"],
6+
): ActivityLogCreateItemRequestDto["items"] =>
7+
mergeArrayItems(
8+
items,
9+
(item1, item2) =>
10+
item1.authorEmail === item2.authorEmail &&
11+
item1.authorName === item2.authorName,
12+
(mergedItem, item) => (mergedItem.commitsNumber += item.commitsNumber),
13+
);
14+
15+
export { mergeStatsItems };
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { type ActivityLogCreateItemRequestDto } from "../../types/types.js";
2+
import { mergeArrayItems } from "../merge-array-items/merge-array-items.helper.js";
3+
import { mergeStatsItems } from "../merge-stats-items/merge-stats-items.helper.js";
4+
5+
const mergeStats = (
6+
statsAll: ActivityLogCreateItemRequestDto[],
7+
): ActivityLogCreateItemRequestDto[] =>
8+
mergeArrayItems(
9+
statsAll,
10+
(item1, item2) => item1.date === item2.date,
11+
(mergedItem, item) =>
12+
(mergedItem.items = mergeStatsItems([
13+
...mergedItem.items,
14+
...item.items,
15+
])),
16+
);
17+
18+
export { mergeStats };

0 commit comments

Comments
 (0)