From 41b3d88544eb46171acf36b4fd61332c33db5bf8 Mon Sep 17 00:00:00 2001 From: Joel von der Weid <joel.von-der-weid@hesge.ch> Date: Mon, 17 Jun 2024 15:02:25 +0200 Subject: [PATCH] Create SonarAnalyzer --- helpers/Dojo/AssignmentValidator.ts | 24 +++++-------- helpers/Dojo/SonarAnalyzer.ts | 54 +++++++++++++++++++++++++++++ types/Dojo/ApiRoute.ts | 1 + 3 files changed, 63 insertions(+), 16 deletions(-) create mode 100644 helpers/Dojo/SonarAnalyzer.ts diff --git a/helpers/Dojo/AssignmentValidator.ts b/helpers/Dojo/AssignmentValidator.ts index 4a16475..c06a4ea 100644 --- a/helpers/Dojo/AssignmentValidator.ts +++ b/helpers/Dojo/AssignmentValidator.ts @@ -15,6 +15,7 @@ import Assignment, { Language } from '../../models/Assignment'; import ClientsSharedAssignmentHelper from './ClientsSharedAssignmentHelper'; import { spawnSync } from 'node:child_process'; import SharedConfig from '../../../shared/config/SharedConfig'; +import SonarAnalyzer from './SonarAnalyzer'; const execAsync = util.promisify(exec); @@ -281,35 +282,27 @@ class AssignmentValidator { { this.newStep('ASSIGNMENT_SONAR', 'Please wait while we are running Sonar analysis on the assignment...'); - let additionalParams: string[] = []; - this.newSubStep('SONAR_BUILD', 'Build files'); - const buildProcess = spawnSync('docker', ['build', '--tag', 'dojo-sonar-scanner', '/sonar']); - if ( buildProcess.status !== 0 ) { + const buildSuccess = SonarAnalyzer.buildDocker() + if ( !buildSuccess ) { this.emitError(`Build sonar image failed`, 'Sonar analysis failure', AssignmentCheckerError.SONAR_ANALYSIS_FAILED); - console.log(buildProcess.stdout.toString()) - console.log(buildProcess.stderr.toString()) return; } - if ([Language.c, Language.cpp, Language.objc].includes(assignment.language) && assignmentFile.buildLine != undefined) { - const process = spawnSync('docker run -v ./:/usr/src dojo-sonar-scanner /usr/local/bin/build-wrapper-linux-x86-64 --out-dir bw-output ' + assignmentFile.buildLine, [], { shell: true }) - if ( process.status !== 0 ) { + if (SonarAnalyzer.mustRunBuild(assignment.language, assignmentFile.buildLine)) { + const buildSuccess = SonarAnalyzer.runBuildStep(assignmentFile.buildLine!); + if ( !buildSuccess ) { this.emitError(`Failed to build files using buildLine`, 'Sonar analysis failure', AssignmentCheckerError.SONAR_ANALYSIS_FAILED); - console.log(process.stdout.toString()) - console.log(process.stderr.toString()) return; } - additionalParams = ['-Dsonar.cfamily.build-wrapper-output=/usr/src/bw-output']; } this.endSubStep('Sonar files build success', false); this.newSubStep('SONAR_RUN', 'Run sonar analysis'); - - const process = spawnSync('docker', ['run', '-v', './:/usr/src', 'dojo-sonar-scanner' , 'sonar-scanner', '-Dsonar.qualitygate.wait=true', '-Dsonar.projectKey=' + assignment.sonarKey, '-Dsonar.sources=.', '-Dsonar.host.url=' + SharedConfig.sonar.url, '-Dsonar.login=' + SharedConfig.sonar.token, ...additionalParams]) - if ( process.status !== 0 ) { + const runSuccess = SonarAnalyzer.runAnalysis(assignment.sonarKey, assignment.language, assignmentFile.buildLine); + if ( runSuccess ) { this.emitError(`Sonar gate failed`, 'Sonar analysis failure', AssignmentCheckerError.SONAR_ANALYSIS_FAILED); return; } @@ -326,7 +319,6 @@ class AssignmentValidator { { this.newStep('ASSIGNMENT_RUN', 'Please wait while we are running the assignment...'); - const exerciseDockerCompose = new ExerciseDockerCompose(ClientsSharedConfig.dockerCompose.projectName, assignmentFile, this.folderAssignment); try { diff --git a/helpers/Dojo/SonarAnalyzer.ts b/helpers/Dojo/SonarAnalyzer.ts new file mode 100644 index 0000000..d763d32 --- /dev/null +++ b/helpers/Dojo/SonarAnalyzer.ts @@ -0,0 +1,54 @@ +import { spawnSync } from 'node:child_process'; +import { Language } from '../../models/Assignment'; +import SharedConfig from '../../../shared/config/SharedConfig'; + +const IMAGE_NAME = 'dojo-sonar-scanner' +const OUT_DIR = 'bw-output'; + +class SonarAnalyzer { + buildDocker = () => { + const buildProcess = spawnSync('docker', ['build', '--tag', IMAGE_NAME, '/sonar']); + if ( buildProcess.status !== 0 ) { + console.log(buildProcess.stdout.toString()) + console.log(buildProcess.stderr.toString()) + return false; + } + return true; + } + + mustRunBuild = (language: Language, buildLine: string | undefined) => { + return [Language.c, Language.cpp, Language.objc].includes(language) && buildLine != undefined; + } + + runBuildStep = (buildLine: string) => { + const process = spawnSync(`docker run -v ./:/usr/src ${IMAGE_NAME} /usr/local/bin/build-wrapper-linux-x86-64 --out-dir ${OUT_DIR} ` + buildLine, [], { shell: true }) + if ( process.status !== 0 ) { + console.log(process.stdout.toString()) + console.log(process.stderr.toString()) + return false; + } + return true; + } + + runAnalysis = (sonarKey: string, language: Language, buildLine: string | undefined) => { + let addParam: string[] = []; + if (this.mustRunBuild(language, buildLine)) { + addParam = [ `-Dsonar.cfamily.build-wrapper-output=/usr/src/${OUT_DIR}`]; + } + + const process = spawnSync( + 'docker', + ['run', '-v', './:/usr/src', + IMAGE_NAME , 'sonar-scanner', + '-Dsonar.qualitygate.wait=true', + '-Dsonar.projectKey=' + sonarKey, + '-Dsonar.sources=.', + '-Dsonar.host.url=' + SharedConfig.sonar.url, + '-Dsonar.login=' + SharedConfig.sonar.token, + ...addParam]) + + return process.status === 0; + } +} + +export default new SonarAnalyzer(); \ No newline at end of file diff --git a/types/Dojo/ApiRoute.ts b/types/Dojo/ApiRoute.ts index 0569734..6b10960 100644 --- a/types/Dojo/ApiRoute.ts +++ b/types/Dojo/ApiRoute.ts @@ -13,6 +13,7 @@ enum ApiRoute { ASSIGNMENT_CORRECTION_LINK = '/assignments/{{assignmentNameOrUrl}}/corrections', ASSIGNMENT_CORRECTION_UPDATE = '/assignments/{{assignmentNameOrUrl}}/corrections/{{exerciseIdOrUrl}}', EXERCISE_CREATE = '/assignments/{{nameOrUrl}}/exercises', + EXERCISE_GET = '/exercises/{{id}}', EXERCISE_ASSIGNMENT = '/exercises/{{id}}/assignment', EXERCISE_RESULTS = '/exercises/{{id}}/results' } -- GitLab