-
Notifications
You must be signed in to change notification settings - Fork 39
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
gradle-plugin: add task to merge sarif reports (#1456)
### What's done: * Added task to merge SARIF reports This pull request closes #1452
- Loading branch information
Showing
8 changed files
with
199 additions
and
33 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
101 changes: 101 additions & 0 deletions
101
...gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/tasks/SarifReportMergeTask.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
package org.cqfn.diktat.plugin.gradle.tasks | ||
|
||
import org.cqfn.diktat.plugin.gradle.DiktatExtension | ||
import org.cqfn.diktat.plugin.gradle.DiktatGradlePlugin.Companion.MERGE_SARIF_REPORTS_TASK_NAME | ||
import org.cqfn.diktat.plugin.gradle.DiktatJavaExecTaskBase | ||
import org.cqfn.diktat.plugin.gradle.createReporterFlag | ||
import org.cqfn.diktat.plugin.gradle.getOutputFile | ||
import org.cqfn.diktat.plugin.gradle.isSarifReporterActive | ||
import io.github.detekt.sarif4k.SarifSchema210 | ||
import org.gradle.api.DefaultTask | ||
import org.gradle.api.Project | ||
import org.gradle.api.file.ConfigurableFileCollection | ||
import org.gradle.api.file.RegularFileProperty | ||
import org.gradle.api.tasks.InputFiles | ||
import org.gradle.api.tasks.OutputFile | ||
import org.gradle.api.tasks.PathSensitive | ||
import org.gradle.api.tasks.PathSensitivity | ||
import org.gradle.api.tasks.TaskAction | ||
import org.gradle.api.tasks.TaskExecutionException | ||
import kotlinx.serialization.SerializationException | ||
import kotlinx.serialization.decodeFromString | ||
import kotlinx.serialization.encodeToString | ||
import kotlinx.serialization.json.Json | ||
|
||
/** | ||
* A task to merge SARIF reports produced by diktat check / diktat fix tasks. | ||
*/ | ||
abstract class SarifReportMergeTask : DefaultTask() { | ||
/** | ||
* Source reports that should be merged | ||
*/ | ||
@get:InputFiles | ||
@get:PathSensitive(PathSensitivity.RELATIVE) | ||
abstract val input: ConfigurableFileCollection | ||
|
||
/** | ||
* Destination for the merged report | ||
*/ | ||
@get:OutputFile | ||
abstract val output: RegularFileProperty | ||
|
||
/** | ||
* @throws TaskExecutionException if failed to deserialize SARIF | ||
*/ | ||
@TaskAction | ||
fun mergeReports() { | ||
val sarifReports = input.files | ||
.filter { it.exists() } | ||
.also { logger.info("Merging SARIF reports from files $it") } | ||
.map { | ||
try { | ||
Json.decodeFromString<SarifSchema210>(it.readText()) | ||
} catch (e: SerializationException) { | ||
logger.error("Couldn't deserialize JSON: is ${it.canonicalPath} a SARIF file?") | ||
throw TaskExecutionException(this, e) | ||
} | ||
} | ||
|
||
if (sarifReports.isEmpty()) { | ||
logger.warn("Cannot perform merging of SARIF reports because no matching files were found; " + | ||
"Is SARIF reporter active?" | ||
) | ||
return | ||
} | ||
|
||
// All reports should contain identical metadata, so we are using the first one as a base. | ||
val templateReport = sarifReports.first() | ||
val allResults = sarifReports.flatMap { sarifSchema -> | ||
sarifSchema.runs | ||
.flatMap { it.results.orEmpty() } | ||
} | ||
val mergedSarif = templateReport.copy( | ||
runs = listOf(templateReport.runs.first().copy(results = allResults)) | ||
) | ||
|
||
output.get().asFile.writeText(Json.encodeToString(mergedSarif)) | ||
} | ||
} | ||
|
||
/** | ||
* @param diktatExtension extension of type [DiktatExtension] | ||
*/ | ||
internal fun Project.configureMergeReportsTask(diktatExtension: DiktatExtension) { | ||
if (path == rootProject.path) { | ||
tasks.register(MERGE_SARIF_REPORTS_TASK_NAME, SarifReportMergeTask::class.java) { reportMergeTask -> | ||
val diktatReportsDir = "${project.buildDir}/reports/diktat" | ||
val mergedReportFile = project.file("$diktatReportsDir/diktat-merged.sarif") | ||
reportMergeTask.outputs.file(mergedReportFile) | ||
reportMergeTask.output.set(mergedReportFile) | ||
} | ||
} | ||
val reportMergeTaskTaskProvider = rootProject.tasks.named(MERGE_SARIF_REPORTS_TASK_NAME, SarifReportMergeTask::class.java) { reportMergeTask -> | ||
if (isSarifReporterActive(createReporterFlag(diktatExtension))) { | ||
getOutputFile(diktatExtension)?.let { reportMergeTask.input.from(it) } | ||
reportMergeTask.shouldRunAfter(tasks.withType(DiktatJavaExecTaskBase::class.java)) | ||
} | ||
} | ||
tasks.withType(DiktatJavaExecTaskBase::class.java).configureEach { diktatJavaExecTaskBase -> | ||
diktatJavaExecTaskBase.finalizedBy(reportMergeTaskTaskProvider) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
34 changes: 34 additions & 0 deletions
34
diktat-gradle-plugin/src/test/kotlin/org/cqfn/diktat/plugin/gradle/ReporterSelectionTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package org.cqfn.diktat.plugin.gradle | ||
|
||
import org.gradle.api.Project | ||
import org.gradle.api.tasks.util.PatternSet | ||
import org.gradle.testfixtures.ProjectBuilder | ||
import org.junit.jupiter.api.Assertions | ||
import org.junit.jupiter.api.BeforeEach | ||
import org.junit.jupiter.api.Test | ||
|
||
class ReporterSelectionTest { | ||
private val projectBuilder = ProjectBuilder.builder() | ||
private lateinit var project: Project | ||
|
||
@BeforeEach | ||
fun setUp() { | ||
project = projectBuilder.build() | ||
// mock kotlin sources | ||
project.mkdir("src/main/kotlin") | ||
project.file("src/main/kotlin/Test.kt").createNewFile() | ||
project.pluginManager.apply(DiktatGradlePlugin::class.java) | ||
} | ||
|
||
@Test | ||
fun `should fallback to plain reporter for unknown reporter types`() { | ||
val diktatExtension = DiktatExtension(PatternSet()).apply { | ||
reporter = "jsonx" | ||
} | ||
|
||
Assertions.assertEquals( | ||
"--reporter=plain", | ||
project.createReporterFlag(diktatExtension) | ||
) | ||
} | ||
} |