UNPKG

sonarqube-scanner

Version:
130 lines (129 loc) 5.69 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.fetchScannerEngine = fetchScannerEngine; exports.runScannerEngine = runScannerEngine; /* * sonar-scanner-npm * Copyright (C) SonarSource Sàrl * mailto:info AT sonarsource DOT com * * You can redistribute and/or modify this program under the terms of * the Sonar Source-Available License Version 1, as published by SonarSource Sàrl. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the Sonar Source-Available License for more details. * * You should have received a copy of the Sonar Source-Available License * along with this program; if not, see https://sonarsource.com/license/ssal/ */ const constants_1 = require("./constants"); const deps_1 = require("./deps"); const file_1 = require("./file"); const logging_1 = require("./logging"); const proxy_1 = require("./proxy"); const types_1 = require("./types"); async function fetchScannerEngine(properties) { const { fs, http } = (0, deps_1.getDeps)(); (0, logging_1.log)(logging_1.LogLevel.DEBUG, `Detecting latest version of ${constants_1.SONAR_SCANNER_ALIAS}`); const { data } = await http.fetch({ url: constants_1.API_V2_SCANNER_ENGINE_ENDPOINT, }); const { sha256: checksum, filename, downloadUrl } = data; (0, logging_1.log)(logging_1.LogLevel.DEBUG, `Latest ${constants_1.SONAR_SCANNER_ALIAS} version:`, filename); (0, logging_1.log)(logging_1.LogLevel.DEBUG, `Looking for Cached ${constants_1.SONAR_SCANNER_ALIAS}`); const cachedScannerEngine = await (0, file_1.getCacheFileLocation)(properties, { checksum, filename, alias: constants_1.SONAR_SCANNER_ALIAS, }); if (cachedScannerEngine) { (0, logging_1.log)(logging_1.LogLevel.DEBUG, `Using ${constants_1.SONAR_SCANNER_ALIAS} from the cache`); properties[types_1.ScannerProperty.SonarScannerWasEngineCacheHit] = 'true'; return cachedScannerEngine; } properties[types_1.ScannerProperty.SonarScannerWasEngineCacheHit] = 'false'; const { archivePath } = await (0, file_1.getCacheDirectories)(properties, { checksum, filename, alias: constants_1.SONAR_SCANNER_ALIAS, }); const url = downloadUrl ?? constants_1.API_V2_SCANNER_ENGINE_ENDPOINT; (0, logging_1.log)(logging_1.LogLevel.DEBUG, `Starting download of ${constants_1.SONAR_SCANNER_ALIAS}`); await http.download(url, archivePath); (0, logging_1.log)(logging_1.LogLevel.INFO, `Downloaded ${constants_1.SONAR_SCANNER_ALIAS} to ${archivePath}`); try { await (0, file_1.validateChecksum)(archivePath, checksum); } catch (error) { await fs.remove(archivePath); throw error; } return archivePath; } async function logOutput(message) { try { // Try and assume the log comes from the scanner engine const parsed = JSON.parse(message); (0, logging_1.logWithPrefix)(parsed.level, 'ScannerEngine', parsed.message); if (parsed.stacktrace) { // Console.log without newline globalThis.process.stdout.write(parsed.stacktrace); } } catch (e) { globalThis.process.stdout.write(message); } } function runScannerEngine(javaBinPath, scannerEnginePath, scanOptions, properties) { const { fs, spawn } = (0, deps_1.getDeps)(); (0, logging_1.log)(logging_1.LogLevel.DEBUG, `Running the ${constants_1.SONAR_SCANNER_ALIAS}`); // The scanner engine expects a JSON object of properties attached to a key name "scannerProperties" const propertiesJSON = JSON.stringify({ scannerProperties: Object.entries(properties).map(([key, value]) => ({ key, value, })), }); // Run the scanner-engine const args = [ ...(0, proxy_1.proxyUrlToJavaOptions)(properties), ...(scanOptions.jvmOptions ?? []), ...(properties[types_1.ScannerProperty.SonarScannerJavaOptions] ? properties[types_1.ScannerProperty.SonarScannerJavaOptions].split(' ') : []), '-jar', scannerEnginePath, ]; // If debugging with dumpToFile, write the properties to a file and exit const dumpToFile = properties[types_1.ScannerProperty.SonarScannerInternalDumpToFile]; if (dumpToFile) { const data = { propertiesJSON, javaBinPath, scannerEnginePath, args, }; (0, logging_1.log)(logging_1.LogLevel.INFO, 'Dumping data to file and exiting'); return fs.writeFile(dumpToFile, JSON.stringify(data, null, 2)); } (0, logging_1.log)(logging_1.LogLevel.DEBUG, `Running ${constants_1.SONAR_SCANNER_ALIAS}`, javaBinPath, ...args); const child = spawn(javaBinPath, args); (0, logging_1.log)(logging_1.LogLevel.DEBUG, `Writing properties to ${constants_1.SONAR_SCANNER_ALIAS}`, propertiesJSON); child.stdin.write(propertiesJSON); child.stdin.end(); child.stdout.on('data', buffer => buffer.toString().trim().split('\n').forEach(logOutput)); child.stderr.on('data', buffer => (0, logging_1.log)(logging_1.LogLevel.ERROR, buffer.toString())); return new Promise((resolve, reject) => { child.on('exit', code => { if (code === 0) { (0, logging_1.log)(logging_1.LogLevel.DEBUG, 'Scanner engine finished successfully'); resolve(); } else { reject(new Error(`Scanner engine failed with code ${code}`)); } }); }); }