diff options
Diffstat (limited to 'sonar-scanner-engine')
3 files changed, 58 insertions, 17 deletions
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/sca/CliService.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sca/CliService.java index 013ac2df109..530798c4395 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/sca/CliService.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sca/CliService.java @@ -30,18 +30,21 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.function.Consumer; +import java.util.stream.Stream; import javax.annotation.Nullable; import org.apache.commons.csv.CSVFormat; import org.apache.commons.csv.CSVPrinter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.event.Level; +import org.sonar.api.batch.fs.InputFile; import org.sonar.api.batch.fs.internal.DefaultInputModule; import org.sonar.api.platform.Server; import org.sonar.api.utils.System2; import org.sonar.core.util.ProcessWrapperFactory; import org.sonar.scanner.config.DefaultConfiguration; import org.sonar.scanner.repository.TelemetryCache; +import org.sonar.scanner.scan.filesystem.ProjectExclusionFilters; import org.sonar.scanner.scm.ScmConfiguration; import org.sonar.scm.git.JGitUtils; @@ -53,20 +56,24 @@ import org.sonar.scm.git.JGitUtils; */ public class CliService { private static final Logger LOG = LoggerFactory.getLogger(CliService.class); - public static final String EXCLUDED_MANIFESTS_PROP_KEY = "sonar.sca.excludedManifests"; + public static final String SCA_EXCLUSIONS_KEY = "sonar.sca.exclusions"; + public static final String LEGACY_SCA_EXCLUSIONS_KEY = "sonar.sca.excludedManifests"; private final ProcessWrapperFactory processWrapperFactory; private final TelemetryCache telemetryCache; private final System2 system2; private final Server server; private final ScmConfiguration scmConfiguration; + private final ProjectExclusionFilters projectExclusionFilters; - public CliService(ProcessWrapperFactory processWrapperFactory, TelemetryCache telemetryCache, System2 system2, Server server, ScmConfiguration scmConfiguration) { + public CliService(ProcessWrapperFactory processWrapperFactory, TelemetryCache telemetryCache, System2 system2, Server server, ScmConfiguration scmConfiguration, + ProjectExclusionFilters projectExclusionFilters) { this.processWrapperFactory = processWrapperFactory; this.telemetryCache = telemetryCache; this.system2 = system2; this.server = server; this.scmConfiguration = scmConfiguration; + this.projectExclusionFilters = projectExclusionFilters; } public File generateManifestsZip(DefaultInputModule module, File cliExecutable, DefaultConfiguration configuration) throws IOException, IllegalStateException { @@ -121,7 +128,7 @@ public class CliService { } private @Nullable String getExcludeFlag(DefaultInputModule module, DefaultConfiguration configuration) throws IOException { - List<String> configExcludedPaths = getConfigExcludedPaths(configuration); + List<String> configExcludedPaths = getConfigExcludedPaths(configuration, projectExclusionFilters); List<String> scmIgnoredPaths = getScmIgnoredPaths(module); ArrayList<String> mergedExclusionPaths = new ArrayList<>(); @@ -141,12 +148,15 @@ public class CliService { return toCsvString(mergedExclusionPaths); } - private static List<String> getConfigExcludedPaths(DefaultConfiguration configuration) { - String[] excludedPaths = configuration.getStringArray(EXCLUDED_MANIFESTS_PROP_KEY); - if (excludedPaths == null) { - return List.of(); - } - return Arrays.stream(excludedPaths).toList(); + private static List<String> getConfigExcludedPaths(DefaultConfiguration configuration, ProjectExclusionFilters projectExclusionFilters) { + String[] sonarExclusions = projectExclusionFilters.getExclusionsConfig(InputFile.Type.MAIN); + String[] scaExclusions = configuration.getStringArray(SCA_EXCLUSIONS_KEY); + String[] scaExclusionsLegacy = configuration.getStringArray(LEGACY_SCA_EXCLUSIONS_KEY); + + return Stream.of(sonarExclusions, scaExclusions, scaExclusionsLegacy) + .flatMap(Arrays::stream) + .distinct() + .toList(); } private List<String> getScmIgnoredPaths(DefaultInputModule module) { diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/sca/ScaProperties.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sca/ScaProperties.java index e5086149c03..a697aef3e20 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/sca/ScaProperties.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sca/ScaProperties.java @@ -31,6 +31,8 @@ public class ScaProperties { private static final Pattern sonarScaPropertyRegex = Pattern.compile("^sonar\\.sca\\.([a-zA-Z]+)$"); private static final String SONAR_SCA_PREFIX = "sonar.sca."; private static final Set<String> IGNORED_PROPERTIES = Set.of( + // sonar.sca.exclusions is a special case which we handle when building --exclude + "sonar.sca.exclusions", // excludedManifests is a special case which we handle when building --exclude "sonar.sca.excludedManifests", // keep recursive enabled to better match sonar-scanner behavior diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/sca/CliServiceTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sca/CliServiceTest.java index e907294d6fd..7926860b731 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/sca/CliServiceTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sca/CliServiceTest.java @@ -36,6 +36,7 @@ import org.junit.jupiter.api.extension.RegisterExtension; import org.junit.jupiter.api.io.TempDir; import org.mockito.MockedStatic; import org.sonar.api.batch.bootstrap.ProjectDefinition; +import org.sonar.api.batch.fs.InputFile; import org.sonar.api.batch.fs.internal.DefaultInputModule; import org.sonar.api.batch.scm.ScmProvider; import org.sonar.api.platform.Server; @@ -44,6 +45,7 @@ import org.sonar.api.utils.System2; import org.sonar.core.util.ProcessWrapperFactory; import org.sonar.scanner.config.DefaultConfiguration; import org.sonar.scanner.repository.TelemetryCache; +import org.sonar.scanner.scan.filesystem.ProjectExclusionFilters; import org.sonar.scanner.scm.ScmConfiguration; import org.sonar.scm.git.GitScmProvider; import org.sonar.scm.git.JGitUtils; @@ -69,6 +71,7 @@ class CliServiceTest { ProcessWrapperFactory processWrapperFactory = mock(ProcessWrapperFactory.class, CALLS_REAL_METHODS); private MockedStatic<JGitUtils> jGitUtilsMock; DefaultConfiguration configuration = mock(DefaultConfiguration.class); + ProjectExclusionFilters projectExclusionFilters = mock(ProjectExclusionFilters.class); private CliService underTest; @@ -86,9 +89,12 @@ class CliServiceTest { jGitUtilsMock.when(() -> JGitUtils.getAllIgnoredPaths(any(Path.class))).thenReturn(List.of("ignored.txt")); when(server.getVersion()).thenReturn("1.0.0"); logTester.setLevel(INFO); + when(projectExclusionFilters.getExclusionsConfig(InputFile.Type.MAIN)).thenReturn(new String[0]); + when(configuration.getStringArray(CliService.SCA_EXCLUSIONS_KEY)).thenReturn(new String[0]); + when(configuration.getStringArray(CliService.LEGACY_SCA_EXCLUSIONS_KEY)).thenReturn(new String[0]); when(configuration.getBoolean("sonar.sca.debug")).thenReturn(Optional.of(true)); - underTest = new CliService(processWrapperFactory, telemetryCache, System2.INSTANCE, server, scmConfiguration); + underTest = new CliService(processWrapperFactory, telemetryCache, System2.INSTANCE, server, scmConfiguration, projectExclusionFilters); } @AfterEach @@ -102,8 +108,8 @@ class CliServiceTest { void generateZip_shouldCallProcessCorrectly_andRegisterTelemetry() throws IOException, URISyntaxException { assertThat(rootModuleDir.resolve("test_file").toFile().createNewFile()).isTrue(); - when(configuration.getProperties()).thenReturn(Map.of(CliService.EXCLUDED_MANIFESTS_PROP_KEY, "foo,bar,baz/**")); - when(configuration.getStringArray(CliService.EXCLUDED_MANIFESTS_PROP_KEY)).thenReturn(new String[] {"foo", "bar", "baz/**"}); + when(configuration.getProperties()).thenReturn(Map.of(CliService.SCA_EXCLUSIONS_KEY, "foo,bar,baz/**")); + when(configuration.getStringArray(CliService.SCA_EXCLUSIONS_KEY)).thenReturn(new String[] {"foo", "bar", "baz/**"}); File producedZip = underTest.generateManifestsZip(rootInputModule, scriptDir(), configuration); @@ -239,7 +245,7 @@ class CliServiceTest { } @Test - void generateZip_withExclusionDisabled_doesNotIncludeScmIgnoredPaths() throws Exception { + void generateZip_withScmExclusionDisabled_doesNotIncludeScmIgnoredPaths() throws Exception { when(scmConfiguration.isExclusionDisabled()).thenReturn(true); underTest.generateManifestsZip(rootInputModule, scriptDir(), configuration); @@ -259,8 +265,8 @@ class CliServiceTest { } @Test - void generateZip_withExistingExcludedManifests_appendsScmIgnoredPaths() throws Exception { - when(configuration.getStringArray(CliService.EXCLUDED_MANIFESTS_PROP_KEY)).thenReturn(new String[] {"**/test/**"}); + void generateZip_withExcludedManifests_appendsScmIgnoredPaths() throws Exception { + when(configuration.getStringArray(CliService.SCA_EXCLUSIONS_KEY)).thenReturn(new String[] {"**/test/**"}); underTest.generateManifestsZip(rootInputModule, scriptDir(), configuration); @@ -269,8 +275,8 @@ class CliServiceTest { } @Test - void generateZip_withExcludedManifestsSettingContainingBadCharacters_handlesTheBadCharacters() throws Exception { - when(configuration.getStringArray(CliService.EXCLUDED_MANIFESTS_PROP_KEY)).thenReturn(new String[] { + void generateZip_withExcludedManifestsContainingBadCharacters_handlesTheBadCharacters() throws Exception { + when(configuration.getStringArray(CliService.SCA_EXCLUSIONS_KEY)).thenReturn(new String[] { "**/test/**", "**/path with spaces/**", "**/path,with,commas/**", "**/path'with'quotes/**", "**/path\"with\"double\"quotes/**"}); underTest.generateManifestsZip(rootInputModule, scriptDir(), configuration); @@ -284,6 +290,29 @@ class CliServiceTest { } @Test + void generateZip_withExcludedManifestsContainingDupes_dedupes() throws Exception { + when(configuration.getStringArray(CliService.SCA_EXCLUSIONS_KEY)).thenReturn(new String[] {"**/test1/**", "**/test2/**", "**/test1/**"}); + when(configuration.getStringArray(CliService.LEGACY_SCA_EXCLUSIONS_KEY)).thenReturn(new String[] {"**/test1/**", "**/test3/**"}); + + underTest.generateManifestsZip(rootInputModule, scriptDir(), configuration); + + String capturedArgs = logTester.logs().stream().filter(log -> log.contains("Arguments Passed In:")).findFirst().get(); + assertThat(capturedArgs).contains("--exclude **/test1/**,**/test2/**,**/test3/**,ignored.txt,.scannerwork/**"); + } + + @Test + void generateZip_withExcludedManifestsAndSonarExcludesContainingDupes_mergesAndDedupes() throws Exception { + when(projectExclusionFilters.getExclusionsConfig(InputFile.Type.MAIN)).thenReturn(new String[] {"**/test1/**", "**/test4/**"}); + when(configuration.getStringArray(CliService.SCA_EXCLUSIONS_KEY)).thenReturn(new String[] {"**/test1/**", "**/test2/**", "**/test1/**"}); + when(configuration.getStringArray(CliService.LEGACY_SCA_EXCLUSIONS_KEY)).thenReturn(new String[] {"**/test1/**", "**/test3/**"}); + + underTest.generateManifestsZip(rootInputModule, scriptDir(), configuration); + + String capturedArgs = logTester.logs().stream().filter(log -> log.contains("Arguments Passed In:")).findFirst().get(); + assertThat(capturedArgs).contains("--exclude **/test1/**,**/test4/**,**/test2/**,**/test3/**,ignored.txt,.scannerwork/**"); + } + + @Test void generateZip_withScmIgnoresContainingBadCharacters_handlesTheBadCharacters() throws Exception { jGitUtilsMock.when(() -> JGitUtils.getAllIgnoredPaths(any(Path.class))) .thenReturn(List.of("**/test/**", "**/path with spaces/**", "**/path,with,commas/**", "**/path'with'quotes/**", "**/path\"with\"double\"quotes/**")); |