From 32c4b92f3752075ddf0ac1b67ee5bcee00519ca7 Mon Sep 17 00:00:00 2001
From: Joel von der Weid <joel.von-der-weid@hesge.ch>
Date: Tue, 23 Apr 2024 16:01:41 +0200
Subject: [PATCH] Check sonar languages

---
 .../subcommands/AssignmentCreateCommand.ts    | 43 ++++++++++++-------
 NodeApp/src/managers/DojoBackendManager.ts    | 10 +++--
 2 files changed, 35 insertions(+), 18 deletions(-)

diff --git a/NodeApp/src/commander/assignment/subcommands/AssignmentCreateCommand.ts b/NodeApp/src/commander/assignment/subcommands/AssignmentCreateCommand.ts
index 90b588e..5e89eed 100644
--- a/NodeApp/src/commander/assignment/subcommands/AssignmentCreateCommand.ts
+++ b/NodeApp/src/commander/assignment/subcommands/AssignmentCreateCommand.ts
@@ -8,6 +8,7 @@ import Toolbox            from '../../../shared/helpers/Toolbox.js';
 import * as Gitlab        from '@gitbeaker/rest';
 import TextStyle          from '../../../types/TextStyle.js';
 import Config             from '../../../config/Config';
+import SharedSonarManager from '../../../shared/managers/SharedSonarManager';
 
 
 type CommandOptions = { name: string, language: string, template?: string, members_id?: Array<number>, members_username?: Array<string>, clone?: string | boolean, sonar?: boolean }
@@ -23,14 +24,14 @@ class AssignmentCreateCommand extends CommanderCommand {
 
     protected defineCommand() {
         this.command
-        .description('create a new repository for an assignment')
-        .requiredOption('-n, --name <name>', 'name of the assignment')
-        .requiredOption('-l, --language <string>', 'main programming language of the assignment')
-        .option('-i, --members_id <ids...>', 'list of gitlab members ids (teaching staff) to add to the repository')
-        .option('-u, --members_username <usernames...>', 'list of gitlab members username (teaching staff) to add to the repository')
-        .option('-t, --template <string>', 'id or url of the template (http/s and ssh urls are possible)')
-        .option('-c, --clone [string]', 'automatically clone the repository (SSH required) in the specified directory (this will create a subdirectory with the assignment name)')
-        .action(this.commandAction.bind(this));
+            .description('create a new repository for an assignment')
+            .requiredOption('-n, --name <name>', 'name of the assignment')
+            .requiredOption('-l, --language <string>', 'main programming language of the assignment')
+            .option('-i, --members_id <ids...>', 'list of gitlab members ids (teaching staff) to add to the repository')
+            .option('-u, --members_username <usernames...>', 'list of gitlab members username (teaching staff) to add to the repository')
+            .option('-t, --template <string>', 'id or url of the template (http/s and ssh urls are possible)')
+            .option('-c, --clone [string]', 'automatically clone the repository (SSH required) in the specified directory (this will create a subdirectory with the assignment name)')
+            .action(this.commandAction.bind(this));
 
         if ( SharedConfig.sonar.enabled ) {
             this.command.requiredOption('-s, --sonar', 'add sonar to the code checking process for exercises derived from the assignment');
@@ -47,13 +48,15 @@ class AssignmentCreateCommand extends CommanderCommand {
             throw new Error();
         }
 
-        const assignmentGetSonarSpinner: ora.Ora = ora('Checking server sonar status').start();
-        this.sonar = (SharedConfig.sonar.enabled ? options.sonar ?? false : false);
-        if ( this.sonar && !(await DojoBackendManager.isSonarEnabled()) ) {
-            assignmentGetSonarSpinner.fail(`Sonar is currently not supported by the server. Disable sonar integration or try again later.`);
-            return;
+        if ( options.sonar ) {
+            const assignmentGetSonarSpinner: ora.Ora = ora('Checking server sonar status').start();
+            this.sonar = (SharedConfig.sonar.enabled ? options.sonar ?? false : false);
+            if ( this.sonar && !(await DojoBackendManager.isSonarEnabled()) ) {
+                assignmentGetSonarSpinner.fail(`Sonar is currently not supported by the server. Disable sonar integration or try again later.`);
+                throw new Error();
+            }
+            assignmentGetSonarSpinner.succeed(`Sonar is supported by the server`);
         }
-        assignmentGetSonarSpinner.succeed(`Sonar is supported by the server`);
 
         const assignmentGetSpinner: ora.Ora = ora('Checking assignment name availability').start();
         if ( await DojoBackendManager.getAssignment(options.name) ) {
@@ -62,6 +65,7 @@ class AssignmentCreateCommand extends CommanderCommand {
         }
         assignmentGetSpinner.succeed(`Assignment name "${ options.name }" is available`);
 
+        // Dojo languages
         const languagesSpinner: ora.Ora = ora('Checking language support').start();
         const languages = await DojoBackendManager.getLanguages();
         if ( !languages.includes(options.language) ) {
@@ -70,10 +74,19 @@ class AssignmentCreateCommand extends CommanderCommand {
             for ( const l of languages ) {
                 console.log(`  - ${ l }`);
             }
-            return;
+            throw new Error();
         }
         languagesSpinner.succeed(`Language "${ options.language }" is supported`);
 
+        // SonarQube languages
+        if ( this.sonar ) {
+            const sonarLang = await DojoBackendManager.getSonarLanguages();
+            if ( !sonarLang.includes(SharedSonarManager.mapLanguage(options.language)) ) {
+                languagesSpinner.fail(`Language "${ options.language }" is not supported with Sonar. Choose a supported language or disable sonar`);
+                throw new Error();
+            }
+        }
+
         if ( options.template ) {
             this.templateIdOrNamespace = options.template;
 
diff --git a/NodeApp/src/managers/DojoBackendManager.ts b/NodeApp/src/managers/DojoBackendManager.ts
index 7fa3f0d..c2c4b66 100644
--- a/NodeApp/src/managers/DojoBackendManager.ts
+++ b/NodeApp/src/managers/DojoBackendManager.ts
@@ -381,10 +381,14 @@ class DojoBackendManager {
         return response.data.data.sonarEnabled;
     }
 
-    public async getLanguages(): Promise<Array<string>> {
-        const response = await axios.get<DojoBackendResponse<Array<string>>>(DojoBackendHelper.getApiUrl(ApiRoute.LANGUAGES));
+    public async getSonarLanguages(): Promise<Array<string>> {
+        const sonar = await axios.get<DojoBackendResponse<{ languages: string[] }>>(DojoBackendHelper.getApiUrl(ApiRoute.SONAR));
+        return sonar.data.data.languages;
+    }
 
-        return response.data.data;
+    public async getLanguages(): Promise<Array<string>> {
+        const resp = await axios.get<DojoBackendResponse<Array<string>>>(DojoBackendHelper.getApiUrl(ApiRoute.LANGUAGES));
+        return resp.data.data;
     }
 
     public async createTag(name: string, type: string, verbose: boolean = true): Promise<Tag | undefined> {
-- 
GitLab