KT-58662 Fix build reports for Gradle 8.1 with Configuration Cache
(cherry picked from commit af05f4c2010b69ebf13956cc9c97dfd4b57f15f0)
diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BuildReportsIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BuildReportsIT.kt
index 060e6e6..81ebf71 100644
--- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BuildReportsIT.kt
+++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BuildReportsIT.kt
@@ -29,6 +29,11 @@
get() = projectPath.getSingleFileInDir("build/reports/kotlin-build")
@DisplayName("Build report is created")
+ @GradleTestVersions(
+ minVersion = TestVersions.Gradle.MIN_SUPPORTED,
+ additionalVersions = [TestVersions.Gradle.G_7_6, TestVersions.Gradle.G_8_0],
+ maxVersion = TestVersions.Gradle.G_8_1
+ )
@GradleTest
fun testBuildReportSmokeTest(gradleVersion: GradleVersion) {
project("simpleProject", gradleVersion) {
@@ -43,6 +48,11 @@
}
@DisplayName("Build report output property accepts only certain values")
+ @GradleTestVersions(
+ minVersion = TestVersions.Gradle.MIN_SUPPORTED,
+ additionalVersions = [TestVersions.Gradle.G_7_6, TestVersions.Gradle.G_8_0],
+ maxVersion = TestVersions.Gradle.G_8_1
+ )
@GradleTest
fun testBuildReportOutputProperty(gradleVersion: GradleVersion) {
project("simpleProject", gradleVersion) {
@@ -53,24 +63,44 @@
}
@DisplayName("Build metrics produces valid report")
+ @GradleTestVersions(
+ minVersion = TestVersions.Gradle.MIN_SUPPORTED,
+ additionalVersions = [TestVersions.Gradle.G_7_6, TestVersions.Gradle.G_8_0],
+ maxVersion = TestVersions.Gradle.G_8_1
+ )
@GradleTest
fun testBuildMetricsSmokeTest(gradleVersion: GradleVersion) {
testBuildReportInFile("simpleProject", "assemble", gradleVersion)
}
@DisplayName("Build metrics produces valid report for mpp-jvm")
+ @GradleTestVersions(
+ minVersion = TestVersions.Gradle.MIN_SUPPORTED,
+ additionalVersions = [TestVersions.Gradle.G_7_6, TestVersions.Gradle.G_8_0],
+ maxVersion = TestVersions.Gradle.G_8_1
+ )
@GradleTest
fun testBuildMetricsForMppJvm(gradleVersion: GradleVersion) {
testBuildReportInFile("mppJvmWithJava", "assemble", gradleVersion)
}
@DisplayName("Build metrics produces valid report for mpp-js")
+ @GradleTestVersions(
+ minVersion = TestVersions.Gradle.MIN_SUPPORTED,
+ additionalVersions = [TestVersions.Gradle.G_7_6, TestVersions.Gradle.G_8_0],
+ maxVersion = TestVersions.Gradle.G_8_1
+ )
@GradleTest
fun testBuildMetricsForMppJs(gradleVersion: GradleVersion) {
testBuildReportInFile("kotlin-js-package-module-name", "assemble", gradleVersion)
}
@DisplayName("Build metrics produces valid report for JS project")
+ @GradleTestVersions(
+ minVersion = TestVersions.Gradle.MIN_SUPPORTED,
+ additionalVersions = [TestVersions.Gradle.G_7_6, TestVersions.Gradle.G_8_0],
+ maxVersion = TestVersions.Gradle.G_8_1
+ )
@GradleTest
fun testBuildMetricsForJsProject(gradleVersion: GradleVersion) {
testBuildReportInFile("kotlin-js-plugin-project", "compileKotlinJs", gradleVersion,
@@ -119,6 +149,11 @@
}
@DisplayName("Compiler build metrics report is produced")
+ @GradleTestVersions(
+ minVersion = TestVersions.Gradle.MIN_SUPPORTED,
+ additionalVersions = [TestVersions.Gradle.G_7_6, TestVersions.Gradle.G_8_0],
+ maxVersion = TestVersions.Gradle.G_8_1
+ )
@GradleTest
fun testCompilerBuildMetricsSmokeTest(gradleVersion: GradleVersion) {
project("simpleProject", gradleVersion) {
@@ -135,6 +170,11 @@
}
@DisplayName("with no kotlin task executed")
+ @GradleTestVersions(
+ minVersion = TestVersions.Gradle.MIN_SUPPORTED,
+ additionalVersions = [TestVersions.Gradle.G_7_6, TestVersions.Gradle.G_8_0],
+ maxVersion = TestVersions.Gradle.G_8_1
+ )
@GradleTest
fun testFileReportWithoutKotlinTask(gradleVersion: GradleVersion) {
project("simpleProject", gradleVersion) {
@@ -149,6 +189,11 @@
}
@DisplayName("validation")
+ @GradleTestVersions(
+ minVersion = TestVersions.Gradle.MIN_SUPPORTED,
+ additionalVersions = [TestVersions.Gradle.G_7_6, TestVersions.Gradle.G_8_0],
+ maxVersion = TestVersions.Gradle.G_8_1
+ )
@GradleTest
fun testSingleBuildMetricsFileValidation(gradleVersion: GradleVersion) {
project("simpleProject", gradleVersion) {
@@ -161,6 +206,11 @@
}
@DisplayName("deprecated property")
+ @GradleTestVersions(
+ minVersion = TestVersions.Gradle.MIN_SUPPORTED,
+ additionalVersions = [TestVersions.Gradle.G_7_6, TestVersions.Gradle.G_8_0],
+ maxVersion = TestVersions.Gradle.G_8_1
+ )
@GradleTest
fun testDeprecatedAndNewSingleBuildMetricsFile(gradleVersion: GradleVersion) {
project("simpleProject", gradleVersion) {
@@ -176,6 +226,11 @@
}
@DisplayName("smoke")
+ @GradleTestVersions(
+ minVersion = TestVersions.Gradle.MIN_SUPPORTED,
+ additionalVersions = [TestVersions.Gradle.G_7_6, TestVersions.Gradle.G_8_0],
+ maxVersion = TestVersions.Gradle.G_8_1
+ )
@GradleTest
fun testSingleBuildMetricsFileSmoke(gradleVersion: GradleVersion) {
project("simpleProject", gradleVersion) {
@@ -195,6 +250,11 @@
}
@DisplayName("custom value limit")
+ @GradleTestVersions(
+ minVersion = TestVersions.Gradle.MIN_SUPPORTED,
+ additionalVersions = [TestVersions.Gradle.G_7_6, TestVersions.Gradle.G_8_0],
+ maxVersion = TestVersions.Gradle.G_8_1
+ )
@GradleTest
fun testCustomValueLimitForBuildScan(gradleVersion: GradleVersion) {
project("simpleProject", gradleVersion, buildOptions = defaultBuildOptions.copy(logLevel = LogLevel.DEBUG)) {
@@ -210,6 +270,11 @@
}
@DisplayName("build scan listener lazy initialisation")
+ @GradleTestVersions(
+ minVersion = TestVersions.Gradle.MIN_SUPPORTED,
+ additionalVersions = [TestVersions.Gradle.G_7_6, TestVersions.Gradle.G_8_0],
+ maxVersion = TestVersions.Gradle.G_8_1
+ )
@GradleTest
fun testBuildScanListenerLazyInitialisation(gradleVersion: GradleVersion) {
project("simpleProject", gradleVersion, buildOptions = defaultBuildOptions.copy(logLevel = LogLevel.DEBUG)) {
@@ -226,6 +291,11 @@
private val kotlinErrorPath = ".gradle/kotlin/errors"
@DisplayName("Error file is created")
+ @GradleTestVersions(
+ minVersion = TestVersions.Gradle.MIN_SUPPORTED,
+ additionalVersions = [TestVersions.Gradle.G_7_6, TestVersions.Gradle.G_8_0],
+ maxVersion = TestVersions.Gradle.G_8_1
+ )
@GradleTest
fun testErrorsFileSmokeTest(gradleVersion: GradleVersion) {
project("simpleProject", gradleVersion) {
@@ -265,6 +335,11 @@
}
@DisplayName("Error file should not contain compilation exceptions")
+ @GradleTestVersions(
+ minVersion = TestVersions.Gradle.MIN_SUPPORTED,
+ additionalVersions = [TestVersions.Gradle.G_7_6, TestVersions.Gradle.G_8_0],
+ maxVersion = TestVersions.Gradle.G_8_1
+ )
@GradleTest
fun testErrorsFileWithCompilationError(gradleVersion: GradleVersion) {
project("simpleProject", gradleVersion) {
@@ -280,6 +355,11 @@
}
@DisplayName("build scan metrics validation")
+ @GradleTestVersions(
+ minVersion = TestVersions.Gradle.MIN_SUPPORTED,
+ additionalVersions = [TestVersions.Gradle.G_7_6, TestVersions.Gradle.G_8_0],
+ maxVersion = TestVersions.Gradle.G_8_1
+ )
@GradleTest
fun testBuildScanMetricsValidation(gradleVersion: GradleVersion) {
project("simpleProject", gradleVersion) {
diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/ConfigurationCacheIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/ConfigurationCacheIT.kt
index 57d1a93..e04d1ac 100644
--- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/ConfigurationCacheIT.kt
+++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/ConfigurationCacheIT.kt
@@ -232,6 +232,11 @@
@JvmGradlePluginTests
@DisplayName("with build report")
+ @GradleTestVersions(
+ minVersion = TestVersions.Gradle.MIN_SUPPORTED,
+ additionalVersions = [TestVersions.Gradle.G_7_6, TestVersions.Gradle.G_8_0],
+ maxVersion = TestVersions.Gradle.G_8_1
+ )
@GradleTest
fun testBuildReportSmokeTestForConfigurationCache(gradleVersion: GradleVersion) {
project(
@@ -251,6 +256,11 @@
@JvmGradlePluginTests
@DisplayName("with build scan report")
+ @GradleTestVersions(
+ minVersion = TestVersions.Gradle.MIN_SUPPORTED,
+ additionalVersions = [TestVersions.Gradle.G_7_6], //build scan reports doesn't work properly for Gradle 8.0
+ maxVersion = TestVersions.Gradle.G_8_1
+ )
@GradleTest
fun testBuildScanReportSmokeTestForConfigurationCache(gradleVersion: GradleVersion) {
project("simpleProject", gradleVersion) {
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/StatisticsBuildFlowManager.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/StatisticsBuildFlowManager.kt
index 7bcaf47..cc937c0 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/StatisticsBuildFlowManager.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/StatisticsBuildFlowManager.kt
@@ -54,7 +54,7 @@
}
override fun execute(parameters: Parameters) {
- parameters.buildMetricService.orNull?.addCollectedTagsToBuildScan(parameters.buildScanExtensionHolder.orNull)
+ parameters.buildMetricService.orNull?.addBuildScanReport(parameters.buildScanExtensionHolder.orNull)
}
}
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/report/BuildMetricsService.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/report/BuildMetricsService.kt
index 3348468..8c3aaf9 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/report/BuildMetricsService.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/report/BuildMetricsService.kt
@@ -17,6 +17,7 @@
import org.gradle.api.services.BuildServiceParameters
import org.gradle.api.tasks.Internal
import org.gradle.tooling.events.FailureResult
+import org.gradle.tooling.events.FinishEvent
import org.gradle.tooling.events.OperationCompletionListener
import org.gradle.tooling.events.task.TaskExecutionResult
import org.gradle.tooling.events.task.TaskFailureResult
@@ -52,7 +53,7 @@
val buildMetricsService: Property<BuildMetricsService?>
}
-abstract class BuildMetricsService : BuildService<BuildMetricsService.Parameters>, AutoCloseable {
+abstract class BuildMetricsService : BuildService<BuildMetricsService.Parameters>, AutoCloseable, OperationCompletionListener {
//Part of BuildReportService
interface Parameters : BuildServiceParameters {
@@ -165,6 +166,14 @@
buildReportService.close(buildOperationRecords, failureMessages.toList(), parameters.toBuildReportParameters())
}
+ override fun onFinish(event: FinishEvent?) {
+ if (event is TaskFinishEvent) {
+ val buildOperation = updateBuildOperationRecord(event)
+ val buildParameters = parameters.toBuildReportParameters()
+ buildReportService.onFinish(event, buildOperation, buildParameters)
+ }
+ }
+
companion object {
private val serviceClass = BuildMetricsService::class.java
private val serviceName = "${serviceClass.name}_${serviceClass.classLoader.hashCode()}"
@@ -221,35 +230,46 @@
}
- private fun subscribeForTaskEvents(project: Project, buildMetricService: Provider<BuildMetricsService>) {
+ private fun subscribeForTaskEvents(project: Project, buildMetricServiceProvider: Provider<BuildMetricsService>) {
// BuildScanExtension cant be parameter nor BuildService's field
val buildScanExtension = project.rootProject.extensions.findByName("buildScan")
val buildScan = buildScanExtension?.let { BuildScanExtensionHolder(it) }
+ val buildMetricService = buildMetricServiceProvider.get()
+ val buildScanReportSettings = buildMetricService.parameters.reportingSettings.orNull?.buildScanReportSettings
+ val gradle80withBuildScanReport =
+ GradleVersion.current().baseVersion == GradleVersion.version("8.0") && buildScanReportSettings != null && buildScan != null
- val buildScanReportSettings = buildMetricService.get().parameters.reportingSettings.orNull?.buildScanReportSettings
- BuildEventsListenerRegistryHolder.getInstance(project).listenerRegistry.onTaskCompletion(project.provider {
- OperationCompletionListener { event ->
- if (event is TaskFinishEvent) {
- val buildOperation = buildMetricService.get().updateBuildOperationRecord(event)
- val buildParameters = buildMetricService.get().parameters.toBuildReportParameters()
- val buildReportService = buildMetricService.map { it.buildReportService }
- buildReportService.get().onFinish(event, buildOperation, buildParameters, buildScan)
- }
- }
- })
+ if (!gradle80withBuildScanReport) {
+ BuildEventsListenerRegistryHolder.getInstance(project).listenerRegistry.onTaskCompletion(buildMetricServiceProvider)
+ }
+
if (buildScanReportSettings != null) {
- buildScan?.also {
- buildMetricService.map { it.buildReportService }.get().initBuildScanTags(
- it, buildMetricService.get().parameters.label.orNull
- )
- if (GradleVersion.current().baseVersion < GradleVersion.version("8.0")) {
- it.buildScan.buildFinished {
- buildMetricService.map { it.addCollectedTagsToBuildScan(buildScan) }
+ buildScan?.also { buildScanHolder ->
+ when {
+ GradleVersion.current().baseVersion < GradleVersion.version("8.0") -> {
+ buildScanHolder.buildScan.buildFinished {
+ buildMetricServiceProvider.map {it.addBuildScanReport(buildScan)}.get()
+ }
}
+ GradleVersion.current().baseVersion < GradleVersion.version("8.1") -> {
+ buildMetricService.buildReportService.initBuildScanTags(buildScan, buildMetricService.parameters.label.orNull)
+ BuildEventsListenerRegistryHolder.getInstance(project).listenerRegistry.onTaskCompletion(project.provider {
+ OperationCompletionListener { event ->
+ if (event is TaskFinishEvent) {
+ val buildOperation = buildMetricService.updateBuildOperationRecord(event)
+ val buildParameters = buildMetricService.parameters.toBuildReportParameters()
+ val buildReportService = buildMetricServiceProvider.map { it.buildReportService }.get()
+ buildReportService.addBuildScanReport(event, buildOperation, buildParameters, buildScanHolder)
+ buildReportService.onFinish(event, buildOperation, buildParameters)
+ }
+ }
+
+ })
+ }
+ else -> {}//do nothing, BuildScanFlowAction is used
}
}
}
-
}
fun registerIfAbsent(project: Project) = registerIfAbsentImpl(project)?.also { serviceProvider ->
@@ -276,11 +296,13 @@
}
}
- internal fun addCollectedTagsToBuildScan(buildScan: BuildScanExtensionHolder?) {
+ internal fun addBuildScanReport(buildScan: BuildScanExtensionHolder?) {
if (buildScan == null) return
+ buildReportService.initBuildScanTags(buildScan, parameters.label.orNull)
+ buildReportService.addBuildScanReport(buildOperationRecords, parameters.toBuildReportParameters(), buildScan)
+ parameters.buildConfigurationTags.orNull?.forEach { buildScan.buildScan.tag(it.readableString) }
buildReportService.addCollectedTags(buildScan)
}
-
}
internal class TaskRecord(
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/report/BuildReportsService.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/report/BuildReportsService.kt
index f4a6eda..8fa5a39 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/report/BuildReportsService.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/report/BuildReportsService.kt
@@ -68,21 +68,7 @@
it.buildReportDir,
parameters.projectName,
it.includeMetricsInReport,
- buildOperationRecords.mapNotNull {
- prepareData(
- taskResult = null,
- it.path,
- it.startTimeMs,
- it.totalTimeMs + it.startTimeMs,
- parameters.projectName,
- buildUuid,
- parameters.label,
- parameters.kotlinVersion,
- it,
- onlyKotlinTask = false,
- parameters.additionalTags
- )
- },
+ transformOperationRecordsToCompileStatisticsData(buildOperationRecords, parameters, onlyKotlinTask = false),
parameters.startParameters,
failureMessages.filter { it.isNotEmpty() },
loggerAdapter
@@ -101,11 +87,32 @@
executorService.shutdown()
}
+ private fun transformOperationRecordsToCompileStatisticsData(
+ buildOperationRecords: Collection<BuildOperationRecord>,
+ parameters: BuildReportParameters,
+ onlyKotlinTask: Boolean,
+ metricsToShow: Set<String>? = null
+ ) = buildOperationRecords.mapNotNull {
+ prepareData(
+ taskResult = null,
+ it.path,
+ it.startTimeMs,
+ it.totalTimeMs + it.startTimeMs,
+ parameters.projectName,
+ buildUuid,
+ parameters.label,
+ parameters.kotlinVersion,
+ it,
+ onlyKotlinTask = onlyKotlinTask,
+ parameters.additionalTags,
+ metricsToShow = metricsToShow
+ )
+ }
+
fun onFinish(
event: TaskFinishEvent, buildOperation: BuildOperationRecord,
- parameters: BuildReportParameters, buildScan: BuildScanExtensionHolder?
+ parameters: BuildReportParameters
) {
- buildScan?.also { addBuildScanReport(event, buildOperation, parameters, it) }
addHttpReport(event, buildOperation, parameters)
}
@@ -177,7 +184,7 @@
}
- private fun addBuildScanReport(
+ internal fun addBuildScanReport(
event: TaskFinishEvent,
buildOperationRecord: BuildOperationRecord,
parameters: BuildReportParameters,
@@ -201,6 +208,28 @@
}
}
+ internal fun addBuildScanReport(
+ buildOperationRecords: Collection<BuildOperationRecord>,
+ parameters: BuildReportParameters,
+ buildScanExtension: BuildScanExtensionHolder
+ ) {
+ val buildScanSettings = parameters.reportingSettings.buildScanReportSettings ?: return
+
+ val (collectDataDuration, compileStatData) = measureTimeMillisWithResult {
+ transformOperationRecordsToCompileStatisticsData(
+ buildOperationRecords,
+ parameters,
+ onlyKotlinTask = true,
+ metricsToShow = buildScanSettings.metrics
+ )
+ }
+ log.debug("Collect data takes $collectDataDuration: $compileStatData")
+
+ compileStatData.forEach {
+ addBuildScanReport(it, buildScanSettings.customValueLimit, buildScanExtension)
+ }
+ }
+
private fun addBuildScanReport(data: CompileStatisticsData, customValuesLimit: Int, buildScan: BuildScanExtensionHolder) {
val elapsedTime = measureTimeMillis {
tags.addAll(data.tags)