Skip to content
Closed
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
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/
package org.sonar.plugins.javascript.bridge;

import javax.annotation.Nullable;
import org.sonar.api.SonarProduct;
import org.sonar.api.batch.sensor.SensorContext;
import org.sonar.api.config.Configuration;
Expand All @@ -29,13 +30,15 @@
public record BridgeServerConfig(
Configuration config,
String workDirAbsolutePath,
SonarProduct product
SonarProduct product,
@Nullable Integer existingNodeProcessPort
) {
public static BridgeServerConfig fromSensorContext(SensorContext context) {
return new BridgeServerConfig(
context.config(),
context.fileSystem().workDir().getAbsolutePath(),
context.runtime().getProduct()
context.runtime().getProduct(),
null
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,9 @@ private enum Status {
*/
private boolean ownsNodeProcess;

@Nullable
private Integer existingNodeProcessPortOverride;

// Used by pico container for dependency injection
public BridgeServerImpl(
NodeCommandBuilder nodeCommandBuilder,
Expand Down Expand Up @@ -396,6 +399,7 @@ static Integer extractStartupPort(String message) {

@Override
public void startServerLazily(BridgeServerConfig serverConfig) throws IOException {
existingNodeProcessPortOverride = serverConfig.existingNodeProcessPort();
if (status == Status.FAILED) {
if (shouldRestartFailedServer()) {
// Reset the status, which will cause the server to retry deployment
Expand All @@ -414,6 +418,11 @@ public void startServerLazily(BridgeServerConfig serverConfig) throws IOExceptio
if (!waitChannelReady(timeoutSeconds * 1000)) {
status = Status.FAILED;
closeChannel();
if (existingNodeProcessPortOverride != null) {
throw new IllegalStateException(
"Could not connect to existing Node.js process on " + hostAddress + ":" + port
);
}
throw new ServerAlreadyFailedException();
}
serverHasStarted();
Expand Down Expand Up @@ -812,7 +821,9 @@ private AnalyzeProjectServiceGrpc.AnalyzeProjectServiceStub asyncAnalyzeProjectS
}

public String getExistingNodeProcessPort() {
return System.getenv(SONARJS_EXISTING_NODE_PROCESS_PORT);
return existingNodeProcessPortOverride != null
? String.valueOf(existingNodeProcessPortOverride)
: System.getenv(SONARJS_EXISTING_NODE_PROCESS_PORT);
}
Comment thread
gitar-bot[bot] marked this conversation as resolved.

static class LogOutputConsumer implements Consumer<String> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,30 @@ void test_use_existing_node_should_start_local_process_when_port_is_zero() throw
verify(bridgeServerMock).startServer(serverConfig);
}

@Test
void test_getExistingNodeProcessPort_returns_config_value_when_set() throws IOException {
// The override is assigned at the top of startServerLazily, before any connection attempt,
// so getExistingNodeProcessPort() reflects the config value even after the expected throw.
bridgeServer = createUnitBridgeServer(1);
var configWithPort = new BridgeServerConfig(
serverConfig.config(),
serverConfig.workDirAbsolutePath(),
serverConfig.product(),
12345
);
assertThatThrownBy(() -> bridgeServer.startServerLazily(configWithPort))
.isInstanceOf(IllegalStateException.class)
.hasMessageContaining("12345");
assertThat(bridgeServer.getExistingNodeProcessPort()).isEqualTo("12345");
}

@Test
void test_getExistingNodeProcessPort_falls_back_to_env_var_when_config_null() {
bridgeServer = createUnitBridgeServer();
assertThat(bridgeServer.getExistingNodeProcessPort())
.isEqualTo(System.getenv(BridgeServerImpl.SONARJS_EXISTING_NODE_PROCESS_PORT));
}

@Test
void isAlive_should_not_require_a_lease_for_an_existing_node_process() throws Exception {
bridgeServer = createUnitBridgeServer();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import java.io.UncheckedIOException;
import java.nio.file.Path;
import java.util.Optional;
import javax.annotation.Nullable;
import org.sonar.api.SonarProduct;
import org.sonar.plugins.javascript.analyzeproject.grpc.AnalyzeProjectRequest;
import org.sonar.plugins.javascript.analyzeproject.grpc.AnalyzeProjectUnaryResponse;
Expand Down Expand Up @@ -91,7 +92,8 @@ private StandaloneParser(Builder builder) {
new BridgeServerConfig(
builder.configuration,
temporaryFolder.newDir().getAbsolutePath(),
SonarProduct.SONARLINT
SonarProduct.SONARLINT,
builder.existingNodeProcessPort
)
);
} catch (IOException e) {
Expand All @@ -110,6 +112,9 @@ public static class Builder {
private org.sonar.api.config.Configuration configuration = new EmptyConfiguration();
private String[] nodeJsArgs;

@Nullable
private Integer existingNodeProcessPort;

private Builder() {}

public Builder timeout(int timeout) {
Expand All @@ -132,6 +137,17 @@ public Builder nodeJsArgs(String... nodeJsArgs) {
return this;
}

public Builder existingNodeProcessPort(int existingNodeProcessPort) {
if (existingNodeProcessPort < 1 || existingNodeProcessPort > 65535) {
throw new IllegalArgumentException(
"existingNodeProcessPort should be a number between 1 and 65535, got " +
existingNodeProcessPort
);
}
this.existingNodeProcessPort = existingNodeProcessPort;
return this;
}

public StandaloneParser build() {
return new StandaloneParser(this);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.sonar.plugins.javascript.api.estree.ESTree.Program;


import java.util.List;
import java.util.stream.Stream;
import org.junit.jupiter.api.AfterAll;
Expand Down Expand Up @@ -101,6 +102,24 @@ void test_standalone_created_with_builder() {
}
}

@Test
void test_existing_node_port_out_of_range_throws() {
assertThatThrownBy(() ->
StandaloneParser.builder().existingNodeProcessPort(70000)
)
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("between 1 and 65535");
}

@Test
void test_existing_node_port_zero_throws() {
assertThatThrownBy(() ->
StandaloneParser.builder().existingNodeProcessPort(0)
)
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("between 1 and 65535");
}

@Test
void should_parse_ts_empty_body_function_expression() {
ESTree.MethodDefinitionOrPropertyDefinitionOrStaticBlock actual = parseClassAndReturnNode(
Expand Down