sonarqube-scanner
Version:
SonarQube/SonarCloud Scanner for the JavaScript world
130 lines (129 loc) • 5.69 kB
JavaScript
;
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}`));
}
});
});
}