diff --git a/.cirrus.yml b/.cirrus.yml
index fc20b660..df7c6f05 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -111,14 +111,19 @@ gradle_qa_task:
eks_container:
<<: *CONTAINER_DEFINITION_17
cpu: 2
- memory: 2G
+ memory: 4G
env:
matrix:
- - GRADLE_VERSION: 7.5.1
- ANDROID_GRADLE_VERSION: 7.1.0
- - GRADLE_VERSION: 8.2.1
- ANDROID_GRADLE_VERSION: 8.1.1
+ # TODO The combination of AGP 8.3.0 and Gradle 8.3.0 should be restored as part of SCANGRADLE-162
+ #- GRADLE_VERSION: 8.4
+ # ANDROID_GRADLE_VERSION: 8.3.0
+ - GRADLE_VERSION: 8.10
+ - GRADLE_VERSION: 8.4
+ - GRADLE_VERSION: 8.3
- GRADLE_VERSION: 8.0
+ - GRADLE_VERSION: 7.6.4
+#- GRADLE_VERSION: 7.5.1
+# ANDROID_GRADLE_VERSION: 7.1.0
script:
- ./cirrus/cirrus-qa.sh
diff --git a/build.gradle.kts b/build.gradle.kts
index b25bc978..f3a72b6b 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -70,7 +70,7 @@ repositories {
}
dependencies {
- implementation("org.sonarsource.scanner.api:sonar-scanner-api:2.16.2.588")
+ implementation("org.sonarsource.scanner.lib:sonar-scanner-java-library:3.1.1.261")
compileOnly("com.google.code.findbugs:jsr305:3.0.2")
compileOnly("com.android.tools.build:gradle:8.1.1")
compileOnly("org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.21")
diff --git a/integrationTests/pom.xml b/integrationTests/pom.xml
index e31b45bf..3f5f0622 100644
--- a/integrationTests/pom.xml
+++ b/integrationTests/pom.xml
@@ -75,6 +75,12 @@
3.1.0
test
+
+ org.jspecify
+ jspecify
+ 1.0.0
+ test
+
diff --git a/integrationTests/src/test/java/org/sonarqube/gradle/AbstractGradleIT.java b/integrationTests/src/test/java/org/sonarqube/gradle/AbstractGradleIT.java
index c4c79752..07193996 100644
--- a/integrationTests/src/test/java/org/sonarqube/gradle/AbstractGradleIT.java
+++ b/integrationTests/src/test/java/org/sonarqube/gradle/AbstractGradleIT.java
@@ -30,10 +30,12 @@
import java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.Properties;
import java.util.stream.Stream;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
+import org.jspecify.annotations.Nullable;
import org.junit.Rule;
import org.junit.rules.TemporaryFolder;
@@ -79,16 +81,12 @@ protected Properties runGradlewSonarSimulationModeWithEnv(String project, Map env, String... args) throws Exception {
File out = temp.newFile();
String[] newArgs = Stream.concat(
- Stream.of("-Dsonar.scanner.dumpToFile=" + out.getAbsolutePath()),
+ Stream.of("-Dsonar.scanner.internal.dumpToFile=" + out.getAbsolutePath()),
Arrays.stream(args))
.toArray(String[]::new);
- runGradlewSonarWithEnv(project, exeRelativePath, env, newArgs);
+ RunResult result = runGradlewSonarWithEnv(project, exeRelativePath, env, newArgs);
- Properties props = new Properties();
- try (FileReader fr = new FileReader(out)) {
- props.load(fr);
- }
- return props;
+ return result.getDumpedProperties().get();
}
protected RunResult runGradlewSonarWithEnv(String project, Map env, String... args) throws Exception {
@@ -152,7 +150,7 @@ protected RunResult runGradlewWithEnvQuietly(String project, String exeRelativeP
String output = FileUtils.readFileToString(outputFile, StandardCharsets.UTF_8);
- return new RunResult(output, p.exitValue());
+ return new RunResult(output, p.exitValue(), getDumpedProperties(command));
}
private static int getJavaVersion() {
@@ -168,13 +166,34 @@ private static int getJavaVersion() {
return Integer.parseInt(version);
}
+ @Nullable
+ private static Properties getDumpedProperties(List command) throws IOException {
+ for (String part : command) {
+ if (part.trim().startsWith("-Dsonar.scanner.internal.dumpToFile=")) {
+ File dumpFile = new File(part.split("=")[1]);
+ return loadProperties(dumpFile);
+ }
+ }
+ return null;
+ }
+
+ private static Properties loadProperties(File out) throws IOException {
+ Properties props = new Properties();
+ try (FileReader fr = new FileReader(out)) {
+ props.load(fr);
+ }
+ return props;
+ }
+
protected static class RunResult {
private final String log;
private final int exitValue;
+ private final Properties dumpedProperties;
- RunResult(String log, int exitValue) {
+ RunResult(String log, int exitValue, @Nullable Properties dumpedProperties) {
this.log = log;
this.exitValue = exitValue;
+ this.dumpedProperties = dumpedProperties;
}
public String getLog() {
@@ -184,5 +203,9 @@ public String getLog() {
public int getExitValue() {
return exitValue;
}
+
+ public Optional getDumpedProperties() {
+ return Optional.ofNullable(dumpedProperties);
+ }
}
}
diff --git a/integrationTests/src/test/java/org/sonarqube/gradle/GradleTest.java b/integrationTests/src/test/java/org/sonarqube/gradle/GradleTest.java
index f6f68c54..3d21079d 100644
--- a/integrationTests/src/test/java/org/sonarqube/gradle/GradleTest.java
+++ b/integrationTests/src/test/java/org/sonarqube/gradle/GradleTest.java
@@ -19,6 +19,7 @@
*/
package org.sonarqube.gradle;
+import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collections;
@@ -26,6 +27,7 @@
import java.util.Map;
import java.util.Properties;
import org.junit.Assume;
+import org.junit.Ignore;
import org.junit.Test;
import static java.util.Arrays.stream;
@@ -65,11 +67,17 @@ public void testDebugModeEnabled() throws Exception {
@Test
public void testSetLogLevel() throws Exception {
- RunResult runResult = runGradlewSonarWithEnv("/java-gradle-log-level", emptyMap(), "-Dsonar.scanner.dumpToFile=asd");
+ File output = temp.newFile("will-not-be-used-for-this-test.txt");
+ String args = String.format(
+ "-Dsonar.scanner.internal.dumpToFile=%s",
+ output.getAbsolutePath()
+ );
+ RunResult runResult = runGradlewSonarWithEnv("/java-gradle-log-level", emptyMap(), args);
// This is a debug log entry
- assertThat(runResult.getLog()).contains("Work directory:");
+ assertThat(runResult.getLog()).contains(":sonar");
}
+ @Ignore("TODO SCANGRADLE-159: sonar.scanner.skip does not prevent reaching to the server!")
@Test
public void testSkip() throws Exception {
Map env = new HashMap<>();
@@ -77,7 +85,7 @@ public void testSkip() throws Exception {
RunResult result = runGradlewSonarWithEnv("/java-gradle-simple", env);
System.out.println(result.getLog());
- assertThat(result.getExitValue()).isEqualTo(0);
+ assertThat(result.getExitValue()).isZero();
assertThat(result.getLog()).contains("Sonar Scanner analysis skipped");
}
@@ -90,7 +98,7 @@ public void testHostUrlInEnv() throws Exception {
System.out.println(result.getLog());
assertThat(result.getExitValue()).isEqualTo(1);
assertThat(result.getLog()).contains("java.net.UnknownHostException");
- assertThat(result.getLog()).contains("SonarQube server [http://host-in-env] can not be reached");
+ assertThat(result.getLog()).contains("Call to URL [http://host-in-env/api/server/version] failed");
}
@@ -199,7 +207,7 @@ public void testMultimoduleProjectWithSourceInRoot() throws Exception {
@Test
public void testFlatProjectStructure() throws Exception {
Properties props = runGradlewSonarSimulationModeWithEnv("/multi-module-flat", "build", emptyMap());
- assertThat(Paths.get(props.getProperty("sonar.projectBaseDir")).getFileName().toString()).isEqualTo("multi-module-flat");
+ assertThat(Paths.get(props.getProperty("sonar.projectBaseDir")).getFileName()).hasToString("multi-module-flat");
}
@Test
@@ -248,8 +256,10 @@ public void testJaCoCoProperties() throws Exception {
public void testProjectWithConfigurationCacheDoubleExecutionsShouldWork() throws Exception {
Assume.assumeTrue("Tests only applies to version 6.5.0 or greater", getGradleVersion().isGreaterThanOrEqualTo("6.5.0"));
- runGradlewSonarWithEnv("/java-gradle-simple", emptyMap(), "-Dsonar.scanner.dumpToFile=asd", "--configuration-cache");
- RunResult runResult = runGradlewSonarWithEnv("/java-gradle-simple", emptyMap(), "-Dsonar.scanner.dumpToFile=asd", "--configuration-cache");
+ String dumpProperty = String.format("-Dsonar.scanner.internal.dumpToFile=%s", temp.newFile().getAbsolutePath());
+
+ runGradlewSonarWithEnv("/java-gradle-simple", emptyMap(), dumpProperty, "--configuration-cache");
+ RunResult runResult = runGradlewSonarWithEnv("/java-gradle-simple", emptyMap(), dumpProperty, "--configuration-cache");
assertThat(runResult.getLog()).doesNotContain("no properties configured, was it skipped in all projects?");
assertThat(runResult.getLog()).contains("BUILD SUCCESSFUL");
diff --git a/src/main/java/org/sonarqube/gradle/ScanProperties.java b/src/main/java/org/sonarqube/gradle/ScanProperties.java
new file mode 100644
index 00000000..430dec3d
--- /dev/null
+++ b/src/main/java/org/sonarqube/gradle/ScanProperties.java
@@ -0,0 +1,29 @@
+/*
+ * SonarQube Scanner for Gradle
+ * Copyright (C) 2015-2024 SonarSource
+ * 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 02
+ */
+package org.sonarqube.gradle;
+
+public final class ScanProperties {
+ public static final String SKIP = "sonar.skip";
+ public static final String PROJECT_SOURCE_DIRS = "sonar.sources";
+ public static final String PROJECT_TEST_DIRS = "sonar.tests";
+ private ScanProperties() {
+ /* This is a utility class with constants */
+ }
+}
diff --git a/src/main/java/org/sonarqube/gradle/SonarPropertyComputer.java b/src/main/java/org/sonarqube/gradle/SonarPropertyComputer.java
index c7039f48..9771f95e 100644
--- a/src/main/java/org/sonarqube/gradle/SonarPropertyComputer.java
+++ b/src/main/java/org/sonarqube/gradle/SonarPropertyComputer.java
@@ -66,8 +66,7 @@
import org.gradle.testing.jacoco.tasks.JacocoReport;
import org.gradle.util.GradleVersion;
import org.sonarqube.gradle.SonarUtils.InputFileType;
-import org.sonarsource.scanner.api.ScanProperties;
-import org.sonarsource.scanner.api.Utils;
+import org.sonarsource.scanner.lib.EnvironmentConfig;
import static java.util.stream.Collectors.groupingBy;
import static org.sonarqube.gradle.SonarUtils.appendProp;
@@ -191,7 +190,7 @@ private boolean shouldApplyScanAll(Project project, Map properti
var sonarProps = new SonarProperties(new HashMap<>());
actionBroadcastMap.get(project.getPath()).execute(sonarProps);
- boolean sourcesOrTestsAlreadySet = Stream.of(System.getProperties().keySet(), Utils.loadEnvironmentProperties(System.getenv()).keySet(), sonarProps.getProperties().keySet())
+ boolean sourcesOrTestsAlreadySet = Stream.of(System.getProperties().keySet(), EnvironmentConfig.load(System.getenv()).keySet(), sonarProps.getProperties().keySet())
.flatMap(Collection::stream)
.map(String.class::cast)
.anyMatch(k -> ScanProperties.PROJECT_SOURCE_DIRS.endsWith(k) || ScanProperties.PROJECT_TEST_DIRS.endsWith(k));
@@ -337,8 +336,8 @@ private static void configureSourceEncoding(Project project, final Map properties) {
- for (Map.Entry