Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • jw_sonar
  • jw_sonar_backup
  • main
  • update-dependencies
  • v5.0.0
  • v6.0.0
  • 2.2.0
  • 3.0.0
  • 3.1.0
  • 3.2.0
  • 3.3.0
  • 3.4.0
  • 3.5.0
  • 4.0.0
  • 4.1.0
  • 4.1.1
  • 4.2.0
  • 5.0.0
  • 6.0.0-dev
19 results

Target

Select target project
  • dojo_project/projects/pipelines/dojoassignmentchecker
1 result
Select Git revision
  • jw_sonar
  • jw_sonar_backup
  • main
  • update-dependencies
  • v5.0.0
  • v6.0.0
  • 2.2.0
  • 3.0.0
  • 3.1.0
  • 3.2.0
  • 3.3.0
  • 3.4.0
  • 3.5.0
  • 4.0.0
  • 4.1.0
  • 4.1.1
  • 4.2.0
  • 5.0.0
  • 6.0.0-dev
19 results
Show changes
Showing
with 362 additions and 106 deletions
{ {
"name" : "dojo_assignment_checker", "name" : "dojo_assignment_checker",
"description" : "App that check an assignment of the Dojo project", "description" : "App that check an assignment of the Dojo project",
"version" : "3.5.0", "version" : "6.0.0",
"license" : "AGPLv3", "license" : "AGPLv3",
"author" : "Michaël Minelli <dojo@minelli.me>", "author" : "Michaël Minelli <dojo@minelli.me>",
"main" : "dist/app.js", "main" : "dist/app.js",
"bin" : { "bin" : {
"dirmanager": "./dist/app.js" "dirmanager": "./dist/app.js"
}, },
"pkg" : { "pkg": {
"scripts": [], "scripts": [],
"assets" : [ "assets": [
"node_modules/axios/dist/node/axios.cjs", "node_modules/axios/dist/node/axios.cjs",
"config.env",
".env", ".env",
"assets/**/*" "assets/**/*"
], ],
...@@ -21,41 +22,44 @@ ...@@ -21,41 +22,44 @@
] ]
}, },
"scripts" : { "scripts" : {
"dotenv:build": "npx dotenv-vault local build", "dotenv:build": "npx dotenvx encrypt",
"lint" : "npx eslint .", "lint" : "npx eslint .",
"genversion" : "npx genversion -s -e src/config/Version.ts", "genversion" : "npx genversion -s -e src/config/Version.ts",
"build" : "npm run genversion; npx tsc", "build" : "npm run genversion; npx tsc",
"start:dev" : "npm run genversion; npm run lint; npx ts-node src/app.ts", "start:dev" : "npm run genversion; npm run lint; tsc --noEmit && npx tsx --no-warnings src/app.ts",
"test" : "echo \"Error: no test specified\" && exit 1" "test" : "echo \"Error: no test specified\" && exit 1"
}, },
"dependencies" : { "dependencies" : {
"axios" : "^1.6.5", "@dotenvx/dotenvx" : "^0.45.0",
"boxen" : "^5.1.2", "@eslint/js" : "^9.21.0",
"chalk" : "^4.1.2", "@gitbeaker/core" : "^42.1.0",
"dotenv" : "^16.3.1", "@gitbeaker/requester-utils": "^42.1.0",
"dotenv-expand" : "^10.0.0", "@gitbeaker/rest" : "^42.1.0",
"fs-extra" : "^11.2.0", "axios" : "^1.7.8",
"http-status-codes" : "^2.3.0", "boxen" : "^5.1.2",
"json5" : "^2.2.3", "chalk" : "^4.1.2",
"ora" : "^5.4.1", "form-data" : "^4.0.2",
"tar-stream" : "^3.1.6", "fs-extra" : "^11.3.0",
"winston" : "^3.11.0", "http-status-codes" : "^2.3.0",
"yaml" : "^2.3.4", "json5" : "^2.2.3",
"zod" : "^3.22.4", "ora" : "^5.4.1",
"zod-validation-error": "^3.0.0" "tar-stream" : "^3.1.7",
"winston" : "^3.17.0",
"winston-transport" : "^4.9.0",
"yaml" : "^2.7.0",
"zod" : "^3.24.2",
"zod-validation-error" : "^3.4.0"
}, },
"devDependencies": { "devDependencies": {
"@types/fs-extra" : "^11.0.4", "@types/fs-extra" : "^11.0.4",
"@types/js-yaml" : "^4.0.9", "@types/js-yaml" : "^4.0.9",
"@types/node" : "^18.19.8", "@types/node" : "^18.19.76",
"@types/tar-stream" : "^3.1.3", "@types/tar-stream" : "^3.1.3",
"@typescript-eslint/eslint-plugin": "^6.19.0", "genversion" : "^3.2.0",
"@typescript-eslint/parser" : "^6.19.0", "pkg" : "^5.8.1",
"dotenv-vault" : "^1.25.0", "tiny-typed-emitter": "^2.1.0",
"genversion" : "^3.2.0", "tsx" : "^4.19.3",
"pkg" : "^5.8.1", "typescript" : "~5.5.4",
"tiny-typed-emitter" : "^2.1.0", "typescript-eslint" : "^7.18.0"
"ts-node" : "^10.9.2",
"typescript" : "^5.3.3"
} }
} }
// Read from the .env file // ATTENTION : This line MUST be the first of this file
// ATTENTION : These lines MUST be the first of this file (except for the path import) import './init.js';
import path = require('node:path'); import ClientsSharedAssignmentHelper from './sharedByClients/helpers/Dojo/ClientsSharedAssignmentHelper.js';
import myEnv = require('dotenv'); import AssignmentValidator from './sharedByClients/helpers/Dojo/AssignmentValidator.js';
import dotenvExpand = require('dotenv-expand'); import Styles from './types/Style.js';
import HttpManager from './managers/HttpManager.js';
import Config from './config/Config.js';
import Icon from './shared/types/Icon.js';
import SharedAssignmentHelper from './shared/helpers/Dojo/SharedAssignmentHelper';
import SharedConfig from './shared/config/SharedConfig';
dotenvExpand.expand(myEnv.config({ (async () => {
path : path.join(__dirname, '../.env'), await Config.init();
DOTENV_KEY: 'dotenv://:key_f1778b6998874f6fd78c716ccef982c5595fa300f174b129eafc88ba7044d69b@dotenv.local/vault/.env.vault?environment=development'
}));
require('./shared/helpers/TypeScriptExtensions'); // ATTENTION : This line MUST be the second of this file
import ClientsSharedAssignmentHelper from './sharedByClients/helpers/Dojo/ClientsSharedAssignmentHelper';
import AssignmentValidator from './sharedByClients/helpers/Dojo/AssignmentValidator';
import Styles from './types/Style';
import HttpManager from './managers/HttpManager';
import Config from './config/Config';
import Icon from './shared/types/Icon';
SharedAssignmentHelper.init(Config.gitlabManager);
(async () => {
HttpManager.registerAxiosInterceptor(); HttpManager.registerAxiosInterceptor();
console.log(Styles.APP_NAME(`${ Config.appName } (version {{VERSION}})`)); console.log(Styles.APP_NAME(`${ Config.appName } (version {{VERSION}})`));
const assignmentValidator = new AssignmentValidator(Config.folders.project); const assignmentValidator = new AssignmentValidator(Config.folders.project, false, SharedConfig.sonar.enabled);
try { try {
await new Promise<void>((resolve, reject) => { await new Promise<void>((resolve, reject) => {
assignmentValidator.events.on('step', (name: string, message: string) => { assignmentValidator.events.on('step', (_name: string, message: string) => {
console.log(Styles.CAT_INFO(`${ Icon.CAT_INFO } ${ message }`)); console.log(Styles.CAT_INFO(`${ Icon.CAT_INFO } ${ message }`));
}); });
assignmentValidator.events.on('subStep', (name: string, message: string) => { assignmentValidator.events.on('subStep', (_name: string, message: string) => {
console.log(Styles.INFO(`\t${ Icon.INFO } ${ message }`)); console.log(Styles.INFO(`\t${ Icon.INFO } ${ message }`));
}); });
assignmentValidator.events.on('endSubStep', (stepName: string, message: string, error: boolean) => { assignmentValidator.events.on('endSubStep', (_stepName: string, message: string, error: boolean) => {
if ( error ) { if ( error ) {
console.error(Styles.ERROR(`\t${ Icon.ERROR } ${ message }`)); console.error(Styles.ERROR(`\t${ Icon.ERROR } ${ message }`));
} }
......
import fs from 'fs-extra'; import fs from 'fs-extra';
import path from 'path'; import path from 'path';
import GitlabManager from '../managers/GitlabManager';
import ClientsSharedConfig from '../sharedByClients/config/ClientsSharedConfig';
class Config { class Config {
public readonly appName: string; public gitlabManager!: GitlabManager;
public readonly folders: { public appName!: string;
public folders!: {
project: string; resultsVolume: string; resultsDojo: string; resultsExercise: string; project: string; resultsVolume: string; resultsDojo: string; resultsExercise: string;
}; };
public readonly dockerhub: { public assignment!: {
name: string; secret: string;
};
public dockerhub!: {
repositories: { repositories: {
assignmentChecker: string assignmentChecker: string
} }
}; };
constructor() { constructor() { }
async init() {
this.appName = process.env.APP_NAME || ''; this.appName = process.env.APP_NAME || '';
const apiUrl = process.env.API_URL ?? '';
await ClientsSharedConfig.init(apiUrl);
const getEnvVar = ClientsSharedConfig.envVarGetter();
this.gitlabManager = new GitlabManager(ClientsSharedConfig.gitlab.URL, ClientsSharedConfig.login.gitlab.client.id, ClientsSharedConfig.login.gitlab.url.redirect, ClientsSharedConfig.login.gitlab.url.token);
this.appName = getEnvVar('APP_NAME', '');
this.folders = { this.folders = {
project : process.env.PROJECT_FOLDER?.convertWithEnvVars() ?? './', project : getEnvVar('PROJECT_FOLDER', './').convertWithEnvVars(),
resultsVolume : process.env.EXERCISE_RESULTS_VOLUME?.convertWithEnvVars() ?? '', resultsVolume : getEnvVar('EXERCISE_RESULTS_VOLUME', '').convertWithEnvVars(),
resultsDojo : path.join(process.env.EXERCISE_RESULTS_VOLUME?.convertWithEnvVars() ?? '', 'Dojo/'), resultsDojo : path.join(getEnvVar('EXERCISE_RESULTS_VOLUME', '').convertWithEnvVars(), 'Dojo/'),
resultsExercise: path.join(process.env.EXERCISE_RESULTS_VOLUME?.convertWithEnvVars() ?? '', 'Exercise/') resultsExercise: path.join(getEnvVar('EXERCISE_RESULTS_VOLUME', '').convertWithEnvVars(), 'Exercise/')
}; };
this.resetResultsVolume(); this.resetResultsVolume();
this.assignment = {
name : process.env.DOJO_ASSIGNMENT_NAME || '',
secret: process.env.DOJO_ASSIGNMENT_SECRET || ''
};
this.dockerhub = { this.dockerhub = {
repositories: { repositories: {
assignmentChecker: process.env.DOCKERHUB_ASSIGNMENT_CHECKER_REPOSITORY || '' assignmentChecker: getEnvVar('DOCKERHUB_ASSIGNMENT_CHECKER_REPOSITORY', '')
} }
}; };
} }
......
import path from 'node:path';
import dotenv from 'dotenv';
import dotenvExpand from 'dotenv-expand';
import './shared/helpers/TypeScriptExtensions.js';
dotenvExpand.expand(dotenv.config({
path : path.join(__dirname, '../.env'),
DOTENV_KEY: 'dotenv://:key_f1778b6998874f6fd78c716ccef982c5595fa300f174b129eafc88ba7044d69b@dotenv.local/vault/.env.vault?environment=development'
}));
dotenvExpand.expand(dotenv.config({ path: path.join(__dirname, '../config.env') }));
\ No newline at end of file
import ClientsSharedConfig from '../sharedByClients/config/ClientsSharedConfig';
import ApiRoute from '../sharedByClients/types/Dojo/ApiRoute';
class DojoBackendManager {
public getApiUrl(route: ApiRoute): string {
return `${ ClientsSharedConfig.apiURL }${ route }`;
}
}
export default new DojoBackendManager();
import SharedGitlabManager from '../shared/managers/SharedGitlabManager.js';
// NOT USED
// File present only for prevent errors from shared submodules
class GitlabManager extends SharedGitlabManager {
constructor(public gitlabUrl: string, clientId?: string, urlRedirect?: string, urlToken?: string) {
super(gitlabUrl, '', clientId, urlRedirect, urlToken);
}
}
export default GitlabManager;
\ No newline at end of file
import axios, { AxiosRequestHeaders } from 'axios'; import axios, { AxiosRequestHeaders } from 'axios';
import FormData from 'form-data'; import FormData from 'form-data';
import ClientsSharedConfig from '../sharedByClients/config/ClientsSharedConfig'; import ClientsSharedConfig from '../sharedByClients/config/ClientsSharedConfig.js';
import Config from '../config/Config'; import Config from '../config/Config.js';
import { version } from '../config/Version'; import { version } from '../config/Version.js';
import boxen from 'boxen'; import boxen from 'boxen';
import DojoStatusCode from '../shared/types/Dojo/DojoStatusCode'; import DojoStatusCode from '../shared/types/Dojo/DojoStatusCode.js';
import DojoBackendResponse from '../shared/types/Dojo/DojoBackendResponse'; import DojoBackendResponse from '../shared/types/Dojo/DojoBackendResponse.js';
import { StatusCodes } from 'http-status-codes'; import { StatusCodes } from 'http-status-codes';
...@@ -29,19 +29,19 @@ class HttpManager { ...@@ -29,19 +29,19 @@ class HttpManager {
} }
private registerRequestInterceptor() { private registerRequestInterceptor() {
axios.interceptors.request.use((config) => { axios.interceptors.request.use(config => {
if ( config.data instanceof FormData ) { if ( config.data instanceof FormData ) {
config.headers = { ...config.headers, ...(config.data as FormData).getHeaders() } as AxiosRequestHeaders; config.headers = { ...config.headers, ...config.data.getHeaders() } as AxiosRequestHeaders;
} }
if ( config.url && (config.url.indexOf(ClientsSharedConfig.apiURL) !== -1) ) { if ( config.url && (config.url.indexOf(ClientsSharedConfig.apiURL) !== -1) ) {
config.headers['Accept-Encoding'] = 'gzip'; config.headers['Accept-Encoding'] = 'gzip';
if ( config.data && Object.keys(config.data).length > 0 ) { if ( config.data && Object.keys(config.data as { [key: string]: unknown }).length > 0 ) {
config.headers['Content-Type'] = 'multipart/form-data'; config.headers['Content-Type'] = 'multipart/form-data';
} }
//config.headers.Authorization = `ExerciseSecret ${ Config.exercise.secret }`; config.headers.assignmentsecret = ClientsSharedConfig.assignment.secret;
config.headers['client'] = 'DojoAssignmentChecker'; config.headers['client'] = 'DojoAssignmentChecker';
config.headers['client-version'] = version; config.headers['client-version'] = version;
...@@ -52,18 +52,16 @@ class HttpManager { ...@@ -52,18 +52,16 @@ class HttpManager {
} }
private registerResponseInterceptor() { private registerResponseInterceptor() {
axios.interceptors.response.use((response) => { axios.interceptors.response.use(response => response, error => {
return response;
}, (error) => {
if ( error.response ) { if ( error.response ) {
if ( error.response.status === StatusCodes.METHOD_NOT_ALLOWED && error.response.data ) { if ( error.response.status === StatusCodes.METHOD_NOT_ALLOWED && error.response.data ) {
const data: DojoBackendResponse<void> = error.response.data; const data: DojoBackendResponse<void> = error.response.data;
switch ( data.code ) { switch ( data.code ) {
case DojoStatusCode.CLIENT_NOT_SUPPORTED: case DojoStatusCode.CLIENT_NOT_SUPPORTED.valueOf():
this.requestError('Client not recognized by the server. Please contact the administrator.'); this.requestError('Client not recognized by the server. Please contact the administrator.');
break; break;
case DojoStatusCode.CLIENT_VERSION_NOT_SUPPORTED: case DojoStatusCode.CLIENT_VERSION_NOT_SUPPORTED.valueOf():
this.requestError(`AssignmentChecker version not supported by the server.\nPlease check that the CI/CD pipeline use the "${ Config.dockerhub.repositories.assignmentChecker }:latest" image.\nIf yes, try again later and if the problem persists, please contact the administrator.`); this.requestError(`AssignmentChecker version not supported by the server.\nPlease check that the CI/CD pipeline use the "${ Config.dockerhub.repositories.assignmentChecker }:latest" image.\nIf yes, try again later and if the problem persists, please contact the administrator.`);
break; break;
default: default:
......
Subproject commit 89f3579ca9009f793742170928d808ab4c35d931 Subproject commit 937081e68f6127b669daca30e57c43e73b9c96c9
Subproject commit 098c6d20f6ed84240c086b979b56afd598fdfea4 Subproject commit eedbe869a561f6e9a3b02fa9374cee425af27946
{ {
"compilerOptions": { "compilerOptions": {
"rootDir" : "src", "rootDir" : "src",
"outDir" : "dist", "outDir" : "dist",
"strict" : true, "strict" : true,
"target" : "ES2022", "target" : "ES2022",
"module" : "commonjs", "module" : "commonjs",
"sourceMap" : true, "sourceMap" : true,
"esModuleInterop" : true, "noImplicitAny" : true,
"moduleResolution": "node", "esModuleInterop": true,
"noImplicitAny" : true "lib" : [
"ES2022",
"DOM"
],
"types" : [
"node"
]
}, },
"exclude" : [ "exclude" : [
"node_modules" "node_modules"
],
"include" : [
"src/**/*.ts",
"eslint.config.mjs"
] ]
} }
\ No newline at end of file
...@@ -18,6 +18,43 @@ ...@@ -18,6 +18,43 @@
--> -->
## 6.0.0 (Upcoming)
### ✨ Feature
- Add SonarQube integration for exercises (thanks to @joel.vonderwe)
### 🔨 Internal / Developers
- Major dependencies update
## 5.0.0 (2024-10-21)
### ✨ Feature
- Add possibility of self-host the solution
## 4.2.0 (2024-07-05)
- No modifications / Keep major and minors versions in sync with all parts of the project
## 4.1.1 (2024-05-28)
### 🐛 Bugfix
- Remove node warning messages
## 4.1.0 (2024-05-28)
- No modifications / Keep major and minors versions in sync with all parts of the project
## 4.0.0 (2024-04-19)
### 🔨 Internal / Developers
- SonarQube integration
- Migration to GitBreaker library for all Gitlab API calls
- Dependencies update
## 3.5.0 (2024-02-26) ## 3.5.0 (2024-02-26)
- No modifications / Keep major and minors versions in sync with all parts of the project - No modifications / Keep major and minors versions in sync with all parts of the project
......
...@@ -22,7 +22,7 @@ RUN npm install ...@@ -22,7 +22,7 @@ RUN npm install
RUN npm run build RUN npm run build
# Transform app to binary # Transform app to binary
RUN npx pkg . -t node18 --output ${BUILD_WORKDIR}/bin/app --public-packages "*" --public RUN npx pkg . -t node18 --output ${BUILD_WORKDIR}/bin/app --public-packages "*" --public --options no-warnings
...@@ -36,4 +36,6 @@ RUN apk add git ...@@ -36,4 +36,6 @@ RUN apk add git
ARG BUILD_WORKDIR ARG BUILD_WORKDIR
COPY --from=builder ${BUILD_WORKDIR}/bin/app /usr/local/bin/dojo_assignment_checker COPY --from=builder ${BUILD_WORKDIR}/bin/app /usr/local/bin/dojo_assignment_checker
\ No newline at end of file
ADD sonar/ /sonar/
# DojoAssignmentChecker # Documentation of `The Dojo Assignment Checker`
\ No newline at end of file
All documentations are available on the [Dojo documentation website](https://www.hepiapp.ch/) : https://www.hepiapp.ch/.
\ No newline at end of file
# Documentation of `The Dojo Assignment Checker`
All documentations are available on the [Dojo documentation website](https://www.hepiapp.ch/) : https://www.hepiapp.ch/.
\ No newline at end of file
#!/bin/bash
# Define color codes
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
DOCKERFILE=Dockerfile_AssignmentChecker
PROJECT_FOLDER=AssignmentChecker
test_if_command_unsuccessful() {
local status=$1
local title=$2
local text_if_failed=$3
if [ "$status" -ne 0 ]; then
echo -e "${title}: ${RED}${text_if_failed}: $status${NC}\n"
exit 1
fi
}
##########################################################
# Function to prompt for input if not provided
prompt_if_empty() {
local var_name=$1
local prompt_message=$2
local var_value=${!var_name}
if [ -z "$var_value" ]; then
read -p "$prompt_message: " var_value
export "$var_name"="$var_value"
fi
}
# Parse parameters
while [ "$1" != "" ]; do
case $1 in
--dockerhub-user ) shift
DOCKER_REGISTRY_USER=$1
;;
--dockerhub-password ) shift
DOCKER_REGISTRY_PASSWORD=$1
;;
--dockerhub-repo ) shift
DOCKER_REGISTRY_IMAGE=$1
;;
--backend-url ) shift
API_URL=$1
;;
* ) echo -e "${RED}Invalid parameter: $1${NC}"
exit 1
esac
shift
done
# Prompt for values if not provided
prompt_if_empty "DOCKER_REGISTRY_USER" "Docker Hub user"
prompt_if_empty "DOCKER_REGISTRY_PASSWORD" "Docker Hub password"
prompt_if_empty "DOCKER_REGISTRY_IMAGE" "Docker Hub repository"
prompt_if_empty "API_URL" "Backend url"
##########################################################
# Function to check if a command exists
check_dependency() {
local cmd=$1
if ! command -v $cmd &> /dev/null; then
echo -e "${RED}Error: $cmd is not installed.${NC}"
exit 1
fi
}
# Check for dependencies
echo -e "Dependencies: ${YELLOW}Checking...${NC}"
check_dependency jq
check_dependency docker
check_dependency sed
echo -e "Dependencies: ${GREEN}OK${NC}\n"
VERSION=$(jq -r .version $PROJECT_FOLDER/package.json)
CONTAINER_IMAGE=$DOCKER_REGISTRY_IMAGE:$VERSION
##########################################################
# Login to Docker Hub
echo -e "Docker Hub: ${YELLOW}Login in...${NC}"
echo "$DOCKER_REGISTRY_PASSWORD" | docker login -u "$DOCKER_REGISTRY_USER" --password-stdin "$DOCKER_REGISTRY" > /dev/null
test_if_command_unsuccessful $? "Docker Hub" "FAILED to login in"
echo -e "Docker Hub: ${GREEN}Logged in${NC}\n"
##########################################################
echo -e "Project files: ${YELLOW}Configuring...${NC}"
(
cd $PROJECT_FOLDER || exit 1
sed -i -r "s/\{\{VERSION\}\}/${VERSION}/g" src/app.ts 2> /dev/null
if [ $? -ne 0 ]; then # If on macOS
sed -i -r "s/{{VERSION}}/${VERSION}/g" src/app.ts 2> /dev/null
fi
sed -i -r "s/(DOTENV_KEY[ ]*:[ ]*[\'\"\`])[^'\"\`]*([\'\"\`])([ ]*\,)?//g" src/init.ts
sed -i -r "s/,[\ \n]*\}/\}/g" src/init.ts
# Write the content to the file
cat <<EOL > ".env"
##################### App env vars
API_URL=${API_URL}
DOCKERHUB_ASSIGNMENT_CHECKER_REPOSITORY=${DOCKER_REGISTRY_IMAGE}
EOL
)
echo -e "Project files: ${GREEN}Configured${NC}\n"
##########################################################
echo -e "Docker: ${YELLOW}Building/Uploading to Docker Hub...${NC}"
docker buildx create --use --platform=linux/amd64 > /dev/null 2> /dev/null
test_if_command_unsuccessful $? "Docker" "FAILED to initialize builder"
docker buildx build --platform=linux/amd64 --file $DOCKERFILE --push --tag "$CONTAINER_IMAGE" . > /dev/null 2> /dev/null
test_if_command_unsuccessful $? "Docker" "FAILED to build"
docker buildx imagetools create "$CONTAINER_IMAGE" --tag "$DOCKER_REGISTRY_IMAGE":latest > /dev/null 2> /dev/null
test_if_command_unsuccessful $? "Docker" "FAILED to set latest tag"
echo -e "Docker: ${GREEN}Uploaded to Docker Hub${NC}\n"
\ No newline at end of file
sonar.projectKey=DojoAssignmentChecker
sonar.qualitygate.wait=true
# Node needed to analyze JS/TS files
FROM node:18-slim AS node_base
FROM gcc:14
ARG SONAR_HOST_URL=https://isc-sonar.edu.hesge.ch
RUN apt update && apt install -y curl unzip build-essential make g++ clang git-core openssl libssl-dev && apt clean
# Download sonar tools
RUN mkdir -p /sonar && \
curl -sSLo sonar-scanner.zip https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-5.0.1.3006-linux.zip && \
unzip -o sonar-scanner.zip -d /sonar && \
mv /sonar/sonar-scanner-5.0.1.3006-linux/* /sonar/ && \
ln -s /sonar/bin/sonar-scanner /usr/local/bin/sonar-scanner && \
curl --insecure -sSLo build-wrapper-linux-x86.zip "$SONAR_HOST_URL/static/cpp/build-wrapper-linux-x86.zip" && \
unzip -o build-wrapper-linux-x86.zip -d /tmp && \
mv /tmp/build-wrapper-linux-x86/* /usr/local/bin/ && \
rm build-wrapper-linux-x86.zip sonar-scanner.zip
COPY ./cacerts /tmp/cacerts
ENV SONAR_SCANNER_OPTS="-Djavax.net.ssl.trustStore=/tmp/cacerts"
RUN mkdir -p /usr/src && \
useradd -m sonar && \
chown sonar:sonar /usr/src && \
chmod 744 /tmp/cacerts
USER sonar
WORKDIR /usr/src
COPY --from=node_base /usr/local/bin /usr/local/bin
COPY --from=node_base /usr/local/lib/node_modules/npm /usr/local/lib/node_modules/npm
File added