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 scan on startup for non-code #513

Merged
merged 1 commit into from
Apr 18, 2024
Merged
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## [2.7.15]
### Fixed
- Re-enable scan results when re-enabling different scan types
- (LS Preview) do not trigger scan on startup for Snyk Code multiple times

## [2.7.14]
### Added
Expand Down
4 changes: 2 additions & 2 deletions src/main/kotlin/io/snyk/plugin/SnykPostStartupActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,8 @@ class SnykPostStartupActivity : ProjectActivity {
getKubernetesImageCache(project)?.cacheKubernetesFileFromProject()
}

if (settings.scanOnSave && isSnykCodeLSEnabled()) {
getSnykTaskQueueService(project)?.scan()
if (settings.scanOnSave && (isSnykCodeLSEnabled() || isSnykOSSLSEnabled() || isSnykIaCLSEnabled())) {
getSnykTaskQueueService(project)?.scan(true)
}

ExtensionPointsUtil.controllerManager.extensionList.forEach {
Expand Down
5 changes: 5 additions & 0 deletions src/main/kotlin/io/snyk/plugin/Utils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,11 @@ fun isFileListenerEnabled(): Boolean = pluginSettings().fileListenerEnabled

fun isSnykCodeLSEnabled(): Boolean = Registry.`is`("snyk.preview.snyk.code.ls.enabled", true)

fun isSnykOSSLSEnabled(): Boolean = false

fun isSnykIaCLSEnabled(): Boolean = false


fun getWaitForResultsTimeout(): Long =
Registry.intValue(
"snyk.timeout.results.waiting",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class SnykControllerImpl(val project: Project) : SnykController {
* scan enqueues a scan of the project for vulnerabilities.
*/
override fun scan() {
getSnykTaskQueueService(project)?.scan()
getSnykTaskQueueService(project)?.scan(false)
}

/**
Expand Down
18 changes: 14 additions & 4 deletions src/main/kotlin/io/snyk/plugin/services/SnykTaskQueueService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ import io.snyk.plugin.isContainerEnabled
import io.snyk.plugin.isIacEnabled
import io.snyk.plugin.isSnykCodeLSEnabled
import io.snyk.plugin.isSnykCodeRunning
import io.snyk.plugin.isSnykIaCLSEnabled
import io.snyk.plugin.isSnykOSSLSEnabled
import io.snyk.plugin.net.ClientException
import io.snyk.plugin.pluginSettings
import io.snyk.plugin.refreshAnnotationsForOpenFiles
Expand Down Expand Up @@ -98,7 +100,7 @@ class SnykTaskQueueService(val project: Project) {
}
}

fun scan() {
fun scan(isStartup: Boolean) {
taskQueue.run(object : Task.Backgroundable(project, "Snyk: initializing...", true) {
override fun run(indicator: ProgressIndicator) {
if (!confirmScanningAndSetWorkspaceTrustedStateIfNeeded(project)) return
Expand All @@ -114,14 +116,22 @@ class SnykTaskQueueService(val project: Project) {
if (!isSnykCodeLSEnabled()) {
scheduleSnykCodeScan()
} else {
LanguageServerWrapper.getInstance().sendScanCommand(project)
// the LS deals with triggering scans at startup
// TODO: Refactor when more than Snyk Code is available in LS for IntelliJ
if (!isStartup) {
LanguageServerWrapper.getInstance().sendScanCommand(project)
}
}
}
if (settings.ossScanEnable) {
scheduleOssScan()
if (!isSnykOSSLSEnabled()) {
scheduleOssScan()
}
}
if (isIacEnabled() && settings.iacScanEnabled) {
scheduleIacScan()
if (!isSnykIaCLSEnabled()) {
scheduleIacScan()
}
}
if (isContainerEnabled() && settings.containerScanEnabled) {
scheduleContainerScan()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import snyk.analytics.AnalysisIsTriggered
class SnykRunScanAction : AnAction(AllIcons.Actions.Execute), DumbAware {

override fun actionPerformed(actionEvent: AnActionEvent) {
getSnykTaskQueueService(actionEvent.project!!)?.scan()
getSnykTaskQueueService(actionEvent.project!!)?.scan(false)

getSnykAnalyticsService().logAnalysisIsTriggered(
AnalysisIsTriggered.builder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class IssueViewOptionsPanel(
.actionListener{ event, it ->
if (canBeChanged(it, it.isSelected)) {
currentOpenIssuesEnabled = it.isSelected
getSnykTaskQueueService(project)?.scan()
getSnykTaskQueueService(project)?.scan(false)
}
}
// bindSelected is needed to trigger apply() on the settings dialog that this panel is rendered in
Expand All @@ -44,7 +44,7 @@ class IssueViewOptionsPanel(
.actionListener{ event, it ->
if (canBeChanged(it, it.isSelected)) {
currentIgnoredIssuesEnabled = it.isSelected
getSnykTaskQueueService(project)?.scan()
getSnykTaskQueueService(project)?.scan(false)
}
}
.bindSelected(settings::ignoredIssuesEnabled)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -521,7 +521,7 @@ class SnykToolWindowPanel(val project: Project) : JPanel(), Disposable {
.build()
)

getSnykTaskQueueService(project)?.scan()
getSnykTaskQueueService(project)?.scan(false)
}

fun displayAuthPanel() {
Expand Down
6 changes: 4 additions & 2 deletions src/main/kotlin/snyk/common/lsp/LanguageServerWrapper.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import io.snyk.plugin.getSnykTaskQueueService
import io.snyk.plugin.getUserAgentString
import io.snyk.plugin.isCliInstalled
import io.snyk.plugin.isSnykCodeLSEnabled
import io.snyk.plugin.isSnykIaCLSEnabled
import io.snyk.plugin.isSnykOSSLSEnabled
import io.snyk.plugin.pluginSettings
import io.snyk.plugin.toLanguageServerURL
import io.snyk.plugin.ui.SnykBalloonNotificationHelper
Expand Down Expand Up @@ -306,10 +308,10 @@ class LanguageServerWrapper(
fun getSettings(): LanguageServerSettings {
val ps = pluginSettings()
return LanguageServerSettings(
activateSnykOpenSource = false.toString(),
activateSnykOpenSource = isSnykOSSLSEnabled().toString(),
activateSnykCodeSecurity = (isSnykCodeLSEnabled() && ps.snykCodeSecurityIssuesScanEnable).toString(),
activateSnykCodeQuality = (isSnykCodeLSEnabled() && ps.snykCodeQualityIssuesScanEnable).toString(),
activateSnykIac = false.toString(),
activateSnykIac = isSnykIaCLSEnabled().toString(),
organization = ps.organization,
insecure = ps.ignoreUnknownCA.toString(),
endpoint = getEndpointUrl(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package io.snyk.plugin.services

import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.components.service
import com.intellij.openapi.util.registry.Registry
import com.intellij.testFramework.LightPlatformTestCase
import com.intellij.testFramework.PlatformTestUtil
import com.intellij.testFramework.replaceService
Expand All @@ -12,12 +13,14 @@ import io.mockk.mockkStatic
import io.mockk.spyk
import io.mockk.unmockkAll
import io.mockk.verify
import io.snyk.plugin.DEFAULT_TIMEOUT_FOR_SCAN_WAITING_MS
import io.snyk.plugin.getCliFile
import io.snyk.plugin.getContainerService
import io.snyk.plugin.getIacService
import io.snyk.plugin.getOssService
import io.snyk.plugin.getSnykCachedResults
import io.snyk.plugin.getSnykCliDownloaderService
import io.snyk.plugin.getSnykCode
import io.snyk.plugin.isCliInstalled
import io.snyk.plugin.isContainerEnabled
import io.snyk.plugin.isIacEnabled
Expand Down Expand Up @@ -92,7 +95,7 @@ class SnykTaskQueueServiceTest : LightPlatformTestCase() {
setupDummyCliFile()
val snykTaskQueueService = project.service<SnykTaskQueueService>()

snykTaskQueueService.scan()
snykTaskQueueService.scan(false)
PlatformTestUtil.dispatchAllInvocationEventsInIdeEventQueue()

assertTrue(snykTaskQueueService.getTaskQueue().isEmpty)
Expand All @@ -103,13 +106,12 @@ class SnykTaskQueueServiceTest : LightPlatformTestCase() {
assertTrue(snykTaskQueueService.getTaskQueue().isEmpty)
assertNull(snykTaskQueueService.ossScanProgressIndicator)
}

fun testCliDownloadBeforeScanIfNeeded() {
setupAppSettingsForDownloadTests()
every { isCliInstalled() } returns true

val snykTaskQueueService = project.service<SnykTaskQueueService>()
snykTaskQueueService.scan()
snykTaskQueueService.scan(false)

PlatformTestUtil.dispatchAllInvocationEventsInIdeEventQueue()
assertTrue(snykTaskQueueService.getTaskQueue().isEmpty)
Expand All @@ -123,7 +125,7 @@ class SnykTaskQueueServiceTest : LightPlatformTestCase() {
val snykTaskQueueService = project.service<SnykTaskQueueService>()
every { isCliInstalled() } returns true

snykTaskQueueService.scan()
snykTaskQueueService.scan(false)

PlatformTestUtil.dispatchAllInvocationEventsInIdeEventQueue()
assertTrue(snykTaskQueueService.getTaskQueue().isEmpty)
Expand Down Expand Up @@ -169,7 +171,7 @@ class SnykTaskQueueServiceTest : LightPlatformTestCase() {
settings.snykCodeQualityIssuesScanEnable = true
settings.token = "testToken"

snykTaskQueueService.scan()
snykTaskQueueService.scan(false)
PlatformTestUtil.dispatchAllInvocationEventsInIdeEventQueue()

verify { snykApiServiceMock.getSastSettings() }
Expand Down Expand Up @@ -202,7 +204,7 @@ class SnykTaskQueueServiceTest : LightPlatformTestCase() {
every { isCliInstalled() } returns true
every { getIacService(project)?.scan() } returns fakeIacResult

snykTaskQueueService.scan()
snykTaskQueueService.scan(false)
PlatformTestUtil.dispatchAllInvocationEventsInIdeEventQueue()

assertEquals(fakeIacResult, getSnykCachedResults(project)?.currentIacResult)
Expand All @@ -225,11 +227,90 @@ class SnykTaskQueueServiceTest : LightPlatformTestCase() {

getSnykCachedResults(project)?.currentContainerResult = null

snykTaskQueueService.scan()
snykTaskQueueService.scan(false)
PlatformTestUtil.dispatchAllInvocationEventsInIdeEventQueue()

await().atMost(2, TimeUnit.SECONDS).until {
getSnykCachedResults(project)?.currentContainerResult != null
}
}

fun testSnykTaskQueueServiceScanCodeOnStartupAndFailsWhenLS() {
val registryValue = Registry.get("snyk.preview.snyk.code.ls.enabled")
registryValue.setValue(false)

val snykTaskQueueService = project.service<SnykTaskQueueService>()
val settings = pluginSettings()
settings.ossScanEnable = true
settings.snykCodeSecurityIssuesScanEnable = true
settings.snykCodeQualityIssuesScanEnable = true
settings.token = "testToken"
settings.iacScanEnabled = true
settings.containerScanEnabled = true
getSnykCachedResults(project)?.currentOssResults = null
getSnykCachedResults(project)?.currentIacResult = null
getSnykCachedResults(project)?.currentContainerResult = null
getSnykCachedResults(project)?.currentSnykCodeResults = null

val fakeOSSResult = OssResult(emptyList())
val fakeIacResult = IacResult(emptyList())
val fakeContainerResult = ContainerResult(emptyList())

mockkStatic("io.snyk.plugin.UtilsKt")
every { isIacEnabled() } returns true
every { isCliInstalled() } returns true
every { getSnykCode(project)?.scan() } returns null
every { getOssService(project)?.scan() } returns fakeOSSResult
every { getIacService(project)?.scan() } returns fakeIacResult
every { getContainerService(project)?.scan() } returns fakeContainerResult

snykTaskQueueService.scan(true)
PlatformTestUtil.dispatchAllInvocationEventsInIdeEventQueue()

assertEquals(fakeOSSResult, getSnykCachedResults(project)?.currentOssResults)
assertEquals(fakeIacResult, getSnykCachedResults(project)?.currentIacResult)
await().atMost(2, TimeUnit.SECONDS).until {
getSnykCachedResults(project)?.currentContainerResult != null
}
verify(exactly = 1) { getSnykCode(project)?.scan() }
}
fun testSnykTaskQueueServiceDoesNotScanCodeOnStartupWhenLS() {
val registryValue = Registry.get("snyk.preview.snyk.code.ls.enabled")
registryValue.setValue(true)

val snykTaskQueueService = project.service<SnykTaskQueueService>()
val settings = pluginSettings()
settings.ossScanEnable = true
settings.snykCodeSecurityIssuesScanEnable = true
settings.snykCodeQualityIssuesScanEnable = true
settings.token = "testToken"
settings.iacScanEnabled = true
settings.containerScanEnabled = true
getSnykCachedResults(project)?.currentOssResults = null
getSnykCachedResults(project)?.currentIacResult = null
getSnykCachedResults(project)?.currentContainerResult = null
getSnykCachedResults(project)?.currentSnykCodeResults = null

val fakeOSSResult = OssResult(emptyList())
val fakeIacResult = IacResult(emptyList())
val fakeContainerResult = ContainerResult(emptyList())

mockkStatic("io.snyk.plugin.UtilsKt")
every { isIacEnabled() } returns true
every { isCliInstalled() } returns true
every { getOssService(project)?.scan() } returns fakeOSSResult
every { getIacService(project)?.scan() } returns fakeIacResult
every { getContainerService(project)?.scan() } returns fakeContainerResult

snykTaskQueueService.scan(true)
PlatformTestUtil.dispatchAllInvocationEventsInIdeEventQueue()

assertEquals(fakeOSSResult, getSnykCachedResults(project)?.currentOssResults)
assertEquals(fakeIacResult, getSnykCachedResults(project)?.currentIacResult)
await().atMost(2, TimeUnit.SECONDS).until {
getSnykCachedResults(project)?.currentContainerResult != null
}
verify(exactly = 0) { getSnykCode(project)?.scan() }
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ class SnykToolWindowPanelIntegTest : HeavyPlatformTestCase() {
} returns (iacGoofJson)
getIacService(project)?.setConsoleCommandRunner(mockRunner)

project.service<SnykTaskQueueService>().scan()
project.service<SnykTaskQueueService>().scan(false)
PlatformTestUtil.waitWhileBusy(toolWindowPanel.getTree())
}

Expand Down Expand Up @@ -598,7 +598,7 @@ class SnykToolWindowPanelIntegTest : HeavyPlatformTestCase() {
every { getIacService(project)?.scan() } returns iacResultWithError

// actual test run
project.service<SnykTaskQueueService>().scan()
project.service<SnykTaskQueueService>().scan(false)

PlatformTestUtil.waitWhileBusy(toolWindowPanel.getTree())

Expand Down Expand Up @@ -704,7 +704,7 @@ class SnykToolWindowPanelIntegTest : HeavyPlatformTestCase() {
setUpContainerTest(containerResultWithError)

// actual test run
project.service<SnykTaskQueueService>().scan()
project.service<SnykTaskQueueService>().scan(false)

PlatformTestUtil.waitWhileBusy(toolWindowPanel.getTree())

Expand All @@ -731,7 +731,7 @@ class SnykToolWindowPanelIntegTest : HeavyPlatformTestCase() {
setUpContainerTest(fakeContainerResult)

// actual test run
project.service<SnykTaskQueueService>().scan()
project.service<SnykTaskQueueService>().scan(false)
PlatformTestUtil.waitWhileBusy(toolWindowPanel.getTree())

// Assertions
Expand Down Expand Up @@ -765,7 +765,7 @@ class SnykToolWindowPanelIntegTest : HeavyPlatformTestCase() {
mockkObject(SnykBalloonNotificationHelper)

// actual test run
project.service<SnykTaskQueueService>().scan()
project.service<SnykTaskQueueService>().scan(false)
PlatformTestUtil.waitWhileBusy(toolWindowPanel.getTree())

// Assertions
Expand Down Expand Up @@ -797,7 +797,7 @@ class SnykToolWindowPanelIntegTest : HeavyPlatformTestCase() {
setUpContainerTest(fakeContainerResult)

// actual test run
project.service<SnykTaskQueueService>().scan()
project.service<SnykTaskQueueService>().scan(false)
PlatformTestUtil.waitWhileBusy(toolWindowPanel.getTree())

// Assertions
Expand Down Expand Up @@ -879,7 +879,7 @@ class SnykToolWindowPanelIntegTest : HeavyPlatformTestCase() {
setUpContainerTest(containerResult)

// actual test run
project.service<SnykTaskQueueService>().scan()
project.service<SnykTaskQueueService>().scan(false)
PlatformTestUtil.waitWhileBusy(toolWindowPanel.getTree())

return containerResult
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ class SnykToolWindowPanelTest : LightPlatform4TestCase() {
true,
LocalCodeEngine(false, "", false),
)
justRun { taskQueueService.scan() }
justRun { taskQueueService.scan(false) }

cut = SnykToolWindowPanel(project)

Expand All @@ -135,7 +135,7 @@ class SnykToolWindowPanelTest : LightPlatform4TestCase() {
assertNotNull(descriptionPanel)
assertEquals(findOnePixelSplitter(vulnerabilityTree), descriptionPanel!!.parent)

verify(exactly = 1) { taskQueueService.scan() }
verify(exactly = 1) { taskQueueService.scan(false) }
verify(exactly = 1) { analyticsService.logAnalysisIsTriggered(any()) }
}

Expand Down
Loading