Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: trigger folder scan when .snyk file changes [IDE-253] #563

Merged
merged 5 commits into from
Jul 8, 2024

Conversation

cat2608
Copy link
Contributor

@cat2608 cat2608 commented Jun 26, 2024

Description

This PR triggers a workspace scan when the .snyk file was saved.

Checklist

  • Tests added and all succeed
  • Linted
  • README.md updated, if user-facing
  • License file updated, if new 3rd-party dependency is introduced

🚨After having merged, please update the CLI go.mod to pull in latest language server.

Screenshots / GIFs

auto-scan-snyj-ignore.mp4

} else {

if isDotSnykFile(params.TextDocument.URI) {
dotSnykFileDidChangeScan(bgCtx, f)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be dependent on the auto-scan setting too. Although this scenario is right now not defined. I wonder though how we transmit the need to rescan to get new results. Maybe a notification? WDYT?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder though how we transmit the need to rescan to get new results. Maybe a notification? WDYT?

Could you please elaborate a bit here? Are you saying we need to notify the user that after a local change to the .snyk file, the workspace will be re-scanned?

So far, I've been doing it in the background: when textDocumentDidSaveHandler the scan occurs.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From the customer perspective, if they have deactivated auto-scanning, they wouldn't notice a need to re-scan. On the other hand, they are the ones to update the .snyk file so it may be okay.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From the customer perspective, if they have deactivated auto-scanning, they wouldn't notice a need to re-scan. On the other hand, they are the ones to update the .snyk file so it may be okay.

} else {
logger.Warn().Msg("Not scanning, auto-scan is disabled")
}
} else if autoScanEnabled {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this dependent on the autoscan boolean?

Copy link
Contributor Author

@cat2608 cat2608 Jun 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This bit was just a small refactor to reduce one level of nesting. It's the first:

Copy link
Contributor

@acke acke left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me.

} else {
ws := workspace.Get()
if ws != nil && autoScanEnabled && uri.IsDotSnykFile(params.TextDocument.URI) {
go ws.ScanWorkspace(bgCtx)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question: why not scan the workspaceFolder? Scanning the workspace could be too much - especially in Eclipse, corporate users often have 30+ projects (=workspace folders) open, and scanning all of them may slow down their workflow & computer. You could pull line 563 up, and then call f.Scan(). WDYT?

if autoScanEnabled {
logger.Warn().Str("documentURI", filePath).Msg("Not scanning, file not part of workspace")
go f.ScanFile(bgCtx, filePath)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This may cause a double scan, right? First the scan above and afterwards the f.ScanFile. I'd think we can combine it :)

Copy link
Collaborator

@bastiandoetsch bastiandoetsch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please have a look at my comment regarding double scans - else very nice 🚀

Comment on lines 111 to 116

di.FileWatcher().SetFileAsChanged(params.TextDocument.URI)

filePath := uri.PathFromUri(params.TextDocument.URI)
autoScanEnabled := c.IsAutoScanEnabled()

f := workspace.Get().GetFolderContaining(filePath)

if f != nil && autoScanEnabled && uri.IsDotSnykFile(params.TextDocument.URI) {
go f.ScanFolder(ctx)
return nil, nil
}

for _, change := range params.ContentChanges {
if packageScanner, ok := di.Scanner().(snyk.PackageScanner); ok {
packageScanner.ScanPackages(ctx, c, uri.PathFromUri(params.TextDocument.URI), change.Text)
Copy link
Contributor Author

@cat2608 cat2608 Jun 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bastiandoetsch I also added the trigger when a user runs the command snyk ignore --id='ISSUE_ID' --reason='REASON' in the terminal.

The Snyk ignore command triggers the textDocument/didChange

I need to commit the unit test for this branch and move this logic to a function so both handlers can use it

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yeah, probably when VSCode refreshes and the content changes, it is sending this.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me know, once you've pushed it, I'll re-review and merge.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For this case, I'm trying to make this test pass:

func Test_textDocumentDidChangeHandler_shouldTriggerScanForDotSnykFile(t *testing.T) {
	loc, jsonRPCRecorder := setupServer(t)
	config.CurrentConfig().SetSnykCodeEnabled(false)

	fakeAuthenticationProvider := di.AuthenticationService().Provider().(*snyk.FakeAuthenticationProvider)
	fakeAuthenticationProvider.IsAuthenticated = true

	_, err := loc.Client.Call(ctx, "initialize", nil)
	if err != nil {
		t.Fatalf("initialization failed: %v", err)
	}

	snykFilePath, folderPath := createTemporaryDirectoryWithSnykFile(t)

	// Simulate a "did change" event for the .snyk file
	sendFileChangedMessage(t, snykFilePath, folderPath, loc)

	// Wait for $/snyk.scan notification
	assert.Eventually(
		t,
		checkForSnykScan(t, jsonRPCRecorder),
		15*time.Second,
		50*time.Millisecond,
	)
}

func sendFileChangedMessage(t *testing.T, filePath, fileDir string, loc server.Local) sglsp.DocumentURI {
	t.Helper()
	c := config.CurrentConfig()
	didChangeParams := sglsp.DidChangeTextDocumentParams{
		TextDocument: sglsp.VersionedTextDocumentIdentifier{
			TextDocumentIdentifier: sglsp.TextDocumentIdentifier{
				URI: uri.PathToUri(filePath),
			},
			Version: 1,
		},
		ContentChanges: []sglsp.TextDocumentContentChangeEvent{
			{
				Text: "SNYK-JS-QS-3153490", // simulates: `snyk ignore --id='SNYK-JS-QS-3153490'`
			},
		},
	}
	workspace.Get().AddFolder(workspace.NewFolder(c, fileDir,
		"Test",
		di.Scanner(),
		di.HoverService(),
		di.ScanNotifier(),
		di.Notifier()))

	_, err := loc.Client.Call(ctx, "textDocument/didChange", didChangeParams)
	if err != nil {
		t.Fatal(err)
	}

	return didChangeParams.TextDocument.URI
}

I'm following a similar approach written for other cases but I wasn't able to solve this error yet:

024-06-28T16:07:55+01:00 INF - Fake Authentication - successful.
2024-06-28T16:07:55+01:00 DBG - IsAuthenticated: fake auth successful
2024-06-28T16:07:55+01:00 INF ide.workspace.folder.DelegatingConcurrentScanner.ScanFile  - Scan was canceled err={}
--- FAIL: Test_textDocumentDidChangeHandler_shouldTriggerScanForDotSnykFile (15.21s)
    server_test.go:1033: 
        	Error Trace:	/Users/cata/git/snyk/hammerhead/snyk-ls/application/server/server_test.go:1033
        	Error:      	Condition never satisfied
        	Test:       	Test_textDocumentDidChangeHandler_shouldTriggerScanForDotSnykFile
FAIL

which is happening here: domain/snyk/scanner.go.

We could go for the textDocumentDidSaveHandler only and work on the textDocumentDidChangeHandler in another PR. WDYT?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bastiandoetsch here is the initial change needed in IntelliJ snyk/snyk-intellij-plugin#562

Comment on lines +835 to +837
if err != nil {
t.Fatalf("initialization failed: %v", err)
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here - should use assert.NoError(t, err)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the case when there is an error and all the other blocks are using t.Fatal. In this case I'm only appending the error message.

@cat2608 cat2608 force-pushed the fix/IDE-253-scan-when-dot-snyk-file-changes branch from 4c28d00 to c9d2f12 Compare June 28, 2024 16:19
@cat2608 cat2608 force-pushed the fix/IDE-253-scan-when-dot-snyk-file-changes branch from c9d2f12 to 3676313 Compare July 7, 2024 20:26
@cat2608 cat2608 merged commit c8780b2 into main Jul 8, 2024
16 checks passed
@cat2608 cat2608 deleted the fix/IDE-253-scan-when-dot-snyk-file-changes branch July 8, 2024 07:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants