From 62d3c4eb728f50a16ba9794aada8046dffbcad52 Mon Sep 17 00:00:00 2001 From: Florian Dreier Date: Mon, 9 Nov 2026 08:32:08 +0100 Subject: [PATCH 1/2] TS-48590 Fix Gradle deprecation warnings of the aggregation plugin Configuration.visible has no effect since Gradle 9.0 and its setter is deprecated since Gradle 9.8, so the plugin no longer sets it. A Java project additionally triggered the Gradle 9.6 deprecation of Project objects as dependency notation, which the map notation avoids while still working on Gradle 8. Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 1 + .../aggregation/ReportAggregationPlugin.kt | 6 +-- .../com/teamscale/DeprecationWarningTest.kt | 46 +++++++++++++++++++ .../com/teamscale/TeamscalePluginTestBase.kt | 5 +- 4 files changed, 53 insertions(+), 5 deletions(-) create mode 100644 teamscale-gradle-plugin/src/test/kotlin/com/teamscale/DeprecationWarningTest.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index 843f63901..4a1699c1c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ We use [semantic versioning](http://semver.org/): - [fix] _agent_, _teamscale-gradle-plugin_, _teamscale-maven-plugin_: A corrupt class file whose class name cannot be read is skipped with a warning instead of failing the coverage report. - [fix] _impacted-test-engine_: A test that a failing assumption aborts is reported as skipped instead of as an error. - [fix] _teamscale-gradle-plugin_: The plugin now works when the build sets `jacoco.excludes` or the JUnit Platform `excludeEngines` of a test task to a read-only collection (for example, `listOf(...)` or `setOf(...)` in the Kotlin DSL). Previously, applying the plugin or running the test task failed with an `UnsupportedOperationException`. +- [fix] _teamscale-gradle-plugin_: Applying `com.teamscale.aggregation` no longer emits deprecation warnings on Gradle 9.6 and newer. - [fix] _teamscale-gradle-plugin_: The default excludes now match Mockito mocks (e.g. `com.company.IFoo$MockitoMock$123`) and Guice fast classes (e.g. `com.company.Foo$$FastClassByGuice$$abc`). Previously the profiler instrumented them, and the testwise coverage report warned that it found coverage for classes that were not provided. # 39.0.0 diff --git a/teamscale-gradle-plugin/src/main/kotlin/com/teamscale/aggregation/ReportAggregationPlugin.kt b/teamscale-gradle-plugin/src/main/kotlin/com/teamscale/aggregation/ReportAggregationPlugin.kt index b0ba46a8e..18021669c 100755 --- a/teamscale-gradle-plugin/src/main/kotlin/com/teamscale/aggregation/ReportAggregationPlugin.kt +++ b/teamscale-gradle-plugin/src/main/kotlin/com/teamscale/aggregation/ReportAggregationPlugin.kt @@ -48,24 +48,22 @@ abstract class ReportAggregationPlugin : Plugin { @get:Inject protected abstract val jvmPluginServices: JvmPluginServices - @Suppress("DEPRECATION") override fun apply(project: Project) { val configurations = project.configurations val reportAggregation = configurations.dependencyScope(REPORT_AGGREGATION_CONFIGURATION_NAME) { description = "A configuration to collect reports across projects." - isVisible = false }.get() val aggregateReportResults = configurations.resolvable(AGGREGATE_REPORT_RESULTS_CONFIGURATION_NAME) { extendsFrom(reportAggregation) description = "Resolvable configuration used to gather files for report aggregation via ArtifactViews, not intended to be used directly" - isVisible = false }.get() project.plugins.withType { - reportAggregation.dependencies.add(project.dependencyFactory.create(project)) + // The map notation is the only way to create a project dependency that works on Gradle 8 and is not deprecated on Gradle 9. + reportAggregation.dependencies.add(project.dependencies.project(mapOf("path" to project.path))) // If the current project is jvm-based, aggregate dependent projects as jvm-based as well. jvmPluginServices.configureAsRuntimeElements(aggregateReportResults) } diff --git a/teamscale-gradle-plugin/src/test/kotlin/com/teamscale/DeprecationWarningTest.kt b/teamscale-gradle-plugin/src/test/kotlin/com/teamscale/DeprecationWarningTest.kt new file mode 100644 index 000000000..a7c1fb3db --- /dev/null +++ b/teamscale-gradle-plugin/src/test/kotlin/com/teamscale/DeprecationWarningTest.kt @@ -0,0 +1,46 @@ +package com.teamscale + +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test + +/** + * Tests that applying the plugins emits no deprecation warnings. Runs on the Gradle version that builds the plugin, + * since new deprecations only show up on newer Gradle versions than the minimum supported one. + */ +class DeprecationWarningTest : TeamscalePluginTestBase() { + + override val gradleVersion: String? = null + + @BeforeEach + fun init() { + rootProject.settingsFile.writeText("rootProject.name = 'deprecations'") + } + + @Test + fun `aggregation plugin emits no deprecation warning`() { + rootProject.buildFile.writeText( + """ +plugins { + id 'com.teamscale.aggregation' +} + """.trimIndent() + ) + + run("help", "--warning-mode=fail") + } + + @Test + fun `aggregation plugin in a Java project emits no deprecation warning`() { + rootProject.buildFile.writeText( + """ +plugins { + id 'java' + id 'com.teamscale' + id 'com.teamscale.aggregation' +} + """.trimIndent() + ) + + run("help", "--warning-mode=fail") + } +} diff --git a/teamscale-gradle-plugin/src/test/kotlin/com/teamscale/TeamscalePluginTestBase.kt b/teamscale-gradle-plugin/src/test/kotlin/com/teamscale/TeamscalePluginTestBase.kt index 41e9a7e12..667946cbf 100644 --- a/teamscale-gradle-plugin/src/test/kotlin/com/teamscale/TeamscalePluginTestBase.kt +++ b/teamscale-gradle-plugin/src/test/kotlin/com/teamscale/TeamscalePluginTestBase.kt @@ -31,6 +31,9 @@ abstract class TeamscalePluginTestBase { System.getProperty("systemTestCoverageAgent")?.takeIf { it.none(Char::isWhitespace) } } + /** The Gradle version to run the builds with, or null for the Gradle distribution that runs the tests. */ + protected open val gradleVersion: String? = TeamscalePlugin.MINIMUM_SUPPORTED_VERSION.version + /** Teamscale mock server to be used during the tests. */ protected lateinit var teamscaleMockServer: TeamscaleMockServer @@ -87,7 +90,7 @@ abstract class TeamscalePluginTestBase { .withProjectDir(rootProject.projectDir) .withPluginClasspath() .withArguments(runnerArgs) - .withGradleVersion(TeamscalePlugin.MINIMUM_SUPPORTED_VERSION.version) + gradleVersion?.let { runner.withGradleVersion(it) } return runner } From e27ebc5ed10f669e61f1aa489dc77f9050f6457f Mon Sep 17 00:00:00 2001 From: Florian Dreier Date: Mon, 9 Nov 2026 09:06:48 +0100 Subject: [PATCH 2/2] TS-48590 Test and declare compatibility with Isolated Projects The multi-module system test project now enables Isolated Projects, so each of its builds fails on a violation of the Gradle plugins. IsolatedProjectsTest ensures that it stays enabled. Co-Authored-By: Claude Opus 5.5 --- .../gradle-project/gradle.properties | 1 + .../com/teamscale/tia/IsolatedProjectsTest.kt | 22 +++++++++++++++++++ teamscale-gradle-plugin/build.gradle.kts | 2 ++ 3 files changed, 25 insertions(+) create mode 100644 system-tests/gradle-multi-module/src/test/kotlin/com/teamscale/tia/IsolatedProjectsTest.kt diff --git a/system-tests/gradle-multi-module/gradle-project/gradle.properties b/system-tests/gradle-multi-module/gradle-project/gradle.properties index e8a5b0e32..2e17348d8 100644 --- a/system-tests/gradle-multi-module/gradle-project/gradle.properties +++ b/system-tests/gradle-multi-module/gradle-project/gradle.properties @@ -2,3 +2,4 @@ org.gradle.configuration-cache=true org.gradle.configuration-cache.problems=FAIL org.gradle.configuration-cache.parallel=true org.gradle.daemon=false +org.gradle.isolated-projects=true diff --git a/system-tests/gradle-multi-module/src/test/kotlin/com/teamscale/tia/IsolatedProjectsTest.kt b/system-tests/gradle-multi-module/src/test/kotlin/com/teamscale/tia/IsolatedProjectsTest.kt new file mode 100644 index 000000000..73a537078 --- /dev/null +++ b/system-tests/gradle-multi-module/src/test/kotlin/com/teamscale/tia/IsolatedProjectsTest.kt @@ -0,0 +1,22 @@ +package com.teamscale.tia + +import com.teamscale.test.commons.SystemTestUtils.runGradle +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +/** + * Checks that the plugins are compatible with [Isolated Projects](https://docs.gradle.org/current/userguide/isolated_projects.html). + * It is enabled via gradle.properties, so every build of the test project fails on a violation. + */ +class IsolatedProjectsTest { + @Test + fun testIsolatedProjects() { + val result = runGradle( + "gradle-project", "clean", + "unitTestAggregateCompactCoverageReport", "unitTestAggregateJUnitReport", + "systemTestAggregateTestwiseCoverageReport" + ) + // Guards against the tests of this module silently running without Isolated Projects. + assertThat(result.stdout).contains("Isolated Projects is an incubating feature") + } +} diff --git a/teamscale-gradle-plugin/build.gradle.kts b/teamscale-gradle-plugin/build.gradle.kts index 00981093d..2185412e5 100644 --- a/teamscale-gradle-plugin/build.gradle.kts +++ b/teamscale-gradle-plugin/build.gradle.kts @@ -42,6 +42,7 @@ gradlePlugin { compatibility { features { configurationCache = true + isolatedProjects = true } } } @@ -54,6 +55,7 @@ gradlePlugin { compatibility { features { configurationCache = true + isolatedProjects = true } } }