Skip to content

Commit

Permalink
SCANJLIB-244 Log server type info on bootstrap
Browse files Browse the repository at this point in the history
  • Loading branch information
aleksandra-bozhinoska-sonarsource committed Dec 26, 2024
1 parent f545139 commit c4ba2e4
Show file tree
Hide file tree
Showing 7 changed files with 128 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -138,14 +138,18 @@ public ScannerEngineBootstrapResult bootstrap() {
scannerHttpClient.init(httpConfig);

var serverVersion = !isSonarCloud ? getServerVersion(scannerHttpClient) : null;
ScannerEngineFacade scannerFacade;
if (isSonarCloud || VersionUtils.isAtLeastIgnoringQualifier(serverVersion, SQ_VERSION_NEW_BOOTSTRAPPING)) {
var launcher = scannerEngineLauncherFactory.createLauncher(scannerHttpClient, fileCache, immutableProperties);
return new SuccessfulBootstrap(new NewScannerEngineFacade(immutableProperties, launcher, isSonarCloud, serverVersion));
scannerFacade = new NewScannerEngineFacade(immutableProperties, launcher, isSonarCloud, serverVersion);
} else {
var launcher = launcherFactory.createLauncher(scannerHttpClient, fileCache);
var adaptedProperties = adaptDeprecatedPropertiesForInProcessBootstrapping(immutableProperties, httpConfig);
return new SuccessfulBootstrap(new InProcessScannerEngineFacade(adaptedProperties, launcher, false, serverVersion));
scannerFacade = new InProcessScannerEngineFacade(adaptedProperties, launcher, false, serverVersion);
}

logServerType(scannerFacade);
return new SuccessfulBootstrap(scannerFacade);
} catch (MessageException e) {
return handleException(e);
}
Expand Down Expand Up @@ -182,6 +186,13 @@ private static void logWithStacktraceOnlyIfDebug(String message, Throwable t) {
}
}

private static void logServerType(ScannerEngineFacade engine) {
if (engine.isSonarCloud()) {
LOG.info("Communicating with SonarQube Cloud");
} else {
LOG.info("Communicating with {} {}", engine.getServerType(), engine.getServerVersion());
}
}

/**
* Older SonarQube versions used to rely on some different properties, or even {@link System} properties.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,11 @@ public interface ScannerEngineFacade extends AutoCloseable {
* @return true if the analysis succeeded, false otherwise.
*/
boolean analyze(Map<String, String> analysisProps);

/**
* Get the type of the server that the scanner is connected to. Distinguishes SonarQube Cloud, SonarQube Server and SonarQube Community Build.
*
* @return whether scanner is connected to SonarQube Cloud, Server or Community Build.
*/
String getServerType();
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import javax.annotation.Nullable;
import org.sonarsource.scanner.lib.ScannerEngineFacade;
import org.sonarsource.scanner.lib.internal.facade.forked.JreCacheHit;
import org.sonarsource.scanner.lib.internal.util.VersionUtils;

public abstract class AbstractScannerEngineFacade implements ScannerEngineFacade {

Expand Down Expand Up @@ -82,4 +83,17 @@ private static void initAnalysisProperties(Map<String, String> p) {
public Map<String, String> getBootstrapProperties() {
return bootstrapProperties;
}

@Override
public String getServerType() {
if (isSonarCloud()) {
return "SonarQube Cloud";
}

String version = getServerVersion();
if (VersionUtils.compareMajor(version, 10) <= 0 || VersionUtils.compareMajor(version, 2025) >= 0) {
return "SonarQube Server";
}
return "SonarQube Community Build";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,19 @@
package org.sonarsource.scanner.lib.internal.util;

import java.lang.module.ModuleDescriptor.Version;
import java.util.regex.Pattern;
import javax.annotation.Nullable;
import org.apache.commons.lang3.StringUtils;

import static org.apache.commons.lang3.StringUtils.substringAfter;
import static org.apache.commons.lang3.StringUtils.substringBefore;
import static org.apache.commons.lang3.StringUtils.trimToEmpty;

public class VersionUtils {

private static final String SEQUENCE_SEPARATOR = ".";
private static final String QUALIFIER_SEPARATOR = "-";

private VersionUtils() {
// only util static methods
}
Expand All @@ -36,9 +45,32 @@ private VersionUtils() {
* @return true if the version is at least the target version
*/
public static boolean isAtLeastIgnoringQualifier(@Nullable String version, String targetVersion) {
if (StringUtils.isBlank(version) || String.valueOf(version.charAt(0)).matches("\\D")) {
if (isOfUnexpectedFormat(version)) {
return false;
}
return Version.parse(StringUtils.substringBefore(version, "-")).compareTo(Version.parse(targetVersion)) >= 0;
}

public static int compareMajor(@Nullable String version, int number) {
if (isOfUnexpectedFormat(version)) {
return Integer.compare(0, number);
}

String s = trimToEmpty(version);
String qualifier = substringAfter(s, QUALIFIER_SEPARATOR);
if (!qualifier.isEmpty()) {
s = substringBefore(s, QUALIFIER_SEPARATOR);
}

String[] fields = s.split(Pattern.quote(SEQUENCE_SEPARATOR));
try {
return Integer.compare(Integer.parseInt(fields[0]), number);
} catch (NumberFormatException e) {
return Integer.compare(0, number);
}
}

private static boolean isOfUnexpectedFormat(@Nullable String version) {
return StringUtils.isBlank(version) || String.valueOf(version.trim().charAt(0)).matches("\\D");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.stream.Collectors;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
Expand Down Expand Up @@ -99,6 +100,7 @@ void should_use_new_bootstrapping_with_default_url() throws Exception {
try (var bootstrapResult = underTest.bootstrap()) {
verify(scannerEngineLauncherFactory).createLauncher(eq(scannerHttpClient), any(FileCache.class), anyMap());
assertThat(bootstrapResult.getEngineFacade().isSonarCloud()).isTrue();
verifyCloudServerTypeLogged();
}
}

Expand All @@ -108,6 +110,7 @@ void should_use_new_bootstrapping_with_sonarcloud_url() throws Exception {
verify(scannerEngineLauncherFactory).createLauncher(eq(scannerHttpClient), any(FileCache.class), anyMap());
assertThat(bootstrapResult.isSuccessful()).isTrue();
assertThat(bootstrapResult.getEngineFacade().isSonarCloud()).isTrue();
verifyCloudServerTypeLogged();
}
}

Expand All @@ -117,10 +120,23 @@ void should_use_new_bootstrapping_with_sonarqube_10_6() throws Exception {
try (var bootstrapResult = underTest.setBootstrapProperty(ScannerProperties.HOST_URL, "http://localhost").bootstrap()) {
verify(scannerEngineLauncherFactory).createLauncher(eq(scannerHttpClient), any(FileCache.class), anyMap());
assertThat(bootstrapResult.getEngineFacade().isSonarCloud()).isFalse();
verifySonarQubeServerTypeLogged(SQ_VERSION_NEW_BOOTSTRAPPING);
assertThat(bootstrapResult.getEngineFacade().getServerVersion()).isEqualTo(SQ_VERSION_NEW_BOOTSTRAPPING);
}
}

@Test
void should_log_cb_server_type() throws Exception {
String testCBVersion = "24.12.0.23452";
when(scannerHttpClient.callRestApi("/analysis/version")).thenReturn(testCBVersion);
try (var bootstrapResult = underTest.setBootstrapProperty(ScannerProperties.HOST_URL, "http://localhost").bootstrap()) {
verify(scannerEngineLauncherFactory).createLauncher(eq(scannerHttpClient), any(FileCache.class), anyMap());
assertThat(bootstrapResult.getEngineFacade().isSonarCloud()).isFalse();
assertThat(logTester.logs(Level.INFO)).contains("Communicating with SonarQube Community Build ".concat(testCBVersion));
assertThat(bootstrapResult.getEngineFacade().getServerVersion()).isEqualTo(testCBVersion);
}
}

@Test
void should_use_old_bootstrapping_with_sonarqube_10_5() throws Exception {
IsolatedLauncherFactory launcherFactory = mock(IsolatedLauncherFactory.class);
Expand All @@ -136,6 +152,7 @@ void should_use_old_bootstrapping_with_sonarqube_10_5() throws Exception {
verify(launcherFactory).createLauncher(eq(scannerHttpClient), any(FileCache.class));
assertThat(bootstrapResult.getEngineFacade().isSonarCloud()).isFalse();
assertThat(bootstrapResult.getEngineFacade().getServerVersion()).isEqualTo("10.5");
verifySonarQubeServerTypeLogged("10.5");
}
}

Expand All @@ -155,7 +172,9 @@ void should_show_help_on_proxy_auth_error() throws Exception {
assertThat(result.isSuccessful()).isFalse();
}

assertThat(logTester.logs(Level.ERROR)).contains("Failed to query server version: Proxy Authentication Required. Please check the properties sonar.scanner.proxyUser and sonar.scanner.proxyPassword.");
assertThat(logTester.logs(Level.ERROR)).contains("Failed to query server version: Proxy Authentication Required. Please check the properties sonar.scanner.proxyUser and " +
"sonar.scanner.proxyPassword.");
assertThatNoServerTypeIsLogged();
}

@Test
Expand All @@ -182,6 +201,7 @@ void should_preserve_both_exceptions_when_checking_version() throws Exception {
.containsSubsequence(
"Suppressed: org.sonarsource.scanner.lib.internal.http.HttpException: Not Found",
"Caused by: org.sonarsource.scanner.lib.internal.http.HttpException: Server Error");
assertThatNoServerTypeIsLogged();
}


Expand All @@ -201,7 +221,9 @@ void should_log_user_friendly_message_when_auth_error(int code) throws Exception
assertThat(result.isSuccessful()).isFalse();
}

assertThat(logTester.logs(Level.ERROR)).contains("Failed to query server version: Unauthorized. Please check the property sonar.token or the environment variable SONAR_TOKEN.");
assertThat(logTester.logs(Level.ERROR)).contains("Failed to query server version: Unauthorized. Please check the property sonar.token or the environment variable SONAR_TOKEN" +
".");
assertThatNoServerTypeIsLogged();
}

@Test
Expand Down Expand Up @@ -430,4 +452,16 @@ void should_not_change_ssl_properties_if_already_set_as_scanner_props(@TempDir P
assertThat(mutableProps).containsExactlyInAnyOrderEntriesOf(properties);
}

private void verifyCloudServerTypeLogged() {
assertThat(logTester.logs(Level.INFO)).contains("Communicating with SonarQube Cloud");
}

private void verifySonarQubeServerTypeLogged(String version) {
assertThat(logTester.logs(Level.INFO)).contains("Communicating with SonarQube Server ".concat(version));
}

private void assertThatNoServerTypeIsLogged() {
assertThat(logTester.logs(Level.INFO).stream().filter(logMessage -> logMessage.startsWith("Communicating with")).collect(Collectors.toList())).isEmpty();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,17 @@ void error_dump() {
.hasMessage("Fail to export scanner properties");
}

@Test
void test_get_server_type() {
assertThat(underTest.getServerType()).isEqualTo("SonarQube Cloud");

var nonCommunityServerFacade = new SimulationScannerEngineFacade(new HashMap<>(), false, "10.6");
assertThat(nonCommunityServerFacade.getServerType()).isEqualTo("SonarQube Server");

var communityServerFacade = new SimulationScannerEngineFacade(new HashMap<>(), false, "24.12");
assertThat(communityServerFacade.getServerType()).isEqualTo("SonarQube Community Build");
}

private Map<String, String> createProperties() {
Map<String, String> prop = new HashMap<>();
prop.put("key1:subkey", "value1");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,18 @@ void isAtLeast_IgnoringQualifier_shouldCompareCorrectly() {
assertThat(VersionUtils.isAtLeastIgnoringQualifier("10.6-SNAPSHOT", "10.5")).isTrue();
assertThat(VersionUtils.isAtLeastIgnoringQualifier("10.5.0.1234", "10.5")).isTrue();
}

@Test
void compareMajor_shouldCompareMajorCorrectly() {
assertThat(VersionUtils.compareMajor(null, 10)).isNegative();
assertThat(VersionUtils.compareMajor("fhk10.5.0.1234", 10)).isNegative();

assertThat(VersionUtils.compareMajor("10.5.0.1234", 10)).isZero();
assertThat(VersionUtils.compareMajor("11.5.0.1234", 10)).isPositive();
assertThat(VersionUtils.compareMajor("8.5.0.1234", 10)).isNegative();

assertThat(VersionUtils.compareMajor("10.0-SNAPSHOT", 10)).isZero();
assertThat(VersionUtils.compareMajor(" 10.5.0.1234", 10)).isZero();
assertThat(VersionUtils.compareMajor("", 10)).isNegative();
}
}

0 comments on commit c4ba2e4

Please sign in to comment.