From a7e9082823aad891c6aed34174ee11385918a8fb Mon Sep 17 00:00:00 2001 From: Artem Zagorodnyuk Date: Thu, 3 Oct 2024 11:57:41 +0300 Subject: [PATCH] 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 --- .../setup-analytics-modal.tsx | 7 ++-- .../analytics-cli/base-analytics-cli.ts | 9 ++--- .../analytics-cli/init-analytics-cli.ts | 10 +++--- .../modules/analytics/analytics.service.ts | 33 +++++++++++-------- .../modules/analytics/libs/helpers/helpers.ts | 1 + .../merge-array-items.helper.ts | 23 +++++++++++++ .../merge-stats-items.helper.ts | 15 +++++++++ .../helpers/merge-stats/merge-stats.helper.ts | 18 ++++++++++ 8 files changed, 90 insertions(+), 26 deletions(-) create mode 100644 scripts/analytics/src/modules/analytics/libs/helpers/helpers.ts create mode 100644 scripts/analytics/src/modules/analytics/libs/helpers/merge-array-items/merge-array-items.helper.ts create mode 100644 scripts/analytics/src/modules/analytics/libs/helpers/merge-stats-items/merge-stats-items.helper.ts create mode 100644 scripts/analytics/src/modules/analytics/libs/helpers/merge-stats/merge-stats.helper.ts diff --git a/apps/frontend/src/pages/project/libs/components/setup-analytics-modal/setup-analytics-modal.tsx b/apps/frontend/src/pages/project/libs/components/setup-analytics-modal/setup-analytics-modal.tsx index b992b5e45..8eed105da 100644 --- a/apps/frontend/src/pages/project/libs/components/setup-analytics-modal/setup-analytics-modal.tsx +++ b/apps/frontend/src/pages/project/libs/components/setup-analytics-modal/setup-analytics-modal.tsx @@ -57,7 +57,7 @@ const SetupAnalyticsModal = ({ const apiKey = project.apiKey as string; const userId = String(authenticatedUser.id); - return `npx @git-fit/analytics@latest track ${apiKey} ${userId} `; + return `npx @git-fit/analytics@latest track ${apiKey} ${userId} ...`; }, [hasProjectApiKey, hasAuthenticatedUser, project, authenticatedUser]); const { control, errors, handleSubmit, handleValueSet } = useAppForm({ @@ -233,8 +233,9 @@ const SetupAnalyticsModal = ({ Prepare the script.

- Copy the command below and replace <project-path> - placeholder with your local repository's path: + Copy the command below and replace <project-path-1>, + <project-path-2>, ... placeholder with your local + repositories paths:

") + .command("track ") .description("Start the background job for collecting statistics") - .action(async (apiKey: string, userId: string, repoPath: string) => { - if (!apiKey || !userId || !repoPath) { + .action(async (apiKey: string, userId: string, repoPaths: string[]) => { + if (!apiKey || !userId || repoPaths.length === EMPTY_LENGTH) { this.logger.error("Not all command arguments are provided."); return; @@ -80,7 +81,7 @@ class BaseAnalyticsCli { pm2.start( { - args: [apiKey, userId, repoPath], + args: [apiKey, userId, ...repoPaths], autorestart: false, error: `${project.projectName}-err.log`, name: project.projectName, diff --git a/scripts/analytics/src/libs/modules/analytics-cli/init-analytics-cli.ts b/scripts/analytics/src/libs/modules/analytics-cli/init-analytics-cli.ts index a35003963..f685f3452 100644 --- a/scripts/analytics/src/libs/modules/analytics-cli/init-analytics-cli.ts +++ b/scripts/analytics/src/libs/modules/analytics-cli/init-analytics-cli.ts @@ -10,17 +10,15 @@ import { CRON_SCHEDULE, } from "./libs/constants/constants.js"; -const [apiKey, userId, repoPath] = process.argv.slice(ARGUMENT_START_INDEX) as [ - string, - string, - string, -]; +const [apiKey, userId, ...repoPaths] = process.argv.slice( + ARGUMENT_START_INDEX, +) as [string, string, string]; const analyticsService = new AnalyticsService({ analyticsApi, apiKey, gitService, - repoPath, + repoPaths, userId, }); diff --git a/scripts/analytics/src/modules/analytics/analytics.service.ts b/scripts/analytics/src/modules/analytics/analytics.service.ts index ced41fa1b..9cd3a3429 100644 --- a/scripts/analytics/src/modules/analytics/analytics.service.ts +++ b/scripts/analytics/src/modules/analytics/analytics.service.ts @@ -8,6 +8,7 @@ import { EMPTY_LENGTH, FIRST_ARRAY_INDEX, } from "./libs/constants/constants.js"; +import { mergeStats } from "./libs/helpers/helpers.js"; import { type ActivityLogCreateItemRequestDto, type CommitStatistics, @@ -17,7 +18,7 @@ type Constructor = { analyticsApi: typeof analyticsApi; apiKey: string; gitService: GITService; - repoPath: string; + repoPaths: string[]; userId: string; }; @@ -25,29 +26,29 @@ class AnalyticsService { private analyticsApi: typeof analyticsApi; private apiKey: string; private gitService: GITService; - private repoPath: string; + private repoPaths: string[]; private userId: string; public constructor({ analyticsApi, apiKey, gitService, - repoPath, + repoPaths, userId, }: Constructor) { this.analyticsApi = analyticsApi; this.apiKey = apiKey; this.gitService = gitService; - this.repoPath = repoPath; + this.repoPaths = repoPaths; this.userId = userId; } - private async collectStatsByRepository(): Promise< - ActivityLogCreateItemRequestDto[] - > { + private async collectStatsByRepository( + repoPath: string, + ): Promise { const stats: ActivityLogCreateItemRequestDto[] = []; const shortLogResult = await executeCommand( - this.gitService.getShortLogCommand(this.repoPath, "midnight"), + this.gitService.getShortLogCommand(repoPath, "midnight"), ); const commitItems: CommitStatistics[] = []; @@ -77,15 +78,21 @@ class AnalyticsService { return stats; } - private async fetchRepository(): Promise { - await executeCommand(this.gitService.getFetchCommand(this.repoPath)); - logger.info(`Fetched latest updates for repo at path: ${this.repoPath}`); + private async fetchRepository(repoPath: string): Promise { + await executeCommand(this.gitService.getFetchCommand(repoPath)); + logger.info(`Fetched latest updates for repo at path: ${repoPath}`); } public async collectAndSendStats(): Promise { try { - await this.fetchRepository(); - const stats = await this.collectStatsByRepository(); + const statsAll = []; + + for (const repoPath of this.repoPaths) { + await this.fetchRepository(repoPath); + statsAll.push(...(await this.collectStatsByRepository(repoPath))); + } + + const stats = mergeStats(statsAll); if ( stats[FIRST_ARRAY_INDEX] && diff --git a/scripts/analytics/src/modules/analytics/libs/helpers/helpers.ts b/scripts/analytics/src/modules/analytics/libs/helpers/helpers.ts new file mode 100644 index 000000000..2a0df46d9 --- /dev/null +++ b/scripts/analytics/src/modules/analytics/libs/helpers/helpers.ts @@ -0,0 +1 @@ +export { mergeStats } from "./merge-stats/merge-stats.helper.js"; diff --git a/scripts/analytics/src/modules/analytics/libs/helpers/merge-array-items/merge-array-items.helper.ts b/scripts/analytics/src/modules/analytics/libs/helpers/merge-array-items/merge-array-items.helper.ts new file mode 100644 index 000000000..8c5a46c24 --- /dev/null +++ b/scripts/analytics/src/modules/analytics/libs/helpers/merge-array-items/merge-array-items.helper.ts @@ -0,0 +1,23 @@ +const mergeArrayItems = ( + items: T[], + compareFunction: (item1: T, item2: T) => boolean, + mergeFunction: (mergedItem: T, item: T) => void, +): T[] => { + const mergedItems: T[] = []; + + for (const item of items) { + const mergedItem = mergedItems.find((mergedItem) => + compareFunction(mergedItem, item), + ); + + if (mergedItem) { + mergeFunction(mergedItem, item); + } else { + mergedItems.push(item); + } + } + + return mergedItems; +}; + +export { mergeArrayItems }; diff --git a/scripts/analytics/src/modules/analytics/libs/helpers/merge-stats-items/merge-stats-items.helper.ts b/scripts/analytics/src/modules/analytics/libs/helpers/merge-stats-items/merge-stats-items.helper.ts new file mode 100644 index 000000000..102060588 --- /dev/null +++ b/scripts/analytics/src/modules/analytics/libs/helpers/merge-stats-items/merge-stats-items.helper.ts @@ -0,0 +1,15 @@ +import { type ActivityLogCreateItemRequestDto } from "../../types/types.js"; +import { mergeArrayItems } from "../merge-array-items/merge-array-items.helper.js"; + +const mergeStatsItems = ( + items: ActivityLogCreateItemRequestDto["items"], +): ActivityLogCreateItemRequestDto["items"] => + mergeArrayItems( + items, + (item1, item2) => + item1.authorEmail === item2.authorEmail && + item1.authorName === item2.authorName, + (mergedItem, item) => (mergedItem.commitsNumber += item.commitsNumber), + ); + +export { mergeStatsItems }; diff --git a/scripts/analytics/src/modules/analytics/libs/helpers/merge-stats/merge-stats.helper.ts b/scripts/analytics/src/modules/analytics/libs/helpers/merge-stats/merge-stats.helper.ts new file mode 100644 index 000000000..53121b1e5 --- /dev/null +++ b/scripts/analytics/src/modules/analytics/libs/helpers/merge-stats/merge-stats.helper.ts @@ -0,0 +1,18 @@ +import { type ActivityLogCreateItemRequestDto } from "../../types/types.js"; +import { mergeArrayItems } from "../merge-array-items/merge-array-items.helper.js"; +import { mergeStatsItems } from "../merge-stats-items/merge-stats-items.helper.js"; + +const mergeStats = ( + statsAll: ActivityLogCreateItemRequestDto[], +): ActivityLogCreateItemRequestDto[] => + mergeArrayItems( + statsAll, + (item1, item2) => item1.date === item2.date, + (mergedItem, item) => + (mergedItem.items = mergeStatsItems([ + ...mergedItem.items, + ...item.items, + ])), + ); + +export { mergeStats };