@sonar/scan
Version:
SonarQube/SonarCloud Scanner for the JavaScript world
136 lines (135 loc) • 6.54 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.fetchServerVersion = fetchServerVersion;
exports.serverSupportsJREProvisioning = serverSupportsJREProvisioning;
exports.fetchJRE = fetchJRE;
/*
* 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 path_1 = __importDefault(require("path"));
const semver_1 = __importDefault(require("semver"));
const constants_1 = require("./constants");
const file_1 = require("./file");
const logging_1 = require("./logging");
const request_1 = require("./request");
const types_1 = require("./types");
async function fetchServerVersion(properties) {
let version = null;
try {
// Try and fetch the new version endpoint first
(0, logging_1.log)(logging_1.LogLevel.DEBUG, `Fetching API V2 ${constants_1.API_V2_VERSION_ENDPOINT}`);
const response = await (0, request_1.fetch)({
url: constants_1.API_V2_VERSION_ENDPOINT,
});
version = semver_1.default.coerce(response.data);
}
catch (error) {
try {
// If it fails, fallback on deprecated server version endpoint
(0, logging_1.log)(logging_1.LogLevel.DEBUG, `Unable to fetch API V2 ${constants_1.API_V2_VERSION_ENDPOINT}: ${error}. Falling back on ${constants_1.API_OLD_VERSION_ENDPOINT}`);
const response = await (0, request_1.fetch)({
url: `${properties[types_1.ScannerProperty.SonarHostUrl]}${constants_1.API_OLD_VERSION_ENDPOINT}`,
});
version = semver_1.default.coerce(response.data);
}
catch (error) {
// If it also failed, give up
(0, logging_1.log)(logging_1.LogLevel.ERROR, `Failed to fetch server version: ${error}`);
// Inform the user of the host url that has failed, most
(0, logging_1.log)(logging_1.LogLevel.ERROR, `Verify that ${properties[types_1.ScannerProperty.SonarHostUrl]} is a valid SonarQube server`);
throw error;
}
}
// If we couldn't parse the version
if (!version) {
throw new Error(`Failed to parse server version "${version}"`);
}
return version;
}
async function serverSupportsJREProvisioning(properties) {
if (properties[types_1.ScannerProperty.SonarScannerInternalIsSonarCloud] === 'true') {
return true;
}
// SonarQube
(0, logging_1.log)(logging_1.LogLevel.DEBUG, 'Detecting SonarQube server version');
const SQServerInfo = semver_1.default.coerce(properties[types_1.ScannerProperty.SonarScannerInternalSqVersion]) ??
(await fetchServerVersion(properties));
(0, logging_1.log)(logging_1.LogLevel.INFO, 'SonarQube server version:', SQServerInfo.version);
const supports = semver_1.default.satisfies(SQServerInfo, `>=${constants_1.SONARQUBE_JRE_PROVISIONING_MIN_VERSION}`);
(0, logging_1.log)(logging_1.LogLevel.DEBUG, `SonarQube Server v${SQServerInfo} supports JRE provisioning: ${supports}`);
return supports;
}
async function fetchJRE(properties) {
(0, logging_1.log)(logging_1.LogLevel.DEBUG, 'Detecting latest version of JRE');
const jreMetaData = await fetchLatestSupportedJRE(properties);
(0, logging_1.log)(logging_1.LogLevel.DEBUG, 'Latest Supported JRE: ', jreMetaData);
(0, logging_1.log)(logging_1.LogLevel.DEBUG, 'Looking for Cached JRE');
const cachedJrePath = await (0, file_1.getCacheFileLocation)(properties, {
checksum: jreMetaData.sha256,
filename: jreMetaData.filename,
alias: constants_1.JRE_ALIAS,
});
properties[types_1.ScannerProperty.SonarScannerWasJreCacheHit] = cachedJrePath
? types_1.CacheStatus.Hit
: types_1.CacheStatus.Miss;
if (cachedJrePath) {
(0, logging_1.log)(logging_1.LogLevel.INFO, 'Using JRE from the cache');
return path_1.default.join(cachedJrePath + constants_1.UNARCHIVE_SUFFIX, jreMetaData.javaPath);
}
// JRE not found in cache. Download it.
const { archivePath, unarchivePath: jreDirPath } = await (0, file_1.getCacheDirectories)(properties, {
checksum: jreMetaData.sha256,
filename: jreMetaData.filename,
alias: constants_1.JRE_ALIAS,
});
// If the JRE has a download URL, download it
const url = jreMetaData.downloadUrl ?? `${constants_1.API_V2_JRE_ENDPOINT}/${jreMetaData.id}`;
(0, logging_1.log)(logging_1.LogLevel.DEBUG, `Starting download of ${constants_1.JRE_ALIAS}`);
await (0, request_1.download)(url, archivePath);
(0, logging_1.log)(logging_1.LogLevel.INFO, `Downloaded ${constants_1.JRE_ALIAS} to ${archivePath}`);
try {
await (0, file_1.validateChecksum)(archivePath, jreMetaData.sha256);
}
catch (error) {
await fs_extra_1.default.remove(archivePath);
throw error;
}
await (0, file_1.extractArchive)(archivePath, jreDirPath);
return path_1.default.join(jreDirPath, jreMetaData.javaPath);
}
async function fetchLatestSupportedJRE(properties) {
const os = properties[types_1.ScannerProperty.SonarScannerOs];
const arch = properties[types_1.ScannerProperty.SonarScannerArch];
(0, logging_1.log)(logging_1.LogLevel.DEBUG, `Downloading JRE information for ${os} ${arch} from ${constants_1.API_V2_JRE_ENDPOINT}`);
const { data } = await (0, request_1.fetch)({
url: constants_1.API_V2_JRE_ENDPOINT,
params: {
os,
arch,
},
});
if (data.length === 0) {
throw new Error(`No JREs available for your platform ${os} ${arch}`);
}
return data[0];
}