Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 39 additions & 1 deletion v6y-apps/bfb-main-analyzer/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,17 @@ import Cors from 'cors';
import Express, { Express as ExpressApp } from 'express';
import ExpressStatusMonitor from 'express-status-monitor';

import { AppLogger, CorsOptions } from '@v6y/core-logic';
import {
AppLogger,
ApplicationProvider,
AuditProvider,
CorsOptions,
DataBaseManager,
DependencyProvider,
} from '@v6y/core-logic';

import ServerConfig from './config/ServerConfig.ts';
import ApplicationManager from './managers/ApplicationManager.ts';

/**
* Creates and configures the Express application
Expand Down Expand Up @@ -48,6 +56,36 @@ export function createApp(): ExpressApp {

// *********************************************** Handle Endpoints ***********************************************

// Trigger analysis for a single application
app.post('/{*any}trigger', async (request, response) => {
const applicationId = parseInt(request.body?.applicationId, 10);
AppLogger.info(`[trigger] applicationId: ${applicationId}`);

if (!applicationId) {
response.status(400).json({ success: false, message: 'applicationId is required' });
return;
}

// Respond immediately; analysis runs in background
response.json({ success: true, applicationId });

try {
await DataBaseManager.connect();
await AuditProvider.deleteAuditsByAppId(applicationId);
await DependencyProvider.deleteDependenciesByAppId(applicationId);

const application = await ApplicationProvider.getApplicationDetailsInfoByParams({
_id: applicationId,
});

if (application) {
await ApplicationManager.buildApplicationReports(application);
}
} catch (error) {
AppLogger.error(`[trigger] error: ${String(error)}`);
}
});

// default response (unknown routes)
app.get('/{*any}', (request, response) => {
AppLogger.debug(`[*] KO: la route demandé ${request.url} n'existe pas`);
Expand Down
25 changes: 24 additions & 1 deletion v6y-apps/bfb-main-analyzer/src/managers/ApplicationManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,28 @@ const buildApplicationReports = async (application: ApplicationType) => {
return false;
}

const userBranchesToAudit = application.repo.branchesToAudit;

let branchesToAudit;
if (userBranchesToAudit?.length) {
const matched = repositoryBranches.filter((branch) =>
userBranchesToAudit.includes(branch?.name),
);
branchesToAudit = matched.length ? matched : [repositoryBranches[0]];
} else {
const defaultBranchName =
repositoryDetails.default_branch || repositoryBranches[0]?.name;
const defaultBranch = repositoryBranches.find(
(branch) => branch?.name === defaultBranchName,
);
branchesToAudit = defaultBranch ? [defaultBranch] : [repositoryBranches[0]];
}

AppLogger.info(
'[ApplicationManager - buildApplicationReports] auditing branches: ',
branchesToAudit.map((b) => b?.name).join(', '),
);

await ApplicationProvider.editApplication({
...application,
repo: {
Expand All @@ -59,7 +81,7 @@ const buildApplicationReports = async (application: ApplicationType) => {

await buildStaticReports({
application,
branches: repositoryBranches,
branches: branchesToAudit,
});

AppLogger.info('[ApplicationManager - buildApplicationDetails] end of static analysis');
Expand Down Expand Up @@ -109,6 +131,7 @@ const buildApplicationList = async () => {
};

const ApplicationManager = {
buildApplicationReports,
buildApplicationList,
};

Expand Down
7 changes: 0 additions & 7 deletions v6y-apps/bfb-main-analyzer/src/workers/DataUpdateScheduler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,6 @@ const startUpdateWorkers = () => {
* Database updates are performed by default at startup, then every midnight.
*/
const start = () => {
// Check every second to make sure the main thread is still responsive
setInterval(() => {
AppLogger.info(
'******************** Checking that the main thread is not blocked **************************',
);
}, 1000);

// Initial update
AppLogger.info('******************** Starting initial update **************************');
setTimeout(() => {
Expand Down
44 changes: 44 additions & 0 deletions v6y-apps/bff/src/resolvers/application/ApplicationMutations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const createOrEditApplication = async (
gitOrganization,
gitUrl,
gitWebUrl,
gitBranchesToAudit,
productionLink,
additionalProductionLinks,
dataDogApiKey,
Expand All @@ -46,6 +47,9 @@ const createOrEditApplication = async (
AppLogger.info(
`[AppMutations - createOrEditApplication] gitOrganization : ${gitOrganization}`,
);
AppLogger.info(
`[AppMutations - createOrEditApplication] gitBranchesToAudit : ${gitBranchesToAudit}`,
);
AppLogger.info(
`[AppMutations - createOrEditApplication] dataDogApiKey : ${dataDogApiKey ? '"********"}`,' : 'null'}`,
);
Expand Down Expand Up @@ -83,6 +87,7 @@ const createOrEditApplication = async (
gitOrganization,
gitUrl,
gitWebUrl,
gitBranchesToAudit,
productionLink,
contactMail,
sonarqubeLink,
Expand Down Expand Up @@ -111,6 +116,7 @@ const createOrEditApplication = async (
gitOrganization,
gitUrl,
gitWebUrl,
gitBranchesToAudit,
productionLink,
contactMail,
sonarqubeLink,
Expand Down Expand Up @@ -166,9 +172,47 @@ const deleteApplication = async (_: unknown, params: { input: SearchQueryType })
}
};

/**
* Trigger analysis for a single application on demand.
*/
const triggerApplicationAnalysis = async (_: unknown, params: { applicationId: number }) => {
try {
const { applicationId } = params || {};
AppLogger.info(
`[AppMutations - triggerApplicationAnalysis] applicationId: ${applicationId}`,
);

if (!applicationId) {
return { success: false, message: 'applicationId is required' };
}

const mainAnalyzerPort = process.env.V6Y_MAIN_API_PORT || '4002';
const mainAnalyzerPath = process.env.V6Y_MAIN_API_PATH || '/api/main';
const triggerUrl = `http://localhost:${mainAnalyzerPort}${mainAnalyzerPath}trigger`;

AppLogger.info(`[AppMutations - triggerApplicationAnalysis] calling: ${triggerUrl}`);

const response = await fetch(triggerUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ applicationId }),
});

if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}

return { success: true, applicationId };
} catch (error) {
AppLogger.info(`[AppMutations - triggerApplicationAnalysis] error: ${error}`);
return { success: false, message: String(error) };
}
};

const ApplicationMutations = {
createOrEditApplication,
deleteApplication,
triggerApplicationAnalysis,
};

export default ApplicationMutations;
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ const ApplicationCreateOrEditInput = `

""" Application git repository url """
gitUrl: String!


""" Branches to audit (leave empty to auto-detect from repository) """
gitBranchesToAudit: [String]

""" Application production url """
productionLink: String!

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
const ApplicationMutationsType = `
type ApplicationAnalysisTriggerOutput {
success: Boolean!
applicationId: Int
message: String
}

type Mutation {
createOrEditApplication(applicationInput: ApplicationCreateOrEditInput!): ApplicationType
deleteApplication(input: ApplicationDeleteInput!): ApplicationDeleteOutput
triggerApplicationAnalysis(applicationId: Int!): ApplicationAnalysisTriggerOutput
}
`;

Expand Down
3 changes: 3 additions & 0 deletions v6y-apps/bff/src/types/commons/RepositoryType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ const RepositoryType = `
""" Repository Organization """
organization: String
""" Branches to audit (user-selected) """
branchesToAudit: [String]
""" Repository all related branches """
allBranches: [String]
Expand Down
3 changes: 3 additions & 0 deletions v6y-apps/front-bo/public/favicon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions v6y-apps/front-bo/public/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,10 @@
"placeholder": "Enter your application Git URL",
"error": "Application Git URL is a mandatory field!"
},
"app-git-branches-to-audit": {
"label": "Branches to audit (type a branch name and press Enter; leave empty to auto-detect)",
"placeholder": "e.g. main, develop, release/1.0"
},
"app-links": {
"label": "Application links"
},
Expand Down
10 changes: 10 additions & 0 deletions v6y-apps/front-bo/public/locales/fr/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@
"create": "Create",
"edit": "Edit",
"show": "Show"

},
"buttons": {
"create": "Create",
Expand Down Expand Up @@ -196,6 +197,14 @@
"placeholder": "Enter your application Git URL",
"error": "Application Git URL is a mandatory field!"
},
"app-git-default-branch": {
"label": "Branche par défaut à auditer (laisser vide pour détecter automatiquement depuis le dépôt)",
"placeholder": "ex: main, master, develop"
},
"app-git-branches-to-audit": {
"label": "Branches à auditer (saisir un nom de branche et appuyer sur Entrée ; laisser vide pour détecter automatiquement)",
"placeholder": "ex: main, develop, release/1.0"
},
"app-links": {
"label": "Application links"
},
Expand Down Expand Up @@ -459,3 +468,4 @@
"title": "Authentication"
}
}

6 changes: 5 additions & 1 deletion v6y-apps/front-bo/src/__tests__/VitalityFormConfig-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,11 @@ describe('VitalityFormConfig - Form Items', () => {
it('should generate application git repository form items correctly', () => {
const result = applicationGitRepositoryFormItems(mockTranslate);

expect(result).toHaveLength(3);
expect(result).toHaveLength(4);
expect(result[0].id).toBe('app-git-organization');
expect(result[1].id).toBe('app-git-web-url');
expect(result[2].id).toBe('app-git-url');
expect(result[3].id).toBe('app-git-branches-to-audit');
});

it('should generate required application links form items correctly', () => {
Expand Down Expand Up @@ -109,6 +110,7 @@ describe('VitalityFormConfig - Form Items', () => {
'app-git-organization': 'TestOrg',
'app-git-web-url': 'https://testrepo.com',
'app-git-url': 'https://git.testrepo.com',
'app-git-branches-to-audit': undefined,
'app-production-link-1': 'https://testapp.com',
'app-production-link-2': 'https://testapp2.com',
'app-production-link-3': 'https://testapp3.com',
Expand Down Expand Up @@ -156,6 +158,7 @@ describe('VitalityFormConfig - Form Items', () => {
gitOrganization: 'TestOrg',
gitWebUrl: 'https://testrepo.com',
gitUrl: 'https://git.testrepo.com',
gitBranchesToAudit: undefined,
productionLink: 'https://testapp.com',
additionalProductionLinks: ['https://testapp2.com', 'https://testapp3.com'],
sonarqubeLink: 'https://sonarqube.example.com/dashboard?id=testapp',
Expand Down Expand Up @@ -208,6 +211,7 @@ describe('VitalityFormConfig - Form Items', () => {
'app-git-organization': undefined,
'app-git-web-url': undefined,
'app-git-url': 'https://git.partial.com',
'app-git-branches-to-audit': undefined,
'app-production-link-1': undefined,
'app-production-link-2': undefined,
'app-production-link-3': undefined,
Expand Down
2 changes: 1 addition & 1 deletion v6y-apps/front-bo/src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const metadata = {
description:
'Vitality (v6y) is a web-based application developed by Ekino, designed to maintain and optimize the health and performance of codebases and applications.',
icons: {
icon: '/favicon.ico',
icon: '/favicon.svg',
},
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,11 @@ const VitalityFormFieldSet = ({ groupTitle, items, selectOptions }: VitalityForm
disabled={item.disabled || false}
//defaultValue={item.defaultValue}
placeholder={item.placeholder}
options={selectOptions}
options={
((item as Record<string, unknown>).options as
| SelectOptionType[]
| undefined) || selectOptions
}
mode={item.mode || undefined}
/>
)}
Expand Down
21 changes: 18 additions & 3 deletions v6y-apps/front-bo/src/commons/config/VitalityFormConfig.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,10 @@ export const applicationInfosFormItems = (translate: TranslateType) => {
];
};

export const applicationGitRepositoryFormItems = (translate: TranslateType) => [
export const applicationGitRepositoryFormItems = (
translate: TranslateType,
allBranches?: string[],
) => [
{
id: 'app-git-organization',
name: 'app-git-organization',
Expand Down Expand Up @@ -99,6 +102,16 @@ export const applicationGitRepositoryFormItems = (translate: TranslateType) => [
},
],
},
{
id: 'app-git-branches-to-audit',
name: 'app-git-branches-to-audit',
type: 'select',
mode: 'tags',
label: translate('v6y-applications.fields.app-git-branches-to-audit.label'),
placeholder: translate('v6y-applications.fields.app-git-branches-to-audit.placeholder'),
options: allBranches?.map((branch) => ({ label: branch, value: branch })),
rules: [],
},
];

export const applicationRequiredLinksFormItems = (translate: TranslateType) => [
Expand Down Expand Up @@ -212,7 +225,7 @@ export const applicationDataDogConfigurationFormItems = (translate: TranslateTyp
},
];

export const applicationCreateEditItems = (translate: TranslateType) => {
export const applicationCreateEditItems = (translate: TranslateType, allBranches?: string[]) => {
return [
<VitalityFormFieldSet
key={translate('v6y-applications.fields.app-infos-group')}
Expand All @@ -222,7 +235,7 @@ export const applicationCreateEditItems = (translate: TranslateType) => {
<VitalityFormFieldSet
key={translate('v6y-applications.fields.app-git-repository-group')}
groupTitle={translate('v6y-applications.fields.app-git-repository-group')}
items={applicationGitRepositoryFormItems(translate)}
items={applicationGitRepositoryFormItems(translate, allBranches)}
/>,
<VitalityFormFieldSet
key={translate('v6y-applications.fields.app-required-links-group')}
Expand Down Expand Up @@ -250,6 +263,7 @@ export const applicationCreateOrEditFormInAdapter = (params: ApplicationType) =>
'app-git-organization': params?.['repo']?.organization,
'app-git-web-url': params?.['repo']?.webUrl,
'app-git-url': params?.['repo']?.gitUrl,
'app-git-branches-to-audit': params?.['repo']?.branchesToAudit,
'app-contact-email': params?.['contactMail'],
'app-production-link-1': params?.['links']?.find?.(
(item) => item.label === 'Application production url',
Expand Down Expand Up @@ -289,6 +303,7 @@ export const applicationCreateOrEditFormOutputAdapter = (data: unknown): Variabl
gitOrganization: params?.['app-git-organization'],
gitWebUrl: params?.['app-git-web-url'],
gitUrl: params?.['app-git-url'],
gitBranchesToAudit: params?.['app-git-branches-to-audit'] as string[],
name: params?.['app-name'],
contactMail: params?.['app-contact-email'],
productionLink: params?.['app-production-link-1'],
Expand Down
Loading
Loading