From 1565e6d1969aaec0cad7eec970c2228d095d2a07 Mon Sep 17 00:00:00 2001 From: Jordan Hury Date: Tue, 16 Jun 2026 16:51:06 +0300 Subject: [PATCH 1/4] Fix GlobalSettings NPE when JFrog CLI is not on PATH After ide-plugins-common 2.4.x, JfrogCliDriver's second constructor arg is Log, not CLI path. Passing null caused NPE in isJfrogCliInstalled() on Windows where jf is often missing from PATH. Co-authored-by: Cursor --- .../com/jfrog/ide/idea/configuration/ServerConfigImpl.java | 3 ++- .../ide/idea/configuration/ConnectionDetailsFromCliTest.java | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/jfrog/ide/idea/configuration/ServerConfigImpl.java b/src/main/java/com/jfrog/ide/idea/configuration/ServerConfigImpl.java index 80ca2a43..9f977917 100644 --- a/src/main/java/com/jfrog/ide/idea/configuration/ServerConfigImpl.java +++ b/src/main/java/com/jfrog/ide/idea/configuration/ServerConfigImpl.java @@ -34,6 +34,7 @@ import com.jfrog.ide.idea.ui.configuration.ConnectionTimeoutSpinner; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.Strings; +import org.jfrog.build.api.util.NullLog; import org.jfrog.build.client.ProxyConfiguration; import javax.annotation.CheckForNull; @@ -498,7 +499,7 @@ public void readMissingConfFromEnv() { * @return true if connection details loaded from JFrog CLI default server. */ public boolean readConnectionDetailsFromJfrogCli() throws IOException { - JfrogCliDriver driver = new JfrogCliDriver(new HashMap<>(EnvironmentUtil.getEnvironmentMap()), null); + JfrogCliDriver driver = new JfrogCliDriver(new HashMap<>(EnvironmentUtil.getEnvironmentMap()), new NullLog()); if (!driver.isJfrogCliInstalled()) { return false; } diff --git a/src/test/java/com/jfrog/ide/idea/configuration/ConnectionDetailsFromCliTest.java b/src/test/java/com/jfrog/ide/idea/configuration/ConnectionDetailsFromCliTest.java index 429ecd8a..39700d75 100644 --- a/src/test/java/com/jfrog/ide/idea/configuration/ConnectionDetailsFromCliTest.java +++ b/src/test/java/com/jfrog/ide/idea/configuration/ConnectionDetailsFromCliTest.java @@ -2,6 +2,7 @@ import com.intellij.util.EnvironmentUtil; import com.jfrog.ide.common.configuration.JfrogCliDriver; +import org.jfrog.build.api.util.NullLog; import org.apache.commons.io.FileUtils; import org.gradle.internal.impldep.org.junit.Assert; import org.junit.Test; @@ -71,7 +72,7 @@ public void testReadConnectionDetailsFromJfrogCli() throws IOException, Interrup // Config JFrog CLI if (cliParameters != null) { - JfrogCliDriver jfrogCliDriver = new JfrogCliDriver(envVars, null); + JfrogCliDriver jfrogCliDriver = new JfrogCliDriver(envVars, new NullLog()); jfrogCliDriver.runCommand(null, envVars, cliParameters, new ArrayList<>(), null, null); } From 7f6d5bfff7a38ab66309ea4a8020dafb486a3120 Mon Sep 17 00:00:00 2001 From: Jordan Hury Date: Wed, 17 Jun 2026 10:35:48 +0300 Subject: [PATCH 2/4] Add regression test for CLI-not-on-PATH NPE (XRAY-145646) Simulates missing jf by pointing PATH at an empty directory so isJfrogCliInstalled() exercises the log path without mutating the host env. Co-authored-by: Cursor --- .../idea/configuration/ConfigurationTest.java | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/test/java/com/jfrog/ide/idea/configuration/ConfigurationTest.java b/src/test/java/com/jfrog/ide/idea/configuration/ConfigurationTest.java index 96de4cf6..2aa4b801 100644 --- a/src/test/java/com/jfrog/ide/idea/configuration/ConfigurationTest.java +++ b/src/test/java/com/jfrog/ide/idea/configuration/ConfigurationTest.java @@ -3,9 +3,16 @@ import com.intellij.credentialStore.Credentials; import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase; import com.intellij.util.EnvironmentUtil; +import org.apache.commons.io.FileUtils; import org.mockito.MockedStatic; import org.mockito.Mockito; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.HashMap; +import java.util.Map; + import static com.jfrog.ide.idea.configuration.ServerConfigImpl.*; /** @@ -166,6 +173,22 @@ public void testReadMissingConfFromEnv() { } } + /** + * XRAY-145646: when jf is not on PATH, isJfrogCliInstalled() logs the failure and must not NPE. + */ + public void testReadConnectionDetailsFromJfrogCliWhenCliNotInstalled() throws IOException { + Path emptyPath = Files.createTempDirectory("noJfrogCliOnPath"); + try (MockedStatic mockController = Mockito.mockStatic(EnvironmentUtil.class)) { + Map envVars = new HashMap<>(System.getenv()); + envVars.put("PATH", emptyPath.toAbsolutePath().toString()); + mockController.when(EnvironmentUtil::getEnvironmentMap).thenReturn(envVars); + + assertFalse(new ServerConfigImpl().readConnectionDetailsFromJfrogCli()); + } finally { + FileUtils.forceDelete(emptyPath.toFile()); + } + } + /** * Create server config for the tests. * From a3b8f8c40bfda6c6d4a030804a18aae98c312706 Mon Sep 17 00:00:00 2001 From: Jordan Hury Date: Wed, 17 Jun 2026 10:47:06 +0300 Subject: [PATCH 3/4] Fix CLI-not-installed test for Unix CI runners CommandExecutor merges System.getenv() and appends /usr/local/bin on Unix, so PATH isolation cannot reliably hide jf on macOS/ubuntu CI. Use mockConstruction instead and assert JfrogCliDriver receives a non-null Log. Co-authored-by: Cursor --- .../idea/configuration/ConfigurationTest.java | 28 +++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/src/test/java/com/jfrog/ide/idea/configuration/ConfigurationTest.java b/src/test/java/com/jfrog/ide/idea/configuration/ConfigurationTest.java index 2aa4b801..b0f91d46 100644 --- a/src/test/java/com/jfrog/ide/idea/configuration/ConfigurationTest.java +++ b/src/test/java/com/jfrog/ide/idea/configuration/ConfigurationTest.java @@ -3,13 +3,13 @@ import com.intellij.credentialStore.Credentials; import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase; import com.intellij.util.EnvironmentUtil; -import org.apache.commons.io.FileUtils; +import com.jfrog.ide.common.configuration.JfrogCliDriver; +import org.jfrog.build.api.util.Log; +import org.mockito.MockedConstruction; import org.mockito.MockedStatic; import org.mockito.Mockito; import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; import java.util.HashMap; import java.util.Map; @@ -174,18 +174,24 @@ public void testReadMissingConfFromEnv() { } /** - * XRAY-145646: when jf is not on PATH, isJfrogCliInstalled() logs the failure and must not NPE. + * XRAY-145646: when jf is not installed, readConnectionDetailsFromJfrogCli must return false + * without NPE. NullLog must be passed to JfrogCliDriver (regression: null log NPEs in + * isJfrogCliInstalled). mockConstruction is used because CommandExecutor merges + * System.getenv() and appends /usr/local/bin on Unix, so PATH isolation is unreliable in CI. */ public void testReadConnectionDetailsFromJfrogCliWhenCliNotInstalled() throws IOException { - Path emptyPath = Files.createTempDirectory("noJfrogCliOnPath"); - try (MockedStatic mockController = Mockito.mockStatic(EnvironmentUtil.class)) { - Map envVars = new HashMap<>(System.getenv()); - envVars.put("PATH", emptyPath.toAbsolutePath().toString()); - mockController.when(EnvironmentUtil::getEnvironmentMap).thenReturn(envVars); + try (MockedStatic mockController = Mockito.mockStatic(EnvironmentUtil.class); + MockedConstruction driverConstruction = Mockito.mockConstruction( + JfrogCliDriver.class, + (mock, context) -> { + assertNotNull(context.arguments().get(1)); + assertTrue(context.arguments().get(1) instanceof Log); + Mockito.when(mock.isJfrogCliInstalled()).thenReturn(false); + })) { + mockController.when(EnvironmentUtil::getEnvironmentMap).thenReturn(new HashMap<>()); assertFalse(new ServerConfigImpl().readConnectionDetailsFromJfrogCli()); - } finally { - FileUtils.forceDelete(emptyPath.toFile()); + assertEquals(1, driverConstruction.constructed().size()); } } From 540a956234e5ac42a6aa8d35b816f4d93dc18924 Mon Sep 17 00:00:00 2001 From: Jordan Hury Date: Wed, 17 Jun 2026 11:34:38 +0300 Subject: [PATCH 4/4] Shorten XRAY-145646 test docstring Co-authored-by: Cursor --- .../jfrog/ide/idea/configuration/ConfigurationTest.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/test/java/com/jfrog/ide/idea/configuration/ConfigurationTest.java b/src/test/java/com/jfrog/ide/idea/configuration/ConfigurationTest.java index b0f91d46..69b9f296 100644 --- a/src/test/java/com/jfrog/ide/idea/configuration/ConfigurationTest.java +++ b/src/test/java/com/jfrog/ide/idea/configuration/ConfigurationTest.java @@ -173,12 +173,7 @@ public void testReadMissingConfFromEnv() { } } - /** - * XRAY-145646: when jf is not installed, readConnectionDetailsFromJfrogCli must return false - * without NPE. NullLog must be passed to JfrogCliDriver (regression: null log NPEs in - * isJfrogCliInstalled). mockConstruction is used because CommandExecutor merges - * System.getenv() and appends /usr/local/bin on Unix, so PATH isolation is unreliable in CI. - */ + /** XRAY-145646: CLI not installed must return false without NPE when Log is null-safe. */ public void testReadConnectionDetailsFromJfrogCliWhenCliNotInstalled() throws IOException { try (MockedStatic mockController = Mockito.mockStatic(EnvironmentUtil.class); MockedConstruction driverConstruction = Mockito.mockConstruction(