Skip to content

Commit

Permalink
feat: add base URL preference for CLI downloads and only download CLI…
Browse files Browse the repository at this point in the history
… [HEAD-779] (#151)

* feat: download CLI instead of LS

* feat: add baseURL preference

* docs: update Changelog

* fix: show download in progress, change preference to a string field, use base url without cli

* fix: test

* chore: delete obsolete LsMetadata class

* fix: invalidThreadAccess

* fix: small sanity fixes

* feat: only block ui thread during initialization when wizard is shown

* chore: remove superfluous LS_BINARY_KEY constant

* refactor: rename some variables

* chore: add test for default preferences

* fix: cleanup mocks between test runs

* fix: use temp dir for temp file

* fix: create directories before download

* fix: binary name construction in windows
  • Loading branch information
bastiandoetsch authored Nov 13, 2023
1 parent ddd6a1a commit e0b255d
Show file tree
Hide file tree
Showing 23 changed files with 205 additions and 244 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,14 @@ jobs:
- name: Build with Maven
if: ${{ matrix.os == 'ubuntu-latest' }}
run: ./mvnw clean verify -P sign
run: ./mvnw clean verify -P sign -DtrimStackTrace=false
env:
KEYSTORE_PASS: ${{ secrets.KEYSTORE_PASS }}

- name: Build with Maven
if: ${{ matrix.os != 'ubuntu-latest' }}
run: |
./mvnw clean verify
./mvnw clean verify -DtrimStackTrace=false
- name: Authenticate to GCS
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' && matrix.os == 'ubuntu-latest' }}
Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

## [2.1.0] - UNRELEASED
### Changes
- add base URL preference for CLI download
- use LS embedded in CLI and only download CLI as dependency

## [2.1.0] - v20230720.102331
### Changes
- fix custom path configuration

## [2.1.0] - v20230606.182718
Expand Down
2 changes: 1 addition & 1 deletion plugin/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@
clientImpl="io.snyk.languageserver.protocolextension.SnykExtendedLanguageClient"
lastDocumentDisconnectedTimeout="3000000"
singleton="true"
makerType="io.snyk.languageserver.marker">
markerType="io.snyk.languageserver.marker">
</server>

<!-- snyk code -->
Expand Down
37 changes: 18 additions & 19 deletions plugin/src/main/java/io/snyk/eclipse/plugin/SnykStartup.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,35 +50,34 @@ public void earlyStartup() {
logger = Platform.getLog(getClass());
}
runtimeEnvironment = new LsRuntimeEnvironment();
Job initJob = new Job("Downloading latest Language Server release...") {
Job initJob = new Job("Downloading latest CLI release...") {
@Override
protected IStatus run(IProgressMonitor monitor) {
PlatformUI.getWorkbench().getDisplay().asyncExec(() -> {
try {
logger.info("LS: Checking for needed download");
if (downloadLS()) {
logger.info("LS: Need to download");
downloading = true;
monitor.subTask("Starting download of Snyk Language Server");
download(monitor);
}
} catch (Exception exception) {
logError(exception);
try {
logger.info("LS: Checking for needed download");
if (downloadLS()) {
monitor.beginTask("Downloading CLI", 100);
logger.info("LS: Need to download");
downloading = true;
download(monitor);
}
downloading = false;

monitor.subTask("Starting Snyk Language Server...");
startLanguageServer();
} catch (Exception exception) {
logError(exception);
}
downloading = false;
monitor.subTask("Starting Snyk CLI in Language Server mode...");
startLanguageServer();

PlatformUI.getWorkbench().getDisplay().syncExec(() -> {
if (Preferences.getInstance().getAuthToken().isBlank()) {
monitor.subTask("Starting Snyk Wizard to configure initial settings...");
SnykWizard wizard = new SnykWizard();
WizardDialog dialog = new WizardDialog(PlatformUI.getWorkbench().getDisplay().getActiveShell(), wizard);
dialog.setBlockOnOpen(true);
dialog.open();
}

});
monitor.done();

return Status.OK_STATUS;
}
Expand Down Expand Up @@ -117,7 +116,7 @@ public static SnykView getSnykView() {
}

private boolean downloadLS() {
File lsFile = new File(Preferences.getInstance().getLsBinary());
File lsFile = new File(Preferences.getInstance().getCliPath());
logger.info("LS: Expecting file at " + lsFile.getAbsolutePath());
if (!Preferences.getInstance().isManagedBinaries()) {
logger.info("LS: Managed binaries disabled, skipping download");
Expand Down Expand Up @@ -148,7 +147,7 @@ LsDownloader getLsDownloader() throws URISyntaxException {

@SuppressWarnings("ResultOfMethodCallIgnored")
IStatus download(IProgressMonitor monitor) {
final File lsFile = new File(Preferences.getInstance().getLsBinary());
final File lsFile = new File(Preferences.getInstance().getCliPath());
try {
LsDownloader lsDownloader = getLsDownloader();
lsFile.getParentFile().mkdirs();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,22 +26,22 @@ public PreferencesPage() {

@Override
public void init(IWorkbench workbench) {
setPreferenceStore(io.snyk.eclipse.plugin.properties.preferences.Preferences.getInstance().getStore());
setPreferenceStore(Preferences.getInstance().getStore());
setMessage("Snyk Preferences");
}

@Override
protected void createFieldEditors() {
TokenFieldEditor tokenField = new TokenFieldEditor(
io.snyk.eclipse.plugin.properties.preferences.Preferences.getInstance(),
io.snyk.eclipse.plugin.properties.preferences.Preferences.AUTH_TOKEN_KEY, "Snyk API Token:",
Preferences.getInstance(),
Preferences.AUTH_TOKEN_KEY, "Snyk API Token:",
getFieldEditorParent());
addField(tokenField);
addField(new StringFieldEditor(io.snyk.eclipse.plugin.properties.preferences.Preferences.PATH_KEY, "Path:",
addField(new StringFieldEditor(Preferences.PATH_KEY, "Path:",
getFieldEditorParent()));
addField(new StringFieldEditor(io.snyk.eclipse.plugin.properties.preferences.Preferences.ENDPOINT_KEY,
addField(new StringFieldEditor(Preferences.ENDPOINT_KEY,
"Custom Endpoint:", getFieldEditorParent()));
addField(new BooleanFieldEditor(io.snyk.eclipse.plugin.properties.preferences.Preferences.INSECURE_KEY,
addField(new BooleanFieldEditor(Preferences.INSECURE_KEY,
"Allow unknown certificate authorities", getFieldEditorParent()));

addField(space());
Expand All @@ -52,23 +52,23 @@ protected void createFieldEditors() {
getFieldEditorParent()));
addField(space());
addField(new BooleanFieldEditor(
io.snyk.eclipse.plugin.properties.preferences.Preferences.ACTIVATE_SNYK_OPEN_SOURCE,
Preferences.ACTIVATE_SNYK_OPEN_SOURCE,
"Snyk Open Source enabled", getFieldEditorParent()));
snykCodeCheckbox = new BooleanFieldEditor(
io.snyk.eclipse.plugin.properties.preferences.Preferences.ACTIVATE_SNYK_CODE, "Snyk Code enable" + "d",
Preferences.ACTIVATE_SNYK_CODE, "Snyk Code enable" + "d",
getFieldEditorParent());

addField(snykCodeCheckbox);
addField(new BooleanFieldEditor(io.snyk.eclipse.plugin.properties.preferences.Preferences.ACTIVATE_SNYK_IAC,
addField(new BooleanFieldEditor(Preferences.ACTIVATE_SNYK_IAC,
"Snyk Infrastructure-as-Code enabled", getFieldEditorParent()));

addField(space());
addField(new LabelFieldEditor("Advanced options:", getFieldEditorParent()));
addField(new StringFieldEditor(io.snyk.eclipse.plugin.properties.preferences.Preferences.ORGANIZATION_KEY,
addField(new StringFieldEditor(Preferences.ORGANIZATION_KEY,
"Organization:", getFieldEditorParent()));
addField(new StringFieldEditor(io.snyk.eclipse.plugin.properties.preferences.Preferences.ADDITIONAL_PARAMETERS,
addField(new StringFieldEditor(Preferences.ADDITIONAL_PARAMETERS,
"Additional Parameters:", getFieldEditorParent()));
addField(new StringFieldEditor(io.snyk.eclipse.plugin.properties.preferences.Preferences.ADDITIONAL_ENVIRONMENT,
addField(new StringFieldEditor(Preferences.ADDITIONAL_ENVIRONMENT,
"Additional Environment:", getFieldEditorParent()));

addField(space());
Expand All @@ -78,14 +78,14 @@ protected void createFieldEditors() {
System.out.println("managed bionaries changed");
});
addField(manageBinaries);
addField(new FileFieldEditor(io.snyk.eclipse.plugin.properties.preferences.Preferences.LS_BINARY_KEY,
"Snyk Language Server:", getFieldEditorParent()));
addField(new FileFieldEditor(io.snyk.eclipse.plugin.properties.preferences.Preferences.CLI_PATH, "Snyk CLI:",
addField(new StringFieldEditor(Preferences.CLI_BASE_URL, "Base URL for CLI download:",
getFieldEditorParent()));
addField(new FileFieldEditor(Preferences.CLI_PATH, "Snyk CLI (incl. Language Server):",
getFieldEditorParent()));

addField(space());

addField(new BooleanFieldEditor(io.snyk.eclipse.plugin.properties.preferences.Preferences.SEND_ERROR_REPORTS,
addField(new BooleanFieldEditor(Preferences.SEND_ERROR_REPORTS,
"Send error reports to Snyk", getFieldEditorParent()));
addField(new BooleanFieldEditor(Preferences.ENABLE_TELEMETRY, "Send usage statistics to Snyk",
getFieldEditorParent()));
Expand All @@ -97,7 +97,7 @@ protected void createFieldEditors() {
+ "paths are safe to scan. Every path below a given path is considered safe to scan. \n"
+ "Please separate entries with \"" + File.pathSeparator + "\".",
getFieldEditorParent()));
addField(new StringFieldEditor(io.snyk.eclipse.plugin.properties.preferences.Preferences.TRUSTED_FOLDERS,
addField(new StringFieldEditor(Preferences.TRUSTED_FOLDERS,
"Trusted Folders:", getFieldEditorParent()));

disableSnykCodeIfOrgDisabled();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import org.eclipse.jface.preference.IPreferenceStore;

import io.snyk.eclipse.plugin.EnvironmentConstants;
import io.snyk.languageserver.LsRuntimeEnvironment;

import java.io.File;
import java.util.Optional;
Expand All @@ -12,10 +13,11 @@

public class Preferences {
static Preferences CURRENT_PREFERENCES;
static LsRuntimeEnvironment LS_RUNTIME_ENV = new LsRuntimeEnvironment();

public static synchronized Preferences getInstance() {
if (CURRENT_PREFERENCES == null) {
CURRENT_PREFERENCES = new Preferences(new SecurePreferenceStore());
CURRENT_PREFERENCES = new Preferences(new SecurePreferenceStore());
}
return CURRENT_PREFERENCES;
}
Expand All @@ -31,8 +33,8 @@ public static synchronized Preferences getInstance(PreferenceStore store) {
public static final String PATH_KEY = "path";
public static final String ENDPOINT_KEY = "endpoint";
public static final String INSECURE_KEY = "insecure";
public static final String LS_BINARY_KEY = "ls-binary";
public static final String CLI_PATH = "cli-path";
public static final String CLI_BASE_URL = "cli-base-url";
public static final String ACTIVATE_SNYK_CODE = "ACTIVATE_SNYK_CODE";
public static final String ACTIVATE_SNYK_OPEN_SOURCE = "ACTIVATE_SNYK_OPEN_SOURCE";
public static final String ACTIVATE_SNYK_IAC = "ACTIVATE_SNYK_IAC";
Expand Down Expand Up @@ -82,34 +84,34 @@ public static synchronized Preferences getInstance(PreferenceStore store) {
if (getPref(AUTHENTICATION_METHOD) == null || getPref(AUTHENTICATION_METHOD).isBlank()) {
store(AUTHENTICATION_METHOD, AUTH_METHOD_TOKEN);
}

if (getPref(LS_BINARY_KEY) == null || getPref(LS_BINARY_KEY).equals("")) {
store(LS_BINARY_KEY, getDefaultLsPath());
}

String token = SystemUtils.getEnvironmentVariable(EnvironmentConstants.ENV_SNYK_TOKEN, "");
if (getPref(AUTH_TOKEN_KEY) == null && !"".equals(token)) {
store(AUTH_TOKEN_KEY, token);
}

String endpoint = SystemUtils.getEnvironmentVariable(EnvironmentConstants.ENV_SNYK_API, "");
if (getPref(ENDPOINT_KEY) == null && !"".equals(endpoint)) {
store(ENDPOINT_KEY, endpoint);
}

String org = SystemUtils.getEnvironmentVariable(EnvironmentConstants.ENV_SNYK_ORG, "");
if (getPref(ORGANIZATION_KEY) == null && !"".equals(org)) {
store(ORGANIZATION_KEY, org);
}

String cliPath = getDefaultCliPath();
if (getPref(CLI_PATH) == null && !"".equals(cliPath)) {
store(CLI_PATH, cliPath);
}

if (getPref(CLI_BASE_URL) == null || getPref(CLI_BASE_URL).isBlank()) {
store(CLI_BASE_URL, "https://static.snyk.io");
}
}

private String getBinaryName() {
var osName = SystemUtils.OS_NAME;
var executable = "snyk-ls";
if (osName.toLowerCase().startsWith("win")) executable += ".exe";
return executable;
}

private String getDefaultLsPath() {
File binary = new File(getBinaryDirectory(), getBinaryName());
private String getDefaultCliPath() {
File binary = new File(getBinaryDirectory(), LS_RUNTIME_ENV.getDownloadBinaryName());
return binary.getAbsolutePath();
}

Expand All @@ -129,9 +131,6 @@ public String getEndpoint() {
return getPref(ENDPOINT_KEY, "");
}

public String getLsBinary() {
return getPref(LS_BINARY_KEY, "");
}
public String getLspVersion() {
return getPref(LSP_VERSION);
}
Expand All @@ -145,7 +144,7 @@ public Optional<String> getPath() {
}

public String getCliPath() {
return getPref(CLI_PATH, "");
return getPref(CLI_PATH, getDefaultCliPath());
}

public boolean isInsecure() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ public class FileDownloadResponseHandler implements ResponseHandler<File> {

private final File destinationFile;
private final IProgressMonitor progressMonitor;
private static final String HEADER_CONTENT_LENGTH = "content-length";

public FileDownloadResponseHandler(File file, IProgressMonitor monitor) {
this.destinationFile = file;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,27 @@
package io.snyk.eclipse.plugin.utils;

import com.fasterxml.jackson.databind.ObjectMapper;
import io.snyk.languageserver.download.LsMetadata;
import org.apache.http.HttpResponse;
import org.apache.http.client.ResponseHandler;

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;

import org.apache.http.HttpResponse;
import org.apache.http.client.ResponseHandler;

public class LsMetadataResponseHandler implements ResponseHandler<LsMetadata> {
private final ObjectMapper om = new ObjectMapper();
public class LsMetadataResponseHandler implements ResponseHandler<String> {

public LsMetadataResponseHandler() {
}

@Override
public LsMetadata handleResponse(HttpResponse httpResponse) {
try (InputStream inputStream = httpResponse.getEntity().getContent()) {
return om.readValue(inputStream, LsMetadata.class);
public String handleResponse(HttpResponse httpResponse) {
String latestCliSupportingLSProtocolVersion = "10";
InputStream inputStream;
try {
inputStream = httpResponse.getEntity().getContent();
latestCliSupportingLSProtocolVersion = new String(inputStream.readAllBytes(), Charset.defaultCharset());
} catch (UnsupportedOperationException | IOException e) {
throw new RuntimeException(e);
}
return latestCliSupportingLSProtocolVersion;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,42 +24,31 @@ public class LsRuntimeEnvironment {
public static final Map<String, String> map = new HashMap<>();

static {
map.put("win", "windows");
map.put("win", "win");
map.put("lin", "linux");
map.put("mac", "darwin");
map.put("dar", "darwin");
map.put("macosx", "darwin");

map.put("amd64", "amd64");
map.put("x8664", "amd64");
map.put("x86_64", "amd64");
map.put("x64", "amd64");

map.put("aarch_64", "arm64");
map.put("aarch64", "arm64");
map.put("arm64", "arm64");

map.put("arm_32", "arm");
map.put("arm32", "arm");
map.put("arm", "arm");

map.put("x8632", "386");
map.put("x86_32", "386");
map.put("x86", "386");
map.put("ia32", "386");
map.put("486", "386");
map.put("586", "386");
map.put("686", "386");
map.put("mac", "macos");
map.put("dar", "macos");
map.put("macosx", "macos");

map.put("amd64", "");
map.put("x8664", "");
map.put("x86_64", "");
map.put("x64", "");

map.put("aarch_64", "-arm64");
map.put("aarch64", "-arm64");
map.put("arm64", "-arm64");
}

public LsRuntimeEnvironment() {
}

public String getDownloadBinaryName(String version) {
String base = "snyk-ls_%s_%s_%s";
public String getDownloadBinaryName() {
String base = "snyk-%s%s";
String os = getOs();
String executable = String.format(base, version, os, getArch());
if (executable.toLowerCase().contains("windows")) executable += ".exe";
String executable = String.format(base, os, getArch());
if (executable.toLowerCase().contains("win"))
executable += ".exe";
return executable;
}

Expand Down
Loading

0 comments on commit e0b255d

Please sign in to comment.