Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ repositories {
}
}

def buildInfoVersion = '2.43.6'
def buildInfoVersion = '2.43.x-SNAPSHOT'
// Updated to 2.17.3 for security fixes - compatible with Java 8+
def jacksonVersion = '2.17.3'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.jfrog.ide.common.updateversion.ComponentUpdater;
import org.jfrog.build.api.util.Log;
import org.jfrog.build.extractor.go.GoDriver;
import org.jfrog.build.extractor.WslUtils;

import java.io.IOException;
import java.nio.file.Path;
Expand All @@ -19,7 +20,7 @@ public class GoComponentUpdater extends ComponentUpdater {

public GoComponentUpdater(Path projectDir, Log logger, Map<String, String> env, String executablePath) {
super(projectDir, logger);
this.goDriver = new GoDriver(executablePath, env, projectDir.toFile(), logger);
this.goDriver = new GoDriver(executablePath, env, projectDir.toFile(), logger, WslUtils.isWslPath(projectDir));
}

/**
Expand Down
23 changes: 20 additions & 3 deletions src/main/java/com/jfrog/ide/common/go/GoScanWorkspaceCreator.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,17 @@
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.jfrog.build.api.util.Log;
import org.jfrog.build.extractor.go.GoDriver;
import org.jfrog.build.extractor.WslUtils;

import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.FileVisitor;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;

Expand All @@ -27,13 +31,16 @@ public class GoScanWorkspaceCreator implements FileVisitor<Path> {
private final Path sourceDir;
private final Path targetDir;
private final Log logger;
private final boolean runGoThroughWsl;
private static final String[] EXCLUDED_DIRS = new String[]{".git", ".idea", ".vscode"};

public GoScanWorkspaceCreator(String executablePath, Path sourceDir, Path targetDir, Path goModAbsDir, Map<String, String> env, Log logger) {
this.goDriver = new GoDriver(executablePath, env, goModAbsDir.toFile(), logger);
public GoScanWorkspaceCreator(String executablePath, Path sourceDir, Path targetDir, Path goModAbsDir,
Map<String, String> env, Log logger, boolean runGoThroughWsl) {
this.goDriver = new GoDriver(executablePath, env, goModAbsDir.toFile(), logger, runGoThroughWsl);
this.sourceDir = sourceDir;
this.targetDir = targetDir;
this.logger = logger;
this.runGoThroughWsl = runGoThroughWsl;
}

@Override
Expand Down Expand Up @@ -73,7 +80,17 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IO
if (fileName.equals("go.mod")) {
Path targetGoMod = targetDir.resolve(sourceDir.relativize(file));
Files.copy(file, targetGoMod);
goDriver.runCmd("run . -goModPath=" + targetGoMod.toAbsolutePath() + " -wd=" + sourceDir.toAbsolutePath(), true);
if (runGoThroughWsl) {
String goModPathArg = WslUtils.windowsLocalPathToWslMount(targetGoMod.toAbsolutePath().toString());
String sourceAbs = sourceDir.toAbsolutePath().toString();
String wdArg = WslUtils.isWslPath(sourceAbs)
? WslUtils.toLinuxPath(sourceAbs)
: WslUtils.windowsLocalPathToWslMount(sourceAbs);
List<String> args = new ArrayList<>(Arrays.asList("run", ".", "-goModPath=" + goModPathArg, "-wd=" + wdArg));
goDriver.runCmd(args, true);
} else {
goDriver.runCmd("run . -goModPath=" + targetGoMod.toAbsolutePath() + " -wd=" + sourceDir.toAbsolutePath(), true);
}
return FileVisitResult.CONTINUE;
}
// Files other than go.mod and *.go files are not necessary to build the dependency tree of used Go packages.
Expand Down
9 changes: 6 additions & 3 deletions src/main/java/com/jfrog/ide/common/go/GoTreeBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.jfrog.build.client.Version;
import org.jfrog.build.extractor.executor.CommandResults;
import org.jfrog.build.extractor.go.GoDriver;
import org.jfrog.build.extractor.WslUtils;

import java.io.*;
import java.nio.file.Files;
Expand Down Expand Up @@ -126,7 +127,8 @@ private Path createGoWorkspace() throws IOException {
Path goModAbsDir = null;
try {
goModAbsDir = prepareGoModAbs();
GoScanWorkspaceCreator goScanWorkspaceCreator = new GoScanWorkspaceCreator(executablePath, projectDir, targetDir, goModAbsDir, env, logger);
boolean runGoThroughWsl = WslUtils.isWslPath(projectDir);
GoScanWorkspaceCreator goScanWorkspaceCreator = new GoScanWorkspaceCreator(executablePath, projectDir, targetDir, goModAbsDir, env, logger, runGoThroughWsl);
Files.walkFileTree(projectDir, goScanWorkspaceCreator);
} finally {
if (goModAbsDir != null) {
Expand Down Expand Up @@ -176,9 +178,10 @@ private static void populateChildren(DepTree depTree, String[] dependenciesGraph
public DepTree buildTree() throws IOException {
File tmpDir = createGoWorkspace().toFile();
try {
GoDriver goDriver = new GoDriver(executablePath, env, tmpDir, logger);
boolean runGoThroughWsl = WslUtils.isWslPath(projectDir);
GoDriver goDriver = new GoDriver(executablePath, env, tmpDir, logger, runGoThroughWsl);
if (!goDriver.isInstalled()) {
throw new IOException("Could not scan the Go project dependencies, because the Go executable is not in the PATH.");
throw new IOException("Could not scan the Go project dependencies, because the Go executable is not in the PATH. [WSL=" + runGoThroughWsl + "]");
}

CommandResults versionRes = goDriver.version(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@

public enum SourceCodeScanType {
CONTEXTUAL("analyze-applicability"),
SECRETS("JFrog Secrets scanner"),
IAC("JFrog Terraform scanner"),
SAST("JFrog SAST"),
SECRETS("secrets-scan"),
IAC("iac-scan-modules"),
SAST("sast"),
SCA("JFrog Xray Scanner");

private final String scannerName;
Expand Down
57 changes: 55 additions & 2 deletions src/main/java/com/jfrog/ide/common/npm/NpmComponentUpdater.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
package com.jfrog.ide.common.npm;

import com.jfrog.ide.common.updateversion.ComponentUpdater;
import org.jfrog.build.extractor.WslUtils;
import org.apache.commons.lang3.StringUtils;
import org.jfrog.build.api.util.Log;
import org.jfrog.build.extractor.executor.CommandExecutor;
import org.jfrog.build.extractor.executor.CommandResults;
import org.jfrog.build.extractor.npm.NpmDriver;

import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
Expand All @@ -19,10 +25,33 @@ public class NpmComponentUpdater extends ComponentUpdater {

public static final String NPM_VERSION_DELIMITER = "@";
private final NpmDriver npmDriver;
private final CommandExecutor wslExecutor;
private final boolean isWsl;

public NpmComponentUpdater(Path projectDir, Log logger, Map<String, String> env) {
super(projectDir, logger);
this.npmDriver = new NpmDriver(env);
this.isWsl = WslUtils.isWslPath(projectDir);
if (isWsl) {
this.npmDriver = null;
this.wslExecutor = new CommandExecutor("wsl.exe", env);
} else {
this.npmDriver = new NpmDriver(env);
this.wslExecutor = null;
}
}

/**
* Prefix arguments for {@code wsl.exe} so npm runs in the project directory inside WSL
* (aligned with {@link NpmTreeBuilder}).
*/
private List<String> wslNpmInvocationPrefix() {
String linuxPath = WslUtils.toLinuxPath(projectDir.toString());
List<String> args = new ArrayList<>();
args.add("--cd");
args.add(linuxPath);
args.add("--exec");
args.add("npm");
return args;
}

/**
Expand All @@ -35,7 +64,21 @@ public NpmComponentUpdater(Path projectDir, Log logger, Map<String, String> env)
@Override
public void run(String componentName, String componentVersion) throws IOException {
super.run(componentName, componentVersion);
npmDriver.install(projectDir.toFile(), Collections.singletonList(this.componentFullName), this.logger);
if (isWsl) {
List<String> args = new ArrayList<>(wslNpmInvocationPrefix());
args.add("install");
args.add(this.componentFullName);
try {
CommandResults res = wslExecutor.exeCommand(null, args, null, logger);
if (!res.isOk()) {
throw new IOException(StringUtils.defaultString(res.getErr()) + StringUtils.defaultString(res.getRes()));
}
} catch (IOException | InterruptedException e) {
throw new IOException("npm install failed via WSL", e);
}
} else {
npmDriver.install(projectDir.toFile(), Collections.singletonList(this.componentFullName), this.logger);
}
}

@Override
Expand All @@ -45,6 +88,16 @@ public String getVersionDelimiter() {

@Override
public boolean isDriverInstalled() {
if (isWsl) {
try {
List<String> args = new ArrayList<>(wslNpmInvocationPrefix());
args.add("--version");
CommandResults results = wslExecutor.exeCommand(null, args, null, null);
return results.isOk() && !StringUtils.isBlank(results.getRes());
} catch (Exception e) {
return false;
}
}
return npmDriver.isNpmInstalled();
}

Expand Down
86 changes: 81 additions & 5 deletions src/main/java/com/jfrog/ide/common/npm/NpmTreeBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,24 @@

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectReader;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.collect.Lists;
import com.jfrog.ide.common.deptree.DepTree;
import com.jfrog.ide.common.deptree.DepTreeNode;
import com.jfrog.ide.common.utils.Utils;
import org.jfrog.build.extractor.WslUtils;
import org.apache.commons.lang3.StringUtils;
import org.jfrog.build.api.util.Log;
import org.jfrog.build.extractor.executor.CommandExecutor;
import org.jfrog.build.extractor.executor.CommandResults;
import org.jfrog.build.extractor.npm.NpmDriver;

import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
Expand All @@ -21,14 +29,24 @@
*/
public class NpmTreeBuilder {
private static final ObjectMapper objectMapper = new ObjectMapper();
private static final ObjectReader jsonReader = objectMapper.reader();
private final NpmDriver npmDriver;
private final CommandExecutor wslExecutor;
private final boolean isWsl;
private final Path projectDir;
private final String descriptorFilePath;

public NpmTreeBuilder(Path projectDir, String descriptorFilePath, Map<String, String> env) {
this.projectDir = projectDir;
this.descriptorFilePath = descriptorFilePath;
this.npmDriver = new NpmDriver(env);
this.isWsl = WslUtils.isWslPath(projectDir);
if (isWsl) {
this.npmDriver = null;
this.wslExecutor = new CommandExecutor("wsl.exe", env);
} else {
this.npmDriver = new NpmDriver(env);
this.wslExecutor = null;
}
}

/**
Expand All @@ -39,15 +57,15 @@ public NpmTreeBuilder(Path projectDir, String descriptorFilePath, Map<String, St
* @throws IOException in case of I/O error.
*/
public DepTree buildTree(Log logger) throws IOException {
if (!npmDriver.isNpmInstalled()) {
throw new IOException("Could not scan npm project dependencies, because npm CLI is not in the PATH.");
if (!isNpmInstalled()) {
throw new IOException("Could not scan npm project dependencies, because npm CLI is not in the PATH. [WSL=" + this.isWsl + "]");
}
JsonNode prodResults = npmDriver.list(projectDir.toFile(), Lists.newArrayList("--prod", "--package-lock-only"));
JsonNode prodResults = npmList(Lists.newArrayList("--prod", "--package-lock-only"));
if (prodResults.get("problems") != null) {
logger.warn("Errors occurred during building the Npm dependency tree. " +
"The dependency tree may be incomplete:\n" + prodResults.get("problems").toString());
}
JsonNode devResults = npmDriver.list(projectDir.toFile(), Lists.newArrayList("--dev", "--package-lock-only"));
JsonNode devResults = npmList(Lists.newArrayList("--dev", "--package-lock-only"));
Map<String, DepTreeNode> nodes = new HashMap<>();
String packageId = getPackageId(prodResults);
addDepTreeNodes(nodes, prodResults, packageId, "prod");
Expand All @@ -57,6 +75,64 @@ public DepTree buildTree(Log logger) throws IOException {
return tree;
}

/**
* Check whether npm is available, accounting for WSL projects.
* For WSL projects, npm is invoked through {@code wsl.exe}.
*/
private boolean isNpmInstalled() {
if (isWsl) {
try {
List<String> args = wslNpmInvocationPrefix();
args.add("--version");
CommandResults results = wslExecutor.exeCommand(null, args, null, null);
return results.isOk() && !StringUtils.isBlank(results.getRes());
} catch (Exception e) {
return false;
}
}
return npmDriver.isNpmInstalled();
}

/**
* Prefix arguments for {@code wsl.exe} so npm runs in the project directory inside WSL
* (same {@code --cd} context as {@link #npmList}).
*/
private List<String> wslNpmInvocationPrefix() {
String linuxPath = WslUtils.toLinuxPath(projectDir.toString());
List<String> args = new ArrayList<>();
args.add("--cd");
args.add(linuxPath);
args.add("--exec");
args.add("npm");
return args;
}

/**
* Run {@code npm ls} and return the parsed JSON output.
* For WSL projects, the command is routed through {@code wsl.exe --cd <linux-path> --exec npm ...}.
*/
private JsonNode npmList(List<String> extraArgs) throws IOException {
if (isWsl) {
List<String> args = new ArrayList<>(wslNpmInvocationPrefix());
args.add("ls");
args.add("--json");
args.add("--all");
args.addAll(extraArgs);
try {
CommandResults commandRes = wslExecutor.exeCommand(null, args, null, null);
String res = StringUtils.isBlank(commandRes.getRes()) ? "{}" : commandRes.getRes();
JsonNode results = jsonReader.readTree(res);
if (!commandRes.isOk() && !results.has("problems") && results.isObject()) {
((ObjectNode) results).put("problems", commandRes.getErr());
}
return results;
} catch (IOException | InterruptedException e) {
throw new IOException("npm ls failed via WSL", e);
}
}
return npmDriver.list(projectDir.toFile(), extraArgs);
}

private void addDepTreeNodes(Map<String, DepTreeNode> nodes, JsonNode jsonDep, String depId, String scope) {
DepTreeNode depNode;
if (nodes.containsKey(depId)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.jfrog.ide.common.yarn;

import com.jfrog.ide.common.updateversion.ComponentUpdater;
import org.jfrog.build.extractor.WslUtils;
import org.jfrog.build.api.util.Log;

import java.io.IOException;
Expand All @@ -14,7 +15,7 @@ public class YarnComponentUpdater extends ComponentUpdater {

public YarnComponentUpdater(Path projectDir, Log logger, Map<String, String> env) {
super(projectDir, logger);
this.yarnDriver = new YarnDriver(env);
this.yarnDriver = new YarnDriver(env, logger, WslUtils.isWslPath(projectDir));
}

/**
Expand All @@ -37,7 +38,7 @@ public String getVersionDelimiter() {

@Override
public boolean isDriverInstalled() {
return yarnDriver.isYarnInstalled();
return yarnDriver.isYarnInstalled(projectDir.toFile());
}

@Override
Expand Down
Loading
Loading