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

Rename enonce and exercice to assignment and exercise

parent 8872f91f
No related branches found
No related tags found
No related merge requests found
......@@ -10,7 +10,7 @@ class ClientsSharedConfig {
projectName: string
};
public readonly exerciceResultsFolderMaxSizeInBytes: number;
public readonly exerciseResultsFolderMaxSizeInBytes: number;
public readonly filenames: {
results: string;
......@@ -32,10 +32,10 @@ class ClientsSharedConfig {
projectName: process.env.DOCKER_COMPOSE_PROJECT_NAME || ''
};
this.exerciceResultsFolderMaxSizeInBytes = Number(process.env.EXERCICE_RESULTS_FOLDER_MAX_SIZE_IN_BYTES || 0);
this.exerciseResultsFolderMaxSizeInBytes = Number(process.env.EXERCISE_RESULTS_FOLDER_MAX_SIZE_IN_BYTES || 0);
this.filenames = {
results: process.env.EXERCICE_RESULTS_FILENAME || ''
results: process.env.EXERCISE_RESULTS_FILENAME || ''
};
}
}
......
import ExerciceResultsFile from '../../../shared/types/Dojo/ExerciceResultsFile';
import ExerciseResultsFile from '../../../shared/types/Dojo/ExerciseResultsFile';
import chalk from 'chalk';
import boxen from 'boxen';
import Icon from '../../types/Icon';
class ClientsSharedExerciceHelper {
displayExecutionResults(exerciceResults: ExerciceResultsFile, containerExitCode: number, Style: { INFO: chalk.Chalk, SUCCESS: chalk.Chalk, FAILURE: chalk.Chalk }, additionalText: string = '') {
const finalLogGlobalResult = `${ Style.INFO('Global result') } : ${ exerciceResults.success ? Style.SUCCESS(`${ Icon.SUCCESS } Success`) : Style.FAILURE(`${ Icon.FAILURE } Failure`) }`;
class ClientsSharedExerciseHelper {
displayExecutionResults(exerciseResults: ExerciseResultsFile, containerExitCode: number, Style: { INFO: chalk.Chalk, SUCCESS: chalk.Chalk, FAILURE: chalk.Chalk }, additionalText: string = '') {
const finalLogGlobalResult = `${ Style.INFO('Global result') } : ${ exerciseResults.success ? Style.SUCCESS(`${ Icon.SUCCESS } Success`) : Style.FAILURE(`${ Icon.FAILURE } Failure`) }`;
const finalLogExecutionExitCode = `${ Style.INFO('Execution exit code') } : ${ (containerExitCode == 0 ? Style.SUCCESS : Style.FAILURE)(containerExitCode) }`;
const finalLogResultNumbers = exerciceResults.successfulTests || exerciceResults.failedTests ? `\n\n${ Style.SUCCESS('Tests passed') } : ${ exerciceResults.successfulTests ?? '--' }\n${ Style.FAILURE('Tests failed') } : ${ exerciceResults.failedTests ?? '--' }` : '';
const finalLogResultNumbers = exerciseResults.successfulTests || exerciseResults.failedTests ? `\n\n${ Style.SUCCESS('Tests passed') } : ${ exerciseResults.successfulTests ?? '--' }\n${ Style.FAILURE('Tests failed') } : ${ exerciseResults.failedTests ?? '--' }` : '';
const finalLogSuccessResultDetails = (exerciceResults.successfulTestsList ?? []).map(testName => `- ${ Icon.SUCCESS } ${ testName }`).join('\n');
const finalLogFailedResultDetails = (exerciceResults.failedTestsList ?? []).map(testName => `- ${ Icon.FAILURE } ${ testName }`).join('\n');
const finalLogResultDetails = exerciceResults.successfulTestsList || exerciceResults.failedTestsList ? `\n\n${ Style.INFO('Tests') } :${ finalLogSuccessResultDetails != '' ? '\n' + finalLogSuccessResultDetails : '' }${ finalLogFailedResultDetails != '' ? '\n' + finalLogFailedResultDetails : '' }` : '';
const finalLogSuccessResultDetails = (exerciseResults.successfulTestsList ?? []).map(testName => `- ${ Icon.SUCCESS } ${ testName }`).join('\n');
const finalLogFailedResultDetails = (exerciseResults.failedTestsList ?? []).map(testName => `- ${ Icon.FAILURE } ${ testName }`).join('\n');
const finalLogResultDetails = exerciseResults.successfulTestsList || exerciseResults.failedTestsList ? `\n\n${ Style.INFO('Tests') } :${ finalLogSuccessResultDetails != '' ? '\n' + finalLogSuccessResultDetails : '' }${ finalLogFailedResultDetails != '' ? '\n' + finalLogFailedResultDetails : '' }` : '';
console.log(boxen(`${ finalLogGlobalResult }\n\n${ finalLogExecutionExitCode }${ finalLogResultNumbers }${ finalLogResultDetails }${ additionalText }`, {
title : 'Results',
......@@ -29,4 +29,4 @@ class ClientsSharedExerciceHelper {
}
export default new ClientsSharedExerciceHelper();
\ No newline at end of file
export default new ClientsSharedExerciseHelper();
\ No newline at end of file
import EnonceFile from '../../../shared/types/Dojo/EnonceFile';
import AssignmentFile from '../../../shared/types/Dojo/AssignmentFile';
import { TypedEmitter } from 'tiny-typed-emitter';
import ExerciceRunningEvents from '../../types/Dojo/ExerciceRunningEvents';
import ExerciseRunningEvents from '../../types/Dojo/ExerciseRunningEvents';
import { spawn } from 'child_process';
import ExerciceCheckerError from '../../../shared/types/Dojo/ExerciceCheckerError';
import ExerciseCheckerError from '../../../shared/types/Dojo/ExerciseCheckerError';
class ExerciceDockerCompose {
readonly events: TypedEmitter<ExerciceRunningEvents> = new TypedEmitter<ExerciceRunningEvents>();
class ExerciseDockerCompose {
readonly events: TypedEmitter<ExerciseRunningEvents> = new TypedEmitter<ExerciseRunningEvents>();
public displayableLogs: string = '';
public allLogs: string = '';
......@@ -15,7 +15,7 @@ class ExerciceDockerCompose {
public success: boolean = false;
public exitCode: number = -1;
constructor(private projectName: string, private enonceFile: EnonceFile, private executionFolder: string, private composeFileOverride: Array<string> = []) {
constructor(private projectName: string, private assignmentFile: AssignmentFile, private executionFolder: string, private composeFileOverride: Array<string> = []) {
this.events.on('logs', (log: string, _error: boolean, displayable: boolean) => {
this.allLogs += log;
this.displayableLogs += displayable ? log : '';
......@@ -43,7 +43,7 @@ class ExerciceDockerCompose {
this.events.emit('logs', '####################################################### Docker Compose & Main Container Logs #######################################################\n', false, false);
const dockerCompose = spawn(`${ dockerComposeCommand } run --build --rm ${ this.enonceFile.result.container }`, {
const dockerCompose = spawn(`${ dockerComposeCommand } run --build --rm ${ this.assignmentFile.result.container }`, {
cwd : this.executionFolder,
shell: true,
env : {
......@@ -66,7 +66,7 @@ class ExerciceDockerCompose {
});
} catch ( error ) {
this.events.emit('endStep', 'COMPOSE_RUN', `Error while running the docker compose file`, true);
this.events.emit('finished', false, ExerciceCheckerError.DOCKER_COMPOSE_RUN_ERROR);
this.events.emit('finished', false, ExerciseCheckerError.DOCKER_COMPOSE_RUN_ERROR);
return;
}
this.events.emit('endStep', 'COMPOSE_RUN', `Docker Compose file run successfully`, false);
......@@ -100,7 +100,7 @@ class ExerciceDockerCompose {
});
} catch ( error ) {
this.events.emit('endStep', 'COMPOSE_LOGS', `Error while getting the linked services logs`, true);
this.events.emit('finished', false, ExerciceCheckerError.DOCKER_COMPOSE_LOGS_ERROR);
this.events.emit('finished', false, ExerciseCheckerError.DOCKER_COMPOSE_LOGS_ERROR);
return;
}
this.events.emit('endStep', 'COMPOSE_LOGS', `Linked services logs acquired`, false);
......@@ -135,7 +135,7 @@ class ExerciceDockerCompose {
});
} catch ( error ) {
this.events.emit('endStep', 'COMPOSE_DOWN', `Error stop and remove containers`, true);
this.events.emit('finished', false, ExerciceCheckerError.DOCKER_COMPOSE_DOWN_ERROR);
this.events.emit('finished', false, ExerciseCheckerError.DOCKER_COMPOSE_DOWN_ERROR);
return;
}
this.events.emit('endStep', 'COMPOSE_DOWN', `Containers stopped and removed`, false);
......@@ -148,4 +148,4 @@ class ExerciceDockerCompose {
}
export default ExerciceDockerCompose;
\ No newline at end of file
export default ExerciseDockerCompose;
\ No newline at end of file
import { TypedEmitter } from 'tiny-typed-emitter';
import ExerciceRunningEvents from '../../types/Dojo/ExerciceRunningEvents';
import ExerciceCheckerError from '../../../shared/types/Dojo/ExerciceCheckerError';
import ExerciseRunningEvents from '../../types/Dojo/ExerciseRunningEvents';
import ExerciseCheckerError from '../../../shared/types/Dojo/ExerciseCheckerError';
import path from 'node:path';
import SharedExerciceHelper from '../../../shared/helpers/Dojo/SharedExerciceHelper';
import SharedExerciseHelper from '../../../shared/helpers/Dojo/SharedExerciseHelper';
import ClientsSharedConfig from '../../config/ClientsSharedConfig';
import Toolbox from '../../../shared/helpers/Toolbox';
import * as fs from 'fs-extra';
import ExerciceResultsFile from '../../../shared/types/Dojo/ExerciceResultsFile';
import ExerciseResultsFile from '../../../shared/types/Dojo/ExerciseResultsFile';
class ExerciceResultsValidation {
readonly events: TypedEmitter<ExerciceRunningEvents> = new TypedEmitter<ExerciceRunningEvents>();
class ExerciseResultsValidation {
readonly events: TypedEmitter<ExerciseRunningEvents> = new TypedEmitter<ExerciseRunningEvents>();
public exerciceResults: ExerciceResultsFile | undefined = undefined;
public exerciseResults: ExerciseResultsFile | undefined = undefined;
constructor(private folderResultsDojo: string, private folderResultsExercice: string) { }
constructor(private folderResultsDojo: string, private folderResultsExercise: string) { }
run() {
(async () => {
......@@ -24,12 +24,12 @@ class ExerciceResultsValidation {
// Results file existence
{
this.events.emit('step', 'CHECK_RESULTS_FILE_EXIST', 'Checking if results file exists');
const resultsFileOriginPath = path.join(this.folderResultsExercice, ClientsSharedConfig.filenames.results);
const resultsFileOriginPath = path.join(this.folderResultsExercise, ClientsSharedConfig.filenames.results);
resultsFilePath = path.join(this.folderResultsDojo, ClientsSharedConfig.filenames.results);
if ( !fs.existsSync(resultsFileOriginPath) ) {
this.events.emit('endStep', 'CHECK_RESULTS_FILE_EXIST', `Results file not found`, true);
this.events.emit('finished', false, ExerciceCheckerError.EXERCICE_RESULTS_FILE_NOT_FOUND);
this.events.emit('finished', false, ExerciseCheckerError.EXERCISE_RESULTS_FILE_NOT_FOUND);
return;
}
this.events.emit('endStep', 'CHECK_RESULTS_FILE_EXIST', 'Results file found', false);
......@@ -41,13 +41,13 @@ class ExerciceResultsValidation {
// Results file schema validation
{
this.events.emit('step', 'VALIDATE_RESULTS_FILE', 'Validating results file schema');
const validationResults = SharedExerciceHelper.validateResultFile(resultsFilePath);
const validationResults = SharedExerciseHelper.validateResultFile(resultsFilePath);
if ( !validationResults.isValid ) {
this.events.emit('endStep', 'VALIDATE_RESULTS_FILE', `Results file is not valid. Here are the errors :\n${ JSON.stringify(validationResults.errors) }`, true);
this.events.emit('finished', false, ExerciceCheckerError.EXERCICE_RESULTS_FILE_SCHEMA_NOT_VALID);
this.events.emit('finished', false, ExerciseCheckerError.EXERCISE_RESULTS_FILE_SCHEMA_NOT_VALID);
return;
}
this.exerciceResults = validationResults.results;
this.exerciseResults = validationResults.results;
this.events.emit('endStep', 'VALIDATE_RESULTS_FILE', 'Results file is valid', false);
}
......@@ -56,10 +56,10 @@ class ExerciceResultsValidation {
// ATTENTION: This test is at the end because even if it fail the local execution will continue and we need the other test above to be done
{
this.events.emit('step', 'CHECK_SIZE', 'Validating results folder size');
const resultsFolderSize = await Toolbox.fs.getTotalSize(this.folderResultsExercice);
if ( resultsFolderSize > ClientsSharedConfig.exerciceResultsFolderMaxSizeInBytes ) {
this.events.emit('endStep', 'CHECK_SIZE', `Results folder size is too big (bigger than ${ ClientsSharedConfig.exerciceResultsFolderMaxSizeInBytes / 1000000 } MB)`, true);
this.events.emit('finished', false, ExerciceCheckerError.EXERCICE_RESULTS_FOLDER_TOO_BIG);
const resultsFolderSize = await Toolbox.fs.getTotalSize(this.folderResultsExercise);
if ( resultsFolderSize > ClientsSharedConfig.exerciseResultsFolderMaxSizeInBytes ) {
this.events.emit('endStep', 'CHECK_SIZE', `Results folder size is too big (bigger than ${ ClientsSharedConfig.exerciseResultsFolderMaxSizeInBytes / 1000000 } MB)`, true);
this.events.emit('finished', false, ExerciseCheckerError.EXERCISE_RESULTS_FOLDER_TOO_BIG);
return;
}
this.events.emit('endStep', 'CHECK_SIZE', 'Results folder size is in bounds', false);
......@@ -71,4 +71,4 @@ class ExerciceResultsValidation {
}
export default ExerciceResultsValidation;
\ No newline at end of file
export default ExerciseResultsValidation;
\ No newline at end of file
import GitlabRepository from '../../shared/types/Gitlab/GitlabRepository';
import User from './User';
import Exercice from './Exercice';
import Exercise from './Exercise';
interface Enonce {
interface Assignment {
name: string;
gitlabId: number;
gitlabLink: string;
......@@ -13,8 +13,8 @@ interface Enonce {
published: boolean;
staff: Array<User>;
exercices: Array<Exercice>;
exercises: Array<Exercise>;
}
export default Enonce;
\ No newline at end of file
export default Assignment;
\ No newline at end of file
import EnonceFile from '../../shared/types/Dojo/EnonceFile';
import Enonce from './Enonce';
import GitlabFile from '../../shared/types/Gitlab/GitlabFile';
interface ExerciceEnonce {
enonce: Enonce;
enonceFile: EnonceFile;
immutable: Array<GitlabFile>;
}
export default ExerciceEnonce;
\ No newline at end of file
import GitlabRepository from '../../shared/types/Gitlab/GitlabRepository';
interface Exercice {
interface Exercise {
id: string;
enonceName: string;
assignmentName: string;
name: string;
gitlabId: number;
gitlabLink: string;
......@@ -13,4 +13,4 @@ interface Exercice {
}
export default Exercice;
\ No newline at end of file
export default Exercise;
\ No newline at end of file
import AssignmentFile from '../../shared/types/Dojo/AssignmentFile';
import Assignment from './Assignment';
import GitlabFile from '../../shared/types/Gitlab/GitlabFile';
interface ExerciseAssignment {
assignment: Assignment;
assignmentFile: AssignmentFile;
immutable: Array<GitlabFile>;
}
export default ExerciseAssignment;
\ No newline at end of file
......@@ -2,13 +2,13 @@ enum ApiRoute {
LOGIN = '/login',
TEST_SESSION = '/test_session',
GITLAB_CHECK_TEMPLATE_ACCESS = '/gitlab/project/{{id}}/checkTemplateAccess',
ENONCE_GET = '/enonces/{{nameOrUrl}}',
ENONCE_CREATE = '/enonces',
ENONCE_PUBLISH = '/enonces/{{nameOrUrl}}/publish',
ENONCE_UNPUBLISH = '/enonces/{{nameOrUrl}}/unpublish',
EXERCICE_CREATE = '/enonces/{{nameOrUrl}}/exercices',
EXERCICE_ENONCE = '/exercices/{{id}}/enonce',
EXERCICE_RESULTS = '/exercices/{{id}}/results'
ASSIGNMENT_GET = '/assignments/{{nameOrUrl}}',
ASSIGNMENT_CREATE = '/assignments',
ASSIGNMENT_PUBLISH = '/assignments/{{nameOrUrl}}/publish',
ASSIGNMENT_UNPUBLISH = '/assignments/{{nameOrUrl}}/unpublish',
EXERCISE_CREATE = '/assignments/{{nameOrUrl}}/exercises',
EXERCISE_ASSIGNMENT = '/exercises/{{id}}/assignment',
EXERCISE_RESULTS = '/exercises/{{id}}/results'
}
......
interface ExerciceRunningEvents {
interface ExerciseRunningEvents {
step: (name: string, message: string) => void;
endStep: (stepName: string, message: string, error: boolean) => void;
logs: (log: string, error: boolean, displayable: boolean) => void;
......@@ -6,4 +6,4 @@ interface ExerciceRunningEvents {
}
export default ExerciceRunningEvents;
\ No newline at end of file
export default ExerciseRunningEvents;
\ 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