UNPKG

@sonar/scan

Version:
134 lines (133 loc) 6.08 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.fetchScannerEngine = fetchScannerEngine; exports.runScannerEngine = runScannerEngine; /* * sonar-scanner-npm * Copyright (C) 2022-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * 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 GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ const fs_extra_1 = __importDefault(require("fs-extra")); const child_process_1 = require("child_process"); const constants_1 = require("./constants"); const file_1 = require("./file"); const logging_1 = require("./logging"); const proxy_1 = require("./proxy"); const request_1 = require("./request"); const types_1 = require("./types"); async function fetchScannerEngine(properties) { (0, logging_1.log)(logging_1.LogLevel.DEBUG, `Detecting latest version of ${constants_1.SONAR_SCANNER_ALIAS}`); const { data } = await (0, request_1.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 (0, request_1.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_extra_1.default.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 process.stdout.write(parsed.stacktrace); } } catch (e) { process.stdout.write(message); } } function runScannerEngine(javaBinPath, scannerEnginePath, scanOptions, properties) { (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_extra_1.default.promises.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 = (0, child_process_1.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}`)); } }); }); }