Skip to content
Snippets Groups Projects
Commit dd1de840 authored by michael.minelli's avatar michael.minelli
Browse files

Add icon and styles provided by types (remove code duplicates)

parent 5a37b5ae
Branches
Tags
No related merge requests found
Pipeline #25734 passed
...@@ -4,6 +4,8 @@ const path = require('node:path'); ...@@ -4,6 +4,8 @@ const path = require('node:path');
require('dotenv').config({ path: path.join(__dirname, '../.env') }); require('dotenv').config({ path: path.join(__dirname, '../.env') });
require('./shared/helpers/TypeScriptExtensions'); // ATTENTION : This line MUST be the second of this file require('./shared/helpers/TypeScriptExtensions'); // ATTENTION : This line MUST be the second of this file
import Styles from './types/Styles';
import Icon from './types/Icon';
import boxen from 'boxen'; import boxen from 'boxen';
import RecursiveFilesStats from './shared/helpers/recursiveFilesStats/RecursiveFilesStats'; import RecursiveFilesStats from './shared/helpers/recursiveFilesStats/RecursiveFilesStats';
import Toolbox from './shared/helpers/Toolbox'; import Toolbox from './shared/helpers/Toolbox';
...@@ -12,7 +14,6 @@ import ExerciceCheckerError from './types/ExerciceCheckerError'; ...@@ -12,7 +14,6 @@ import ExerciceCheckerError from './types/ExerciceCheckerError';
import { exec, spawn } from 'child_process'; import { exec, spawn } from 'child_process';
import util from 'util'; import util from 'util';
import fs from 'fs-extra'; import fs from 'fs-extra';
import chalk from 'chalk';
import HttpManager from './managers/HttpManager'; import HttpManager from './managers/HttpManager';
import DojoBackendManager from './managers/DojoBackendManager'; import DojoBackendManager from './managers/DojoBackendManager';
import Config from './config/Config'; import Config from './config/Config';
...@@ -24,22 +25,17 @@ import ArchiveHelper from './shared/helpers/ArchiveHelper'; ...@@ -24,22 +25,17 @@ import ArchiveHelper from './shared/helpers/ArchiveHelper';
HttpManager.registerAxiosInterceptor(); HttpManager.registerAxiosInterceptor();
const chalkInfo: chalk.Chalk = chalk.blue; console.log(Styles.APP_NAME(Config.appName));
const chalkError: chalk.Chalk = chalk.red;
const chalkSuccess: chalk.Chalk = chalk.green;
const chalkFailure: chalk.Chalk = chalk.red;
console.log(chalk.bgBlue.black.bold('DOJO EXERCICE CHECKER'));
/* /*
Step 1 & 2: //////////////////////////////////////////////////////////////////////////////////////////////////////////// Step 1 & 2:
- Read the dojo enonce file from the enonce repository - Read the dojo enonce file from the enonce repository
- Download immutables files (maybe throw or show an error if the files have been modified ?) - Download immutables files (maybe throw or show an error if the files have been modified ?)
*/ */
console.log(chalkInfo(`- Checking the exercice's enonce and his immutable files`)); console.log(Styles.INFO(`${ Icon.INFO } Checking the exercice's enonce and his immutable files`));
const exerciceEnonce = await DojoBackendManager.getExerciceEnonce(); const exerciceEnonce = await DojoBackendManager.getExerciceEnonce();
if ( !exerciceEnonce ) { if ( !exerciceEnonce ) {
console.error(chalkError(`X Error while getting the exercice's enonce`)); console.error(Styles.ERROR(`${ Icon.ERROR } Error while getting the exercice's enonce`));
process.exit(ExerciceCheckerError.EXERCICE_ENONCE_GET_ERROR); process.exit(ExerciceCheckerError.EXERCICE_ENONCE_GET_ERROR);
} }
...@@ -51,12 +47,12 @@ import ArchiveHelper from './shared/helpers/ArchiveHelper'; ...@@ -51,12 +47,12 @@ import ArchiveHelper from './shared/helpers/ArchiveHelper';
/* /*
Step 3 & 4 & 5: //////////////////////////////////////////////////////////////////////////////////////////////////////////// Step 3 & 4 & 5:
- Get override of docker-compose file (for override the volume by a bind mount to the results folder shared between dind and the host) - Get override of docker-compose file (for override the volume by a bind mount to the results folder shared between dind and the host)
- Run docker-compose file - Run docker-compose file
- Get logs from linked services - Get logs from linked services
*/ */
console.log(chalkInfo('- Run docker compose file')); console.log(Styles.INFO(`${ Icon.INFO } Run docker compose file`));
const dockerComposeOverride = fs.readFileSync(path.join(__dirname, '../assets/docker-compose-override.yml'), 'utf8').replace('{{VOLUME_NAME}}', exerciceEnonce.enonceFile.result.volume).replace('{{MOUNT_PATH}}', Config.folders.resultsExercice); const dockerComposeOverride = fs.readFileSync(path.join(__dirname, '../assets/docker-compose-override.yml'), 'utf8').replace('{{VOLUME_NAME}}', exerciceEnonce.enonceFile.result.volume).replace('{{MOUNT_PATH}}', Config.folders.resultsExercice);
fs.writeFileSync(`${ Config.folders.project }/docker-compose-override.yml`, dockerComposeOverride); fs.writeFileSync(`${ Config.folders.project }/docker-compose-override.yml`, dockerComposeOverride);
...@@ -92,34 +88,34 @@ import ArchiveHelper from './shared/helpers/ArchiveHelper'; ...@@ -92,34 +88,34 @@ import ArchiveHelper from './shared/helpers/ArchiveHelper';
}); });
const containerExitCode = containerExitStatus[0]; const containerExitCode = containerExitStatus[0];
if ( containerExitCode === ExerciceCheckerError.DOCKER_COMPOSE_UP_ERROR ) { if ( containerExitCode === ExerciceCheckerError.DOCKER_COMPOSE_UP_ERROR ) {
console.error(chalkError(`X Error while running the docker compose file`)); console.error(Styles.ERROR(`${ Icon.ERROR } Error while running the docker compose file`));
process.exit(containerExitCode); process.exit(containerExitCode);
} }
fs.writeFileSync(`${ Config.folders.resultsDojo }/dockerComposeLogs.txt`, containerExitStatus[1]); fs.writeFileSync(`${ Config.folders.resultsDojo }/dockerComposeLogs.txt`, containerExitStatus[1]);
console.log(chalkInfo('- Acquire logs of linked services')); console.log(Styles.INFO(`${ Icon.INFO } Acquire logs of linked services`));
try { try {
await execAsync(`${ changeDirectoryCommand };${ dockerComposeCommand } logs --timestamps >> ${ Config.folders.resultsDojo }/dockerComposeLogs.txt`); await execAsync(`${ changeDirectoryCommand };${ dockerComposeCommand } logs --timestamps >> ${ Config.folders.resultsDojo }/dockerComposeLogs.txt`);
} catch ( error ) { } catch ( error ) {
console.error(chalkError(`X Error while getting the linked services logs`)); console.error(Styles.ERROR(`${ Icon.ERROR } Error while getting the linked services logs`));
process.exit(ExerciceCheckerError.DOCKER_COMPOSE_LOGS_ERROR); process.exit(ExerciceCheckerError.DOCKER_COMPOSE_LOGS_ERROR);
} }
// Step 6: Check content requirements and content size //////////////////////////////////////////////////////////////////////////////////////////////////////////// Step 6: Check content requirements and content size
console.log(chalkInfo('- Validating results folder size')); console.log(Styles.INFO(`${ Icon.INFO } Validating results folder size`));
const resultsFolderSize = await Toolbox.fs.getTotalSize(Config.folders.resultsExercice); const resultsFolderSize = await Toolbox.fs.getTotalSize(Config.folders.resultsExercice);
if ( resultsFolderSize > Config.resultsFolderMaxSizeInBytes ) { if ( resultsFolderSize > Config.resultsFolderMaxSizeInBytes ) {
console.error(chalkError(`X Results folder size is too big (bigger than ${ Config.resultsFolderMaxSizeInBytes / 1000000 })`)); console.error(Styles.ERROR(`${ Icon.ERROR } Results folder size is too big (bigger than ${ Config.resultsFolderMaxSizeInBytes / 1000000 })`));
process.exit(ExerciceCheckerError.EXERCICE_RESULTS_FOLDER_TOO_BIG); process.exit(ExerciceCheckerError.EXERCICE_RESULTS_FOLDER_TOO_BIG);
} }
console.log(chalkInfo('- Checking results file')); console.log(Styles.INFO(`${ Icon.INFO } Checking results file`));
const resultsFileOriginPath = path.join(Config.folders.resultsExercice, Config.filenames.results); const resultsFileOriginPath = path.join(Config.folders.resultsExercice, Config.filenames.results);
const resultsFilePath = path.join(Config.folders.resultsDojo, Config.filenames.results); const resultsFilePath = path.join(Config.folders.resultsDojo, Config.filenames.results);
if ( !fs.existsSync(resultsFileOriginPath) ) { if ( !fs.existsSync(resultsFileOriginPath) ) {
console.error(chalkError(`X Results file not found.`)); console.error(Styles.ERROR(`${ Icon.ERROR } Results file not found.`));
process.exit(ExerciceCheckerError.EXERCICE_RESULTS_FILE_NOT_FOUND); process.exit(ExerciceCheckerError.EXERCICE_RESULTS_FILE_NOT_FOUND);
} }
...@@ -128,15 +124,15 @@ import ArchiveHelper from './shared/helpers/ArchiveHelper'; ...@@ -128,15 +124,15 @@ import ArchiveHelper from './shared/helpers/ArchiveHelper';
const validationResults = ExerciceHelper.validateResultFile(resultsFilePath); const validationResults = ExerciceHelper.validateResultFile(resultsFilePath);
if ( !validationResults.isValid ) { if ( !validationResults.isValid ) {
console.error(chalkError(`X Results file is not valid. Here are the errors :`)); console.error(Styles.ERROR(`${ Icon.ERROR } Results file is not valid. Here are the errors :`));
console.error(chalkError(JSON.stringify(validationResults.errors))); console.error(Styles.ERROR(JSON.stringify(validationResults.errors)));
process.exit(ExerciceCheckerError.EXERCICE_RESULTS_FILE_SCHEMA_NOT_VALID); process.exit(ExerciceCheckerError.EXERCICE_RESULTS_FILE_SCHEMA_NOT_VALID);
} }
// Step 7: Upload and show the results //////////////////////////////////////////////////////////////////////////////////////////////////////////// Step 7: Upload and show the results
try { try {
console.log(chalkInfo(`- Uploading results to the dojo server`)); console.log(Styles.INFO(`${ Icon.INFO } Uploading results to the dojo server`));
const commit: any = {}; const commit: any = {};
Toolbox.getKeysWithPrefix(process.env, 'CI_COMMIT_').forEach(key => { Toolbox.getKeysWithPrefix(process.env, 'CI_COMMIT_').forEach(key => {
commit[Toolbox.snakeToCamel(key.replace('CI_COMMIT_', ''))] = process.env[key]; commit[Toolbox.snakeToCamel(key.replace('CI_COMMIT_', ''))] = process.env[key];
...@@ -149,22 +145,22 @@ import ArchiveHelper from './shared/helpers/ArchiveHelper'; ...@@ -149,22 +145,22 @@ import ArchiveHelper from './shared/helpers/ArchiveHelper';
await DojoBackendManager.sendResults(containerExitCode, commit, validationResults.results!, files, await ArchiveHelper.getBase64(Config.folders.resultsVolume)); await DojoBackendManager.sendResults(containerExitCode, commit, validationResults.results!, files, await ArchiveHelper.getBase64(Config.folders.resultsVolume));
} catch ( error ) { } catch ( error ) {
console.error(chalkError(`X Error while uploading the results`)); console.error(Styles.ERROR(`${ Icon.ERROR } Error while uploading the results`));
console.error(JSON.stringify(error)); console.error(JSON.stringify(error));
process.exit(ExerciceCheckerError.UPLOAD); process.exit(ExerciceCheckerError.UPLOAD);
} }
// Step 8: Exit with container exit code //////////////////////////////////////////////////////////////////////////////////////////////////////////// Step 8: Exit with container exit code
const finalLogGlobalResult = `${ chalkInfo('Global result') } : ${ validationResults.results!.success ? chalkSuccess(' Success') : chalkFailure(' Failure') }`; const finalLogGlobalResult = `${ Styles.INFO('Global result') } : ${ validationResults.results!.success ? Styles.SUCCESS(`${ Icon.SUCCESS } Success`) : Styles.FAILURE(`${ Icon.FAILURE } Failure`) }`;
const finalLogExecutionExitCode = `${ chalkInfo('Execution exit code') } : ${ (containerExitCode == 0 ? chalkSuccess : chalkError)(containerExitCode) }`; const finalLogExecutionExitCode = `${ Styles.INFO('Execution exit code') } : ${ (containerExitCode == 0 ? Styles.SUCCESS : Styles.ERROR)(containerExitCode) }`;
const finalLogResultNumbers = validationResults.results!.successfulTests || validationResults.results!.failedTests ? `\n\n${ chalkSuccess('Tests passed') } : ${ validationResults.results!.successfulTests ?? '--' }\n${ chalkError('Tests failed') } : ${ validationResults.results!.failedTests ?? '--' }` : ''; const finalLogResultNumbers = validationResults.results!.successfulTests || validationResults.results!.failedTests ? `\n\n${ Styles.SUCCESS('Tests passed') } : ${ validationResults.results!.successfulTests ?? '--' }\n${ Styles.ERROR('Tests failed') } : ${ validationResults.results!.failedTests ?? '--' }` : '';
const finalLogSuccessResultDetails = (validationResults.results!.successfulTestsList ?? []).map(testName => `- ${ testName }`).join('\n'); const finalLogSuccessResultDetails = (validationResults.results!.successfulTestsList ?? []).map(testName => `- ${ Icon.SUCCESS } ${ testName }`).join('\n');
const finalLogFailedResultDetails = (validationResults.results!.failedTestsList ?? []).map(testName => `- ${ testName }`).join('\n'); const finalLogFailedResultDetails = (validationResults.results!.failedTestsList ?? []).map(testName => `- ${ Icon.FAILURE } ${ testName }`).join('\n');
const finalLogResultDetails = validationResults.results!.successfulTestsList || validationResults.results!.failedTestsList ? `\n\n${ chalkInfo('Tests') } :${ finalLogSuccessResultDetails != '' ? '\n' + finalLogSuccessResultDetails : '' }${ finalLogFailedResultDetails != '' ? '\n' + finalLogFailedResultDetails : '' }` : ''; const finalLogResultDetails = validationResults.results!.successfulTestsList || validationResults.results!.failedTestsList ? `\n\n${ Styles.INFO('Tests') } :${ finalLogSuccessResultDetails != '' ? '\n' + finalLogSuccessResultDetails : '' }${ finalLogFailedResultDetails != '' ? '\n' + finalLogFailedResultDetails : '' }` : '';
console.log(boxen(`${ finalLogGlobalResult }\n\n${ finalLogExecutionExitCode }${ finalLogResultNumbers }${ finalLogResultDetails }`, { console.log(boxen(`${ finalLogGlobalResult }\n\n${ finalLogExecutionExitCode }${ finalLogResultNumbers }${ finalLogResultDetails }`, {
title : 'Results', title : 'Results',
...@@ -178,4 +174,3 @@ import ArchiveHelper from './shared/helpers/ArchiveHelper'; ...@@ -178,4 +174,3 @@ import ArchiveHelper from './shared/helpers/ArchiveHelper';
process.exit(containerExitCode); process.exit(containerExitCode);
})(); })();
\ No newline at end of file
...@@ -3,6 +3,8 @@ import path from 'path'; ...@@ -3,6 +3,8 @@ import path from 'path';
class Config { class Config {
public readonly appName: string;
public readonly resultsFolderMaxSizeInBytes: number; public readonly resultsFolderMaxSizeInBytes: number;
public readonly folders: { public readonly folders: {
...@@ -22,6 +24,8 @@ class Config { ...@@ -22,6 +24,8 @@ class Config {
}; };
constructor() { constructor() {
this.appName = process.env.APP_NAME || '';
this.resultsFolderMaxSizeInBytes = Number(process.env.RESULTS_FOLDER_MAX_SIZE_IN_BYTES || 0); this.resultsFolderMaxSizeInBytes = Number(process.env.RESULTS_FOLDER_MAX_SIZE_IN_BYTES || 0);
this.folders = { this.folders = {
......
enum Icon {
INFO = 'ℹ️',
ERROR = '⛔️',
SUCCESS = '',
FAILURE = ''
}
export default Icon;
\ No newline at end of file
import chalk from 'chalk';
class Styles {
public readonly APP_NAME = chalk.bgBlue.black.bold;
public readonly INFO = chalk.blue;
public readonly ERROR = chalk.red;
public readonly SUCCESS = chalk.green;
public readonly FAILURE = chalk.red;
}
export default new Styles();
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment