Skip to content

Commit

Permalink
Merge branch 'main' into dependabot/gradle/org.jetbrains.kotlin.jvm-1…
Browse files Browse the repository at this point in the history
….9.22
  • Loading branch information
adrienpessu authored Dec 22, 2023
2 parents c7723a9 + 1a43517 commit 9194dc1
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 48 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ pluginVersion = 0.0.8

# Supported build number ranges and IntelliJ Platform versions -> https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html
pluginSinceBuild = 223
pluginUntilBuild = 232.*
pluginUntilBuild = 233.*

# IntelliJ Platform Properties -> https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html#configuration-intellij-extension
platformType = IC
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.github.adrienpessu.sarifviewer.models

data class BranchItemComboBox(
val prNumber: Int = 0,
val head: String = "",
val base: String = "",
val prTitle: String = "",
val commit: String = "",
) {
override fun toString(): String {
if (prNumber == 0) {

Check notice on line 11 in src/main/kotlin/com/github/adrienpessu/sarifviewer/models/BranchItemComboBox.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Return or assignment can be lifted out

'Return' can be lifted out of 'if'
return head
} else {
return "pr$prNumber ($prTitle)"
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.github.adrienpessu.sarifviewer.services

import com.contrastsecurity.sarif.Result
import com.contrastsecurity.sarif.SarifSchema210
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.kotlin.readValue
Expand All @@ -8,26 +9,41 @@ import com.github.adrienpessu.sarifviewer.models.Leaf
import com.github.adrienpessu.sarifviewer.models.Root
import com.github.adrienpessu.sarifviewer.utils.GitHubInstance
import com.intellij.openapi.components.Service
import net.minidev.json.JSONArray
import com.intellij.util.alsoIfNull
import java.net.HttpURLConnection
import java.net.URL


@Service(Service.Level.PROJECT)
class SarifService {

fun loadSarifFile(github: GitHubInstance, repositoryFullName: String, branchName: String): SarifSchema210 {
fun getSarifFromGitHub(github: GitHubInstance, repositoryFullName: String, branchName: String): List<SarifSchema210?> {
val analysisFromGitHub = getAnalysisFromGitHub(github, repositoryFullName, branchName)
val objectMapper = ObjectMapper()
val analysis: List<Root> = objectMapper.readValue(analysisFromGitHub)
if (analysis.isEmpty()) {
return SarifSchema210()

val ids = analysis.filter { it.commit_sha == analysis.first().commit_sha }.map { it.id }

return ids.map { id ->
val sarifFromGitHub = getSarifFromGitHub(github, repositoryFullName, id)
val sarif: SarifSchema210 = objectMapper.readValue(sarifFromGitHub)
sarif.alsoIfNull { SarifSchema210() }
}
val id = analysis.first().id
}

val sarifFromGitHub = getSarifFromGitHub(github, repositoryFullName, id)
fun analyseResult(results: List<Result>): HashMap<String, MutableList<Leaf>> {
val map = HashMap<String, MutableList<Leaf>>()
results.forEach { result ->
val element = leaf(result)
val key = result.rule?.id ?: result.correlationGuid?.toString() ?: result.message.text
if (map.containsKey(key)) {
map[key]?.add(element)
} else {
map[key] = mutableListOf(element)
}
}
return map

return objectMapper.readValue(sarifFromGitHub, SarifSchema210::class.java)
}

fun analyseSarif(sarif: SarifSchema210): HashMap<String, MutableList<Leaf>> {
Expand All @@ -36,21 +52,7 @@ class SarifService {
try {
sarif.runs.forEach { run ->
run?.results?.forEach { result ->
val additionalProperties = result.properties?.additionalProperties ?: mapOf()
val element = Leaf(
leafName = result.message.text,
address = "${result.locations[0].physicalLocation.artifactLocation.uri}:${result.locations[0].physicalLocation.region.startLine}",
steps = result.codeFlows?.get(0)?.threadFlows?.get(0)?.locations?.map { "${it.location.physicalLocation.artifactLocation.uri}:${it.location.physicalLocation.region.startLine}" }
?: listOf(),
location = result.locations[0].physicalLocation.artifactLocation.uri,
ruleId = result.ruleId,
ruleName = result.rule?.id ?: "",
ruleDescription = result.message.text,
level = result.level.toString(),
kind = result.kind.toString(),
githubAlertNumber = additionalProperties["github/alertNumber"]?.toString() ?: "",
githubAlertUrl = additionalProperties["github/alertUrl"]?.toString() ?: ""
)
val element = leaf(result)
val key = result.rule?.id ?: result.correlationGuid?.toString() ?: result.message.text
if (map.containsKey(key)) {
map[key]?.add(element)
Expand All @@ -65,7 +67,26 @@ class SarifService {
return map
}

fun getPullRequests(github: GitHubInstance, repositoryFullName: String, branchName: String = "main"): JSONArray {
private fun leaf(result: Result): Leaf {
val additionalProperties = result.properties?.additionalProperties ?: mapOf()
val element = Leaf(
leafName = result.message.text,
address = "${result.locations[0].physicalLocation.artifactLocation.uri}:${result.locations[0].physicalLocation.region.startLine}",
steps = result.codeFlows?.get(0)?.threadFlows?.get(0)?.locations?.map { "${it.location.physicalLocation.artifactLocation.uri}:${it.location.physicalLocation.region.startLine}" }
?: listOf(),
location = result.locations[0].physicalLocation.artifactLocation.uri,
ruleId = result.ruleId,
ruleName = result.rule?.id ?: "",
ruleDescription = result.message.text,
level = result.level.toString(),
kind = result.kind.toString(),
githubAlertNumber = additionalProperties["github/alertNumber"]?.toString() ?: "",
githubAlertUrl = additionalProperties["github/alertUrl"]?.toString() ?: ""
)
return element
}

fun getPullRequests(github: GitHubInstance, repositoryFullName: String, branchName: String = "main"): List<*>? {
val head = "${repositoryFullName.split("/")[0]}:$branchName"
val connection = URL("${github.apiBase}/repos/$repositoryFullName/pulls?state=open&head=$head")
.openConnection() as HttpURLConnection
Expand All @@ -85,8 +106,7 @@ class SarifService {
val response = connection.inputStream.bufferedReader().readText()

connection.disconnect()

return ObjectMapper().readValue(response)
return ObjectMapper().readValue(response, List::class.java)
}

private fun getAnalysisFromGitHub(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package com.github.adrienpessu.sarifviewer.toolWindow

import com.contrastsecurity.sarif.Result
import com.contrastsecurity.sarif.SarifSchema210
import com.fasterxml.jackson.databind.ObjectMapper
import com.github.adrienpessu.sarifviewer.configurable.Settings
import com.github.adrienpessu.sarifviewer.configurable.SettingsState
import com.github.adrienpessu.sarifviewer.exception.SarifViewerException
import com.github.adrienpessu.sarifviewer.models.BranchItemComboBox
import com.github.adrienpessu.sarifviewer.models.Leaf
import com.github.adrienpessu.sarifviewer.services.SarifService
import com.github.adrienpessu.sarifviewer.utils.GitHubInstance
Expand Down Expand Up @@ -71,9 +73,8 @@ class SarifViewerWindowFactory : ToolWindowFactory {
private var main = ScrollPaneFactory.createScrollPane()
private val details = JBTabbedPane()
private val splitPane = JSplitPane(JSplitPane.VERTICAL_SPLIT, false, main, details)
private var sarif: SarifSchema210 = SarifSchema210()
private var myList = JTree()
private var selectList = ComboBox(arrayOf("main"))
private var comboBranchPR = ComboBox(arrayOf(BranchItemComboBox(0, "main", "", "")))
private val refreshButton: JButton = JButton("Refresh from GH")
private val infos = JEditorPane()
private val steps = JEditorPane()
Expand Down Expand Up @@ -114,7 +115,10 @@ class SarifViewerWindowFactory : ToolWindowFactory {
})
}

private fun JBPanel<JBPanel<*>>.loadDataAndUI(repository: GitRepository, refreshCombo: Boolean = true) {
private fun JBPanel<JBPanel<*>>.loadDataAndUI(
repository: GitRepository,
selectedCombo: BranchItemComboBox? = null
) {
val currentBranch = repository.currentBranch

val remote = repository.remotes.firstOrNull {
Expand All @@ -140,7 +144,7 @@ class SarifViewerWindowFactory : ToolWindowFactory {
return
}

if (refreshCombo) {
if (selectedCombo == null) {
sarifGitHubRef = "refs/heads/${currentBranch?.name ?: "refs/heads/main"}"
}

Expand All @@ -151,17 +155,32 @@ class SarifViewerWindowFactory : ToolWindowFactory {

if (repositoryFullName.isNotEmpty() && currentBranch?.name?.isNotEmpty() == true) {
try {
if (refreshCombo) {
if (selectedCombo == null) {
populateCombo(currentBranch, github, repositoryFullName)
}

val map = extractSarif(github, repositoryFullName)
val map = extractSarif(github, repositoryFullName, selectedCombo?.head)
if (map.isEmpty()) {
val element = Leaf(
leafName = "",
address = "",
steps = listOf(),
location = "",
ruleId = "",
ruleName = "",
ruleDescription = "",
level = "",
kind = "",
githubAlertNumber = "",
githubAlertUrl = "",
)
map["No SARIF file found for the repository $repositoryFullName and ref $sarifGitHubRef"] =
listOf(element).toMutableList()
displayError("No SARIF file found for the repository $repositoryFullName and ref $sarifGitHubRef")
} else {
thisLogger().info("Load result for the repository $repositoryFullName and ref $sarifGitHubRef")
buildContent(map, github, repositoryFullName, currentBranch)
}
buildContent(map, github, repositoryFullName, currentBranch)
} catch (e: SarifViewerException) {
add(JLabel(e.message))
thisLogger().warn(e.message)
Expand Down Expand Up @@ -230,27 +249,27 @@ class SarifViewerWindowFactory : ToolWindowFactory {
jToolBar.alignmentX = Component.LEFT_ALIGNMENT
jToolBar.add(refreshButton)

selectList.addActionListener(ActionListener() { event ->
comboBranchPR.addActionListener(ActionListener() { event ->

Check warning on line 252 in src/main/kotlin/com/github/adrienpessu/sarifviewer/toolWindow/SarifViewerWindowFactory.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Redundant SAM constructor

Redundant SAM-constructor

Check notice on line 252 in src/main/kotlin/com/github/adrienpessu/sarifviewer/toolWindow/SarifViewerWindowFactory.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Unnecessary parentheses in function call with lambda

Unnecessary parentheses in function call with lambda
val comboBox = event.source as JComboBox<*>
if (event.actionCommand == "comboBoxChanged" && comboBox.selectedItem != null) {
val selectedOption = comboBox.selectedItem
sarifGitHubRef = if (selectedOption?.toString()?.startsWith("pr") == true) {
"refs/pull/${selectedOption.toString().split(" ")[0].removePrefix("pr")}/merge"
val selectedOption = comboBox.selectedItem as BranchItemComboBox
sarifGitHubRef = if (selectedOption.prNumber != 0) {
"refs/pull/${selectedOption.prNumber}/merge"
} else {
"refs/heads/$selectedOption"
"refs/heads/${selectedOption.head}"
}

clearJSplitPane()
val repository = GitRepositoryManager.getInstance(project).repositories.firstOrNull()
if (repository != null) {
loadDataAndUI(repository, false)
loadDataAndUI(repository, selectedOption)
} else {
add(JLabel("No Git repository found"))
}
}
})

jToolBar.add(selectList)
jToolBar.add(comboBranchPR)

val localFileButton = JButton("📂")
localFileButton.setSize(10, 10)
Expand Down Expand Up @@ -394,12 +413,28 @@ class SarifViewerWindowFactory : ToolWindowFactory {

private fun extractSarif(
github: GitHubInstance,
repositoryFullName: String
repositoryFullName: String,
base: String? = null
): HashMap<String, MutableList<Leaf>> {
sarif = service.loadSarifFile(github, repositoryFullName, sarifGitHubRef)
val sarifs = service.getSarifFromGitHub(github, repositoryFullName, sarifGitHubRef).filterNotNull()
val results = sarifs.flatMap { it.runs?.get(0)?.results ?: emptyList() }
var map = HashMap<String, MutableList<Leaf>>()
if (sarif.runs?.isEmpty() == false) {
map = service.analyseSarif(sarif)
if (sarifs.isNotEmpty()) {
if (sarifGitHubRef.startsWith("refs/pull/") && base != null) {
val resultsToDisplay = ArrayList<Result>()
val sarifMainBranch = service.getSarifFromGitHub(github, repositoryFullName, base).filterNotNull()
val mainResults: List<Result> = sarifMainBranch.flatMap { it.runs?.get(0)?.results ?: emptyList() }

for (currentResult in results) {
if (mainResults.none { it.ruleId == currentResult.ruleId && it.message.text == currentResult.message.text }) {
resultsToDisplay.add(currentResult)
}
}
map = service.analyseResult(resultsToDisplay)
} else {
map = sarifs.map { service.analyseSarif(it) }.reduce { acc, item -> acc.apply { putAll(item) } }
}

}

return map
Expand All @@ -424,14 +459,22 @@ class SarifViewerWindowFactory : ToolWindowFactory {
github: GitHubInstance,
repositoryFullName: String
) {
selectList.removeAllItems()
selectList.addItem(currentBranch?.name ?: "main")
comboBranchPR.removeAllItems()
comboBranchPR.addItem(BranchItemComboBox(0, currentBranch?.name ?: "main", "", ""))
val pullRequests =
service.getPullRequests(github, repositoryFullName, sarifGitHubRef.split('/', limit = 3).last())
if (pullRequests.isNotEmpty()) {
if (pullRequests?.isNotEmpty() == true) {
pullRequests.forEach {
val currentPr = it as LinkedHashMap<*, *>
selectList.addItem("pr${currentPr["number"]} (${currentPr["title"]})")
comboBranchPR.addItem(
BranchItemComboBox(
currentPr["number"] as Int,
(currentPr["base"] as LinkedHashMap<String, String>)["ref"] ?: "",
(currentPr["head"] as LinkedHashMap<String, String>)["ref"] ?: "",
currentPr["title"].toString(),
(currentPr["head"] as LinkedHashMap<String, String>)["commit_sha"] ?: ""
)
)
}
}
}
Expand Down

0 comments on commit 9194dc1

Please sign in to comment.