Skip to content

Commit

Permalink
#139 Allows to set additional scan targets for IQ evaluations (#150)
Browse files Browse the repository at this point in the history
  • Loading branch information
guillermo-varela authored Jan 19, 2024
1 parent a3c4d21 commit edb4449
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 8 deletions.
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,14 @@ Gradle can be used to build projects developed in various programming languages.

```
plugins {
id 'org.sonatype.gradle.plugins.scan' version '2.6.0' // Update the version as needed
id 'org.sonatype.gradle.plugins.scan' version '2.7.0' // Update the version as needed
}
```

- Or `build.gradle.kts`:
```
plugins {
id ("org.sonatype.gradle.plugins.scan") version "2.6.0" // Update the version as needed
id ("org.sonatype.gradle.plugins.scan") version "2.7.0" // Update the version as needed
}
```

Expand Down Expand Up @@ -175,6 +175,7 @@ nexusIQScan {
// For projects using multiple custom variants for the release distribution, a Map can be set with the attributes names and values to match the specific variant. See more at the section "How to Deal with Multiple Release Variants" below in this doc.
variantAttributes = ['com.android.build.api.attributes.ProductFlavor:version': 'prod', 'other.attribute': 'other value'] // Optional, use it only when the plugin can't match a variant on its own
scanTargets = ['package-lock.json', '**/*.lock'] // Optional. Ant-like glob patterns for relative paths (to the project's folder) to select additional files to be scanned and evaluated.
}
```

Expand All @@ -195,6 +196,7 @@ nexusIQScan {
// For projects using multiple custom variants for the release distribution, a Map can be set with the attributes names and values to match the specific variant. See more at the section "How to Deal with Multiple Release Variants" below in this doc.
variantAttributes = mapOf("com.android.build.api.attributes.ProductFlavor:version" to "prod", "other.attribute" to "other value") // Optional, use it only when the plugin can't match a variant on its own
scanTargets = listOf("package-lock.json", "**/*.lock") // Optional. Ant-like glob patterns for relative paths (to the project's folder) to select additional files to be scanned and evaluated.
}
```

Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,11 @@ dependencies {
implementation "com.sonatype.nexus:nexus-platform-api:$nexusPlatformApiVersion"
implementation "org.sonatype.ossindex:ossindex-service-client:$ossIndexClientVersion"
implementation "ch.qos.logback:logback-classic:$logbackVersion"
implementation "commons-io:commons-io:$commonsIoVersion"

testImplementation gradleTestKit()
testImplementation "junit:junit:$junitVersion"
testImplementation "org.assertj:assertj-core:$assertJVersion"
testImplementation "commons-io:commons-io:$commonsIoVersion"
testImplementation "org.powermock:powermock-module-junit4:$powermockVersion"
testImplementation "org.powermock:powermock-api-mockito2:$powermockVersion"
}
Expand Down
6 changes: 3 additions & 3 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@
#

group=org.sonatype.gradle.plugins
version=2.6.3-SNAPSHOT
version=2.7.0-SNAPSHOT
release.useAutomaticVersion=true

nexusPlatformApiVersion=4.0.3-01
nexusPlatformApiVersion=4.0.7-01
ossIndexClientVersion=1.8.1
logbackVersion=1.2.11

junitVersion=4.13.2
powermockVersion=2.0.9
assertJVersion=3.23.1
commonsIoVersion=2.11.0
commonsIoVersion=2.15.1
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ public class NexusIqPluginScanExtension

private Map<String, String> variantAttributes;

private Set<String> scanTargets;

public NexusIqPluginScanExtension(Project project) {
stage = Stage.ID_BUILD;
organizationId = "";
Expand All @@ -68,6 +70,7 @@ public NexusIqPluginScanExtension(Project project) {
dirIncludes = "";
dirExcludes = "";
variantAttributes = Collections.emptyMap();
scanTargets = Collections.emptySet();
}

public String getUsername() {
Expand Down Expand Up @@ -190,4 +193,12 @@ public Map<String, String> getVariantAttributes() {
public void setVariantAttributes(Map<String, String> variantAttributes) {
this.variantAttributes = variantAttributes;
}

public Set<String> getScanTargets() {
return scanTargets;
}

public void setScanTargets(Set<String> scanTargets) {
this.scanTargets = scanTargets;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
import java.util.List;
import java.util.Properties;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import com.sonatype.insight.brain.client.PolicyAction;
import com.sonatype.insight.scan.module.model.Module;
Expand All @@ -42,6 +44,7 @@
import org.sonatype.gradle.plugins.scan.common.PluginVersionUtils;

import org.apache.commons.lang3.StringUtils;
import org.apache.tools.ant.DirectoryScanner;
import org.gradle.api.DefaultTask;
import org.gradle.api.GradleException;
import org.gradle.api.tasks.Input;
Expand All @@ -50,6 +53,8 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static java.util.Arrays.stream;

public class NexusIqScanTask
extends DefaultTask
{
Expand Down Expand Up @@ -108,7 +113,7 @@ public void scan() {
extension.getModulesExcluded(), extension.getVariantAttributes());

ScanResult scanResult = iqClient.scan(extension.getApplicationId(), proprietaryConfig, buildProperties(),
Collections.emptyList(), scanFolder, Collections.emptyMap(), Collections.emptySet(), modules);
buildScanTargets(), scanFolder, Collections.emptyMap(), Collections.emptySet(), modules);

File jsonResultsFile = null;
if (StringUtils.isNotBlank(extension.getResultFilePath())) {
Expand Down Expand Up @@ -166,6 +171,22 @@ private Properties buildProperties() {
return properties;
}

private List<File> buildScanTargets() {
if (extension.getScanTargets() != null && !extension.getScanTargets().isEmpty()) {
// Using the same approach as the Jenkins plugin for consistency
DirectoryScanner directoryScanner = new DirectoryScanner();
directoryScanner.setBasedir(extension.getScanFolderPath());
directoryScanner.setIncludes(extension.getScanTargets().toArray(new String[extension.getScanTargets().size()]));
directoryScanner.addDefaultExcludes();
directoryScanner.scan();
return Stream
.concat(stream(directoryScanner.getIncludedDirectories()), stream(directoryScanner.getIncludedFiles()))
.map(file -> new File(extension.getScanFolderPath(), file))
.collect(Collectors.toList());
}
return Collections.emptyList();
}

private void logReport(PolicyAction policyAction, ApplicationPolicyEvaluation applicationPolicyEvaluation) {
StringBuilder message = new StringBuilder();
for (PolicyAlert alert : applicationPolicyEvaluation.getPolicyAlerts()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@

import java.io.File;
import java.util.Collections;
import java.util.List;
import java.util.Properties;
import java.util.function.Consumer;

import com.sonatype.nexus.api.common.ServerConfig;
import com.sonatype.nexus.api.exception.IqClientException;
Expand All @@ -29,11 +31,14 @@

import org.sonatype.gradle.plugins.scan.common.DependenciesFinder;

import com.google.common.collect.Sets;
import org.gradle.api.GradleException;
import org.gradle.api.Project;
import org.gradle.testfixtures.ProjectBuilder;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
Expand Down Expand Up @@ -67,6 +72,9 @@ public class NexusIqScanTaskTest
private static final String USER_AGENT_REGEX =
"Sonatype_Nexus_Gradle/[^\\s]+ \\(Java [^;]+; [^;]+ [^;]+; Gradle [^;]+\\)";

@Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder();

@Mock
private InternalIqClient iqClientMock;

Expand Down Expand Up @@ -217,12 +225,44 @@ public void testScan_realWithDirExcludes() throws Exception {

}

@Test
@SuppressWarnings("unchecked")
public void testScan_realWithScanTargets() throws Exception {
File file1 = temporaryFolder.newFile("1.txt");
File file2 = temporaryFolder.newFile("2.lock");
temporaryFolder.newFolder("test");
File file3 = temporaryFolder.newFile("test" + File.separator + "3.lock");
File file4 = temporaryFolder.newFile("test" + File.separator + "4.lock");
temporaryFolder.newFile("file-not-scanned.log");

NexusIqScanTask task = buildScanTask(extension -> {
extension.setScanFolderPath(temporaryFolder.getRoot().getAbsolutePath());
extension.setScanTargets(Sets.newHashSet("1.txt", "**/*.lock", "file-not-exists.log"));
});

task.setDependenciesFinder(dependenciesFinderMock);
when(iqClientMock.verifyOrCreateApplication(eq(task.getApplicationId()))).thenReturn(true);

task.scan();

ArgumentCaptor<List<File>> captor = ArgumentCaptor.forClass(List.class);

verify(iqClientMock).scan(eq(task.getApplicationId()), nullable(ProprietaryConfig.class), any(Properties.class),
captor.capture(), any(File.class), anyMap(), anySet(), anyList());

assertThat(captor.getValue()).containsExactlyInAnyOrder(file1, file2, file3, file4);
}

private NexusIqScanTask buildScanTask(boolean isSimulated) {
return buildScanTask(isSimulated, null);
}

private NexusIqScanTask buildScanTask(boolean isSimulated, String resultFilePath) {
return buildScanTask(isSimulated, resultFilePath, "", "", "");
return buildScanTask(isSimulated, resultFilePath, "", "", "", null);
}

private NexusIqScanTask buildScanTask(Consumer<NexusIqPluginScanExtension> extenstionConsumer) {
return buildScanTask(false, null, "", "", "", extenstionConsumer);
}

private NexusIqScanTask buildScanTask(
Expand All @@ -231,6 +271,17 @@ private NexusIqScanTask buildScanTask(
String dirIncludes,
String dirExcludes,
String organizationId)
{
return buildScanTask(isSimulated, resultFilePath, dirIncludes, dirExcludes, organizationId, null);
}

private NexusIqScanTask buildScanTask(
boolean isSimulated,
String resultFilePath,
String dirIncludes,
String dirExcludes,
String organizationId,
Consumer<NexusIqPluginScanExtension> extenstionConsumer)
{
Project project = ProjectBuilder.builder().build();

Expand All @@ -245,6 +296,10 @@ private NexusIqScanTask buildScanTask(
extension.setDirIncludes(dirIncludes);
extension.setDirExcludes(dirExcludes);

if (extenstionConsumer != null) {
extenstionConsumer.accept(extension);
}

project.getExtensions().add("nexusIQScan", extension);
return project.getTasks().create("nexusIQScan", NexusIqScanTask.class);
}
Expand Down

0 comments on commit edb4449

Please sign in to comment.