Skip to content

Commit e0b255d

Browse files
feat: add base URL preference for CLI downloads and only download CLI [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
1 parent ddd6a1a commit e0b255d

23 files changed

Lines changed: 205 additions & 244 deletions

.github/workflows/ci.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,14 @@ jobs:
3737
3838
- name: Build with Maven
3939
if: ${{ matrix.os == 'ubuntu-latest' }}
40-
run: ./mvnw clean verify -P sign
40+
run: ./mvnw clean verify -P sign -DtrimStackTrace=false
4141
env:
4242
KEYSTORE_PASS: ${{ secrets.KEYSTORE_PASS }}
4343

4444
- name: Build with Maven
4545
if: ${{ matrix.os != 'ubuntu-latest' }}
4646
run: |
47-
./mvnw clean verify
47+
./mvnw clean verify -DtrimStackTrace=false
4848
4949
- name: Authenticate to GCS
5050
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' && matrix.os == 'ubuntu-latest' }}

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22

33
## [2.1.0] - UNRELEASED
44
### Changes
5+
- add base URL preference for CLI download
6+
- use LS embedded in CLI and only download CLI as dependency
7+
8+
## [2.1.0] - v20230720.102331
9+
### Changes
510
- fix custom path configuration
611

712
## [2.1.0] - v20230606.182718

plugin/plugin.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@
167167
clientImpl="io.snyk.languageserver.protocolextension.SnykExtendedLanguageClient"
168168
lastDocumentDisconnectedTimeout="3000000"
169169
singleton="true"
170-
makerType="io.snyk.languageserver.marker">
170+
markerType="io.snyk.languageserver.marker">
171171
</server>
172172

173173
<!-- snyk code -->

plugin/src/main/java/io/snyk/eclipse/plugin/SnykStartup.java

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -50,35 +50,34 @@ public void earlyStartup() {
5050
logger = Platform.getLog(getClass());
5151
}
5252
runtimeEnvironment = new LsRuntimeEnvironment();
53-
Job initJob = new Job("Downloading latest Language Server release...") {
53+
Job initJob = new Job("Downloading latest CLI release...") {
5454
@Override
5555
protected IStatus run(IProgressMonitor monitor) {
56-
PlatformUI.getWorkbench().getDisplay().asyncExec(() -> {
57-
try {
58-
logger.info("LS: Checking for needed download");
59-
if (downloadLS()) {
60-
logger.info("LS: Need to download");
61-
downloading = true;
62-
monitor.subTask("Starting download of Snyk Language Server");
63-
download(monitor);
64-
}
65-
} catch (Exception exception) {
66-
logError(exception);
56+
try {
57+
logger.info("LS: Checking for needed download");
58+
if (downloadLS()) {
59+
monitor.beginTask("Downloading CLI", 100);
60+
logger.info("LS: Need to download");
61+
downloading = true;
62+
download(monitor);
6763
}
68-
downloading = false;
69-
70-
monitor.subTask("Starting Snyk Language Server...");
71-
startLanguageServer();
64+
} catch (Exception exception) {
65+
logError(exception);
66+
}
67+
downloading = false;
68+
monitor.subTask("Starting Snyk CLI in Language Server mode...");
69+
startLanguageServer();
7270

71+
PlatformUI.getWorkbench().getDisplay().syncExec(() -> {
7372
if (Preferences.getInstance().getAuthToken().isBlank()) {
7473
monitor.subTask("Starting Snyk Wizard to configure initial settings...");
7574
SnykWizard wizard = new SnykWizard();
7675
WizardDialog dialog = new WizardDialog(PlatformUI.getWorkbench().getDisplay().getActiveShell(), wizard);
7776
dialog.setBlockOnOpen(true);
7877
dialog.open();
7978
}
80-
8179
});
80+
monitor.done();
8281

8382
return Status.OK_STATUS;
8483
}
@@ -117,7 +116,7 @@ public static SnykView getSnykView() {
117116
}
118117

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

149148
@SuppressWarnings("ResultOfMethodCallIgnored")
150149
IStatus download(IProgressMonitor monitor) {
151-
final File lsFile = new File(Preferences.getInstance().getLsBinary());
150+
final File lsFile = new File(Preferences.getInstance().getCliPath());
152151
try {
153152
LsDownloader lsDownloader = getLsDownloader();
154153
lsFile.getParentFile().mkdirs();

plugin/src/main/java/io/snyk/eclipse/plugin/properties/PreferencesPage.java

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -26,22 +26,22 @@ public PreferencesPage() {
2626

2727
@Override
2828
public void init(IWorkbench workbench) {
29-
setPreferenceStore(io.snyk.eclipse.plugin.properties.preferences.Preferences.getInstance().getStore());
29+
setPreferenceStore(Preferences.getInstance().getStore());
3030
setMessage("Snyk Preferences");
3131
}
3232

3333
@Override
3434
protected void createFieldEditors() {
3535
TokenFieldEditor tokenField = new TokenFieldEditor(
36-
io.snyk.eclipse.plugin.properties.preferences.Preferences.getInstance(),
37-
io.snyk.eclipse.plugin.properties.preferences.Preferences.AUTH_TOKEN_KEY, "Snyk API Token:",
36+
Preferences.getInstance(),
37+
Preferences.AUTH_TOKEN_KEY, "Snyk API Token:",
3838
getFieldEditorParent());
3939
addField(tokenField);
40-
addField(new StringFieldEditor(io.snyk.eclipse.plugin.properties.preferences.Preferences.PATH_KEY, "Path:",
40+
addField(new StringFieldEditor(Preferences.PATH_KEY, "Path:",
4141
getFieldEditorParent()));
42-
addField(new StringFieldEditor(io.snyk.eclipse.plugin.properties.preferences.Preferences.ENDPOINT_KEY,
42+
addField(new StringFieldEditor(Preferences.ENDPOINT_KEY,
4343
"Custom Endpoint:", getFieldEditorParent()));
44-
addField(new BooleanFieldEditor(io.snyk.eclipse.plugin.properties.preferences.Preferences.INSECURE_KEY,
44+
addField(new BooleanFieldEditor(Preferences.INSECURE_KEY,
4545
"Allow unknown certificate authorities", getFieldEditorParent()));
4646

4747
addField(space());
@@ -52,23 +52,23 @@ protected void createFieldEditors() {
5252
getFieldEditorParent()));
5353
addField(space());
5454
addField(new BooleanFieldEditor(
55-
io.snyk.eclipse.plugin.properties.preferences.Preferences.ACTIVATE_SNYK_OPEN_SOURCE,
55+
Preferences.ACTIVATE_SNYK_OPEN_SOURCE,
5656
"Snyk Open Source enabled", getFieldEditorParent()));
5757
snykCodeCheckbox = new BooleanFieldEditor(
58-
io.snyk.eclipse.plugin.properties.preferences.Preferences.ACTIVATE_SNYK_CODE, "Snyk Code enable" + "d",
58+
Preferences.ACTIVATE_SNYK_CODE, "Snyk Code enable" + "d",
5959
getFieldEditorParent());
6060

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

6565
addField(space());
6666
addField(new LabelFieldEditor("Advanced options:", getFieldEditorParent()));
67-
addField(new StringFieldEditor(io.snyk.eclipse.plugin.properties.preferences.Preferences.ORGANIZATION_KEY,
67+
addField(new StringFieldEditor(Preferences.ORGANIZATION_KEY,
6868
"Organization:", getFieldEditorParent()));
69-
addField(new StringFieldEditor(io.snyk.eclipse.plugin.properties.preferences.Preferences.ADDITIONAL_PARAMETERS,
69+
addField(new StringFieldEditor(Preferences.ADDITIONAL_PARAMETERS,
7070
"Additional Parameters:", getFieldEditorParent()));
71-
addField(new StringFieldEditor(io.snyk.eclipse.plugin.properties.preferences.Preferences.ADDITIONAL_ENVIRONMENT,
71+
addField(new StringFieldEditor(Preferences.ADDITIONAL_ENVIRONMENT,
7272
"Additional Environment:", getFieldEditorParent()));
7373

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

8686
addField(space());
8787

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

103103
disableSnykCodeIfOrgDisabled();

plugin/src/main/java/io/snyk/eclipse/plugin/properties/preferences/Preferences.java

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import org.eclipse.jface.preference.IPreferenceStore;
55

66
import io.snyk.eclipse.plugin.EnvironmentConstants;
7+
import io.snyk.languageserver.LsRuntimeEnvironment;
78

89
import java.io.File;
910
import java.util.Optional;
@@ -12,10 +13,11 @@
1213

1314
public class Preferences {
1415
static Preferences CURRENT_PREFERENCES;
16+
static LsRuntimeEnvironment LS_RUNTIME_ENV = new LsRuntimeEnvironment();
1517

1618
public static synchronized Preferences getInstance() {
1719
if (CURRENT_PREFERENCES == null) {
18-
CURRENT_PREFERENCES = new Preferences(new SecurePreferenceStore());
20+
CURRENT_PREFERENCES = new Preferences(new SecurePreferenceStore());
1921
}
2022
return CURRENT_PREFERENCES;
2123
}
@@ -31,8 +33,8 @@ public static synchronized Preferences getInstance(PreferenceStore store) {
3133
public static final String PATH_KEY = "path";
3234
public static final String ENDPOINT_KEY = "endpoint";
3335
public static final String INSECURE_KEY = "insecure";
34-
public static final String LS_BINARY_KEY = "ls-binary";
3536
public static final String CLI_PATH = "cli-path";
37+
public static final String CLI_BASE_URL = "cli-base-url";
3638
public static final String ACTIVATE_SNYK_CODE = "ACTIVATE_SNYK_CODE";
3739
public static final String ACTIVATE_SNYK_OPEN_SOURCE = "ACTIVATE_SNYK_OPEN_SOURCE";
3840
public static final String ACTIVATE_SNYK_IAC = "ACTIVATE_SNYK_IAC";
@@ -82,34 +84,34 @@ public static synchronized Preferences getInstance(PreferenceStore store) {
8284
if (getPref(AUTHENTICATION_METHOD) == null || getPref(AUTHENTICATION_METHOD).isBlank()) {
8385
store(AUTHENTICATION_METHOD, AUTH_METHOD_TOKEN);
8486
}
85-
86-
if (getPref(LS_BINARY_KEY) == null || getPref(LS_BINARY_KEY).equals("")) {
87-
store(LS_BINARY_KEY, getDefaultLsPath());
88-
}
8987

9088
String token = SystemUtils.getEnvironmentVariable(EnvironmentConstants.ENV_SNYK_TOKEN, "");
9189
if (getPref(AUTH_TOKEN_KEY) == null && !"".equals(token)) {
9290
store(AUTH_TOKEN_KEY, token);
9391
}
92+
9493
String endpoint = SystemUtils.getEnvironmentVariable(EnvironmentConstants.ENV_SNYK_API, "");
9594
if (getPref(ENDPOINT_KEY) == null && !"".equals(endpoint)) {
9695
store(ENDPOINT_KEY, endpoint);
9796
}
97+
9898
String org = SystemUtils.getEnvironmentVariable(EnvironmentConstants.ENV_SNYK_ORG, "");
9999
if (getPref(ORGANIZATION_KEY) == null && !"".equals(org)) {
100100
store(ORGANIZATION_KEY, org);
101101
}
102+
103+
String cliPath = getDefaultCliPath();
104+
if (getPref(CLI_PATH) == null && !"".equals(cliPath)) {
105+
store(CLI_PATH, cliPath);
106+
}
107+
108+
if (getPref(CLI_BASE_URL) == null || getPref(CLI_BASE_URL).isBlank()) {
109+
store(CLI_BASE_URL, "https://static.snyk.io");
110+
}
102111
}
103112

104-
private String getBinaryName() {
105-
var osName = SystemUtils.OS_NAME;
106-
var executable = "snyk-ls";
107-
if (osName.toLowerCase().startsWith("win")) executable += ".exe";
108-
return executable;
109-
}
110-
111-
private String getDefaultLsPath() {
112-
File binary = new File(getBinaryDirectory(), getBinaryName());
113+
private String getDefaultCliPath() {
114+
File binary = new File(getBinaryDirectory(), LS_RUNTIME_ENV.getDownloadBinaryName());
113115
return binary.getAbsolutePath();
114116
}
115117

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

132-
public String getLsBinary() {
133-
return getPref(LS_BINARY_KEY, "");
134-
}
135134
public String getLspVersion() {
136135
return getPref(LSP_VERSION);
137136
}
@@ -145,7 +144,7 @@ public Optional<String> getPath() {
145144
}
146145

147146
public String getCliPath() {
148-
return getPref(CLI_PATH, "");
147+
return getPref(CLI_PATH, getDefaultCliPath());
149148
}
150149

151150
public boolean isInsecure() {

plugin/src/main/java/io/snyk/eclipse/plugin/utils/FileDownloadResponseHandler.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ public class FileDownloadResponseHandler implements ResponseHandler<File> {
1414

1515
private final File destinationFile;
1616
private final IProgressMonitor progressMonitor;
17-
private static final String HEADER_CONTENT_LENGTH = "content-length";
1817

1918
public FileDownloadResponseHandler(File file, IProgressMonitor monitor) {
2019
this.destinationFile = file;
Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,27 @@
11
package io.snyk.eclipse.plugin.utils;
22

3-
import com.fasterxml.jackson.databind.ObjectMapper;
4-
import io.snyk.languageserver.download.LsMetadata;
5-
import org.apache.http.HttpResponse;
6-
import org.apache.http.client.ResponseHandler;
7-
83
import java.io.IOException;
94
import java.io.InputStream;
5+
import java.nio.charset.Charset;
6+
7+
import org.apache.http.HttpResponse;
8+
import org.apache.http.client.ResponseHandler;
109

11-
public class LsMetadataResponseHandler implements ResponseHandler<LsMetadata> {
12-
private final ObjectMapper om = new ObjectMapper();
10+
public class LsMetadataResponseHandler implements ResponseHandler<String> {
1311

1412
public LsMetadataResponseHandler() {
1513
}
1614

1715
@Override
18-
public LsMetadata handleResponse(HttpResponse httpResponse) {
19-
try (InputStream inputStream = httpResponse.getEntity().getContent()) {
20-
return om.readValue(inputStream, LsMetadata.class);
16+
public String handleResponse(HttpResponse httpResponse) {
17+
String latestCliSupportingLSProtocolVersion = "10";
18+
InputStream inputStream;
19+
try {
20+
inputStream = httpResponse.getEntity().getContent();
21+
latestCliSupportingLSProtocolVersion = new String(inputStream.readAllBytes(), Charset.defaultCharset());
2122
} catch (UnsupportedOperationException | IOException e) {
2223
throw new RuntimeException(e);
2324
}
25+
return latestCliSupportingLSProtocolVersion;
2426
}
2527
}

plugin/src/main/java/io/snyk/languageserver/LsRuntimeEnvironment.java

Lines changed: 18 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -24,42 +24,31 @@ public class LsRuntimeEnvironment {
2424
public static final Map<String, String> map = new HashMap<>();
2525

2626
static {
27-
map.put("win", "windows");
27+
map.put("win", "win");
2828
map.put("lin", "linux");
29-
map.put("mac", "darwin");
30-
map.put("dar", "darwin");
31-
map.put("macosx", "darwin");
32-
33-
map.put("amd64", "amd64");
34-
map.put("x8664", "amd64");
35-
map.put("x86_64", "amd64");
36-
map.put("x64", "amd64");
37-
38-
map.put("aarch_64", "arm64");
39-
map.put("aarch64", "arm64");
40-
map.put("arm64", "arm64");
41-
42-
map.put("arm_32", "arm");
43-
map.put("arm32", "arm");
44-
map.put("arm", "arm");
45-
46-
map.put("x8632", "386");
47-
map.put("x86_32", "386");
48-
map.put("x86", "386");
49-
map.put("ia32", "386");
50-
map.put("486", "386");
51-
map.put("586", "386");
52-
map.put("686", "386");
29+
map.put("mac", "macos");
30+
map.put("dar", "macos");
31+
map.put("macosx", "macos");
32+
33+
map.put("amd64", "");
34+
map.put("x8664", "");
35+
map.put("x86_64", "");
36+
map.put("x64", "");
37+
38+
map.put("aarch_64", "-arm64");
39+
map.put("aarch64", "-arm64");
40+
map.put("arm64", "-arm64");
5341
}
5442

5543
public LsRuntimeEnvironment() {
5644
}
5745

58-
public String getDownloadBinaryName(String version) {
59-
String base = "snyk-ls_%s_%s_%s";
46+
public String getDownloadBinaryName() {
47+
String base = "snyk-%s%s";
6048
String os = getOs();
61-
String executable = String.format(base, version, os, getArch());
62-
if (executable.toLowerCase().contains("windows")) executable += ".exe";
49+
String executable = String.format(base, os, getArch());
50+
if (executable.toLowerCase().contains("win"))
51+
executable += ".exe";
6352
return executable;
6453
}
6554

0 commit comments

Comments
 (0)