Skip to content

Commit

Permalink
JS-471 SonarLint can configure persistent bundle path (#4980)
Browse files Browse the repository at this point in the history
Co-authored-by: Victor Diez <[email protected]>
  • Loading branch information
zglicz and vdiez authored Dec 3, 2024
1 parent 13066ab commit 5242c58
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ private enum Status {
private static final String MAX_OLD_SPACE_SIZE_PROPERTY = "sonar.javascript.node.maxspace";
private static final String ALLOW_TS_PARSER_JS_FILES = "sonar.javascript.allowTsParserJsFiles";
private static final String DEBUG_MEMORY = "sonar.javascript.node.debugMemory";
public static final String SONARLINT_BUNDLE_PATH = "sonar.js.internal.bundlePath";
public static final String SONARJS_EXISTING_NODE_PROCESS_PORT =
"SONARJS_EXISTING_NODE_PROCESS_PORT";
private static final Gson GSON = new Gson();
Expand Down Expand Up @@ -181,7 +182,12 @@ int getTimeoutSeconds() {
* @throws IOException
*/
void deploy(Configuration configuration) throws IOException {
bundle.deploy(temporaryDeployLocation);
var bundlePath = configuration.get(SONARLINT_BUNDLE_PATH);
if (bundlePath.isPresent()) {
bundle.setDeployLocation(Path.of(bundlePath.get()));
} else {
bundle.deploy(temporaryDeployLocation);
}
if (configuration.get(NODE_EXECUTABLE_PROPERTY).isPresent() ||
configuration.getBoolean(SKIP_NODE_PROVISIONING_PROPERTY).orElse(false) ||
configuration.getBoolean(NODE_FORCE_HOST_PROPERTY).orElse(false)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
import java.nio.file.Path;
import org.sonar.plugins.javascript.nodejs.BundlePathResolver;

interface Bundle extends BundlePathResolver {
public interface Bundle extends BundlePathResolver {
void setDeployLocation(Path deployLocation);
void deploy(Path deployLocation) throws IOException;

String startServerScript();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public class BundleImpl implements Bundle {

// this archive is created in the bridge module
private static final String BUNDLE_LOCATION = "/sonarjs-1.0.0.tgz";
private static final String DEFAULT_STARTUP_SCRIPT = "package/bin/server.cjs";
public static final String DEFAULT_STARTUP_SCRIPT = "package/bin/server.cjs";
private Path deployLocation;
private final String bundleLocation;

Expand All @@ -46,6 +46,12 @@ public BundleImpl() {
this.bundleLocation = bundleLocation;
}

@Override
public void setDeployLocation(Path deployLocation) {
LOG.debug("Setting deploy location to {}", deployLocation);
this.deployLocation = deployLocation;
}

@Override
public void deploy(Path deployLocation) throws IOException {
LOG.debug("Deploying the bridge server into {}", deployLocation);
Expand All @@ -54,7 +60,7 @@ public void deploy(Path deployLocation) throws IOException {
throw new IllegalStateException("The bridge server was not found in the plugin jar");
}
BundleUtils.extractFromClasspath(bundle, deployLocation);
this.deployLocation = deployLocation;
setDeployLocation(deployLocation);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,24 @@
*/
package org.sonar.plugins.javascript.bridge;

import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.awaitility.Awaitility.await;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import static org.slf4j.event.Level.DEBUG;
import static org.slf4j.event.Level.ERROR;
import static org.slf4j.event.Level.INFO;
import static org.slf4j.event.Level.WARN;
import static org.sonar.plugins.javascript.bridge.AnalysisMode.DEFAULT_LINTER_ID;
import static org.sonar.plugins.javascript.nodejs.NodeCommandBuilderImpl.NODE_EXECUTABLE_PROPERTY;
import static org.sonar.plugins.javascript.nodejs.NodeCommandBuilderImpl.NODE_FORCE_HOST_PROPERTY;
import static org.sonar.plugins.javascript.nodejs.NodeCommandBuilderImpl.SKIP_NODE_PROVISIONING_PROPERTY;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
Expand Down Expand Up @@ -54,24 +72,6 @@
import org.sonar.plugins.javascript.nodejs.ProcessWrapper;
import org.sonar.plugins.javascript.nodejs.ProcessWrapperImpl;

import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.awaitility.Awaitility.await;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import static org.slf4j.event.Level.DEBUG;
import static org.slf4j.event.Level.ERROR;
import static org.slf4j.event.Level.INFO;
import static org.slf4j.event.Level.WARN;
import static org.sonar.plugins.javascript.bridge.AnalysisMode.DEFAULT_LINTER_ID;
import static org.sonar.plugins.javascript.nodejs.NodeCommandBuilderImpl.NODE_EXECUTABLE_PROPERTY;
import static org.sonar.plugins.javascript.nodejs.NodeCommandBuilderImpl.NODE_FORCE_HOST_PROPERTY;
import static org.sonar.plugins.javascript.nodejs.NodeCommandBuilderImpl.SKIP_NODE_PROVISIONING_PROPERTY;

class BridgeServerImplTest {

private static final String START_SERVER_SCRIPT = "startServer.js";
Expand Down Expand Up @@ -827,18 +827,47 @@ void should_not_deploy_runtime_if_node_force_host_is_set() throws Exception {
);
}

private BridgeServerImpl createBridgeServer(String startServerScript) {
@Test
void should_start_bridge_from_path() throws IOException {
bridgeServer = createBridgeServer(new BundleImpl());
var deployLocation = "src/test/resources";
var settings = new MapSettings().setProperty(BridgeServerImpl.SONARLINT_BUNDLE_PATH, deployLocation);
context.setSettings(settings);

var config = BridgeServerConfig.fromSensorContext(context);
bridgeServer.startServerLazily(config);
assertThat(logTester.logs(DEBUG))
.contains("Setting deploy location to " + deployLocation.replace("/", File.separator));
}

@Test
void should_fail_on_bad_bridge_path() {
bridgeServer = createBridgeServer(new BundleImpl());
var deployLocation = "src/test";
var settings = new MapSettings().setProperty(BridgeServerImpl.SONARLINT_BUNDLE_PATH, deployLocation);
context.setSettings(settings);

var config = BridgeServerConfig.fromSensorContext(context);
assertThatThrownBy(() -> bridgeServer.startServerLazily(config))
.isInstanceOf(NodeCommandException.class);
}

private BridgeServerImpl createBridgeServer(Bundle bundle) {
return new BridgeServerImpl(
builder(),
TEST_TIMEOUT_SECONDS,
new TestBundle(startServerScript),
bundle,
emptyRulesBundles,
deprecationWarning,
tempFolder,
unsupportedEmbeddedRuntime
);
}

private BridgeServerImpl createBridgeServer(String startServerScript) {
return createBridgeServer(new TestBundle(startServerScript));
}

/**
* Mock used to bypass the embedded node deployment
*/
Expand All @@ -858,6 +887,11 @@ static class TestBundle implements Bundle {
this.startServerScript = startServerScript;
}

@Override
public void setDeployLocation(Path deployLocation) {
// no-op for unit test
}

@Override
public void deploy(Path deployLocation) {
// no-op for unit test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,12 @@ void should_not_fail_when_deployed_twice() throws Exception {
bundle.deploy(deployLocation);
// no exception expected
}

@Test
void should_save_deploy_location() {
BundleImpl bundle = new BundleImpl();
bundle.setDeployLocation(deployLocation);
String scriptPath = bundle.startServerScript();
assertThat(scriptPath).isEqualTo(deployLocation.resolve(BundleImpl.DEFAULT_STARTUP_SCRIPT).toString());
}
}
24 changes: 24 additions & 0 deletions sonar-plugin/bridge/src/test/resources/package/bin/server.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/usr/bin/env node

const http = require('http');
const port = process.argv[2];
const host = process.argv[3];

const requestHandler = (request, response) => {
if (request.url === '/status') {
response.writeHead(200, { 'Content-Type': 'text/plain' });
response.end('OK!');
server.close();
}
};

const server = http.createServer(requestHandler);
server.keepAliveTimeout = 100; // this is used so server disconnects faster

server.listen(port, host, err => {
if (err) {
return console.log('something bad happened', err);
}

console.log(`server is listening on ${host} ${port}`);
});

0 comments on commit 5242c58

Please sign in to comment.