diff --git a/.gitignore b/.gitignore index 811c3e5..6a79a0e 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ /.idea .DS_Store build/ +*/.kotlin/* /captures .externalNativeBuild diff --git a/build.gradle.kts b/build.gradle.kts index 49da039..61c9437 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,4 +1,3 @@ -import com.osacky.doctor.DoctorExtension import org.gradle.api.tasks.testing.logging.TestLogEvent // Upgrade transitive dependencies in plugin classpath @@ -18,19 +17,6 @@ buildscript { plugins { alias(libs.plugins.kgp) alias(libs.plugins.versions) - id("com.osacky.doctor") -} - -configure { - disallowMultipleDaemons.set(false) - GCWarningThreshold.set(0.01f) - enableTestCaching.set(false) - downloadSpeedWarningThreshold.set(2.0f) - daggerThreshold.set(100) - javaHome { - ensureJavaHomeMatches.set(true) - ensureJavaHomeIsSet.set(true) - } } tasks.withType(Test::class.java).configureEach { diff --git a/doctor-plugin/build.gradle.kts b/doctor-plugin/build.gradle.kts index 4b06d24..06743c0 100644 --- a/doctor-plugin/build.gradle.kts +++ b/doctor-plugin/build.gradle.kts @@ -46,7 +46,7 @@ gradlePlugin { displayName = "Doctor Plugin" description = "The right prescription for your gradle build." tags.addAll(listOf("doctor", "android")) - implementationClass = "com.osacky.doctor.DoctorPlugin" + implementationClass = "com.osacky.doctor.DoctorSettingsPlugin" } } } diff --git a/doctor-plugin/src/integrationTest/java/com/osacky/doctor/KotlinDaemonFallbackIntegrationTest.kt b/doctor-plugin/src/integrationTest/java/com/osacky/doctor/KotlinDaemonFallbackIntegrationTest.kt index efc00b8..b577c42 100644 --- a/doctor-plugin/src/integrationTest/java/com/osacky/doctor/KotlinDaemonFallbackIntegrationTest.kt +++ b/doctor-plugin/src/integrationTest/java/com/osacky/doctor/KotlinDaemonFallbackIntegrationTest.kt @@ -6,8 +6,8 @@ import org.junit.Test class KotlinDaemonFallbackIntegrationTest : AbstractIntegrationTest() { @Test fun testDisallowKotlinCompileDaemonFallback() { - writeKotlinBuildGradle(true) - writeSettingsFile() + writeKotlinBuildGradle() + writeSettingsFile(true) testProjectRoot.newFolder("src/main/java/foo") testProjectRoot.newFolder("src/test/java/foo") testProjectRoot.writeFileToName( @@ -41,8 +41,8 @@ class KotlinDaemonFallbackIntegrationTest : AbstractIntegrationTest() { @Test fun allowKotlinCompileFallback() { - writeKotlinBuildGradle(false) - writeSettingsFile() + writeKotlinBuildGradle() + writeSettingsFile(false) testProjectRoot.newFolder("src/main/java/foo") testProjectRoot.writeFileToName( "src/main/java/foo/Foo.kt", @@ -62,7 +62,7 @@ class KotlinDaemonFallbackIntegrationTest : AbstractIntegrationTest() { assertThat(result.output).contains("SUCCESS") } - private fun writeSettingsFile() { + private fun writeSettingsFile(allowDaemonFallback: Boolean) { testProjectRoot.writeFileToName( "settings.gradle", """ @@ -72,6 +72,17 @@ class KotlinDaemonFallbackIntegrationTest : AbstractIntegrationTest() { gradlePluginPortal() } } + + plugins { + id "com.osacky.doctor" + } + + doctor { + warnIfKotlinCompileDaemonFallback = $allowDaemonFallback + javaHome { + ensureJavaHomeMatches = false + } + } """.trimIndent(), ) } @@ -80,22 +91,15 @@ class KotlinDaemonFallbackIntegrationTest : AbstractIntegrationTest() { createRunner() .withArguments("check", "-Dkotlin.daemon.jvm.options=invalid_jvm_argument_to_fail_process_startup") - private fun writeKotlinBuildGradle(allowDaemonFallback: Boolean) { + private fun writeKotlinBuildGradle() { testProjectRoot.writeBuildGradle( """ plugins { - id "com.osacky.doctor" id "org.jetbrains.kotlin.jvm" version "1.6.10" } repositories { mavenCentral() } - doctor { - warnIfKotlinCompileDaemonFallback = $allowDaemonFallback - javaHome { - ensureJavaHomeMatches = false - } - } """.trimIndent(), ) } diff --git a/doctor-plugin/src/integrationTest/java/com/osacky/doctor/TestIntegrationTest.kt b/doctor-plugin/src/integrationTest/java/com/osacky/doctor/TestIntegrationTest.kt index 316ca85..14d9d61 100644 --- a/doctor-plugin/src/integrationTest/java/com/osacky/doctor/TestIntegrationTest.kt +++ b/doctor-plugin/src/integrationTest/java/com/osacky/doctor/TestIntegrationTest.kt @@ -12,7 +12,9 @@ class TestIntegrationTest { @Test fun testIgnoreOnEmptyDirectories() { - testProjectRoot.writeBuildGradle( + testProjectRoot.writeBuildGradle("") + val fixtureName = "java-fixture" + testProjectRoot.writeSettingsGradle( """ |plugins { | id "com.osacky.doctor" @@ -25,10 +27,9 @@ class TestIntegrationTest { | failOnEmptyDirectories = true | warnWhenNotUsingParallelGC = false |} - """.trimMargin("|"), + |include '$fixtureName' + """.trimMargin("|") ) - val fixtureName = "java-fixture" - testProjectRoot.newFile("settings.gradle").writeText("include '$fixtureName'") testProjectRoot.setupFixture(fixtureName) testProjectRoot.newFolder("java-fixture", "src", "main", "java", "com", "foo") @@ -46,7 +47,9 @@ class TestIntegrationTest { @Test fun testDirectoriesIgnoredIn6dot8() { - testProjectRoot.writeBuildGradle( + testProjectRoot.writeBuildGradle("") + val fixtureName = "java-fixture" + testProjectRoot.writeSettingsGradle( """ |plugins { | id "com.osacky.doctor" @@ -59,10 +62,9 @@ class TestIntegrationTest { | failOnEmptyDirectories = true | warnWhenNotUsingParallelGC = false |} - """.trimMargin("|"), + |include '$fixtureName' + """.trimMargin("|") ) - val fixtureName = "java-fixture" - testProjectRoot.newFile("settings.gradle").writeText("include '$fixtureName'") testProjectRoot.setupFixture(fixtureName) testProjectRoot.newFolder("java-fixture", "src", "main", "java", "com", "foo") @@ -135,18 +137,8 @@ class TestIntegrationTest { testProjectRoot.writeBuildGradle( """ plugins { - id "com.osacky.doctor" id 'java-library' } - doctor { - disallowMultipleDaemons = false - javaHome { - ensureJavaHomeMatches = false - } - warnWhenNotUsingParallelGC = false - disallowCleanTaskDependencies = $disallowCleanTaskDependencies - } - tasks.register('foo') { doFirst { println 'foo' @@ -158,5 +150,21 @@ class TestIntegrationTest { } """.trimIndent(), ) + + testProjectRoot.writeSettingsGradle( + """ + plugins { + id "com.osacky.doctor" + } + doctor { + disallowMultipleDaemons = false + javaHome { + ensureJavaHomeMatches = false + } + warnWhenNotUsingParallelGC = false + disallowCleanTaskDependencies = $disallowCleanTaskDependencies + } + """.trimIndent() + ) } } diff --git a/doctor-plugin/src/main/java/com/osacky/doctor/AppProjectCollectorBuildService.kt b/doctor-plugin/src/main/java/com/osacky/doctor/AppProjectCollectorBuildService.kt new file mode 100644 index 0000000..cca031a --- /dev/null +++ b/doctor-plugin/src/main/java/com/osacky/doctor/AppProjectCollectorBuildService.kt @@ -0,0 +1,25 @@ +package com.osacky.doctor + +import org.gradle.api.Project +import org.gradle.api.services.BuildService +import org.gradle.api.services.BuildServiceParameters + +abstract class AppProjectCollectorBuildService : BuildService { + private val appProjects = mutableSetOf() + + fun addProject(project: Project) { + appProjects.add(project) + } + + fun getProjects(): Set { + return appProjects + } +} + +fun Project.getAppProjectCollectorBuildService(): AppProjectCollectorBuildService { + return project.gradle.sharedServices.registerIfAbsent( + "appProjectCollector", + AppProjectCollectorBuildService::class.java, + {} + ).get() +} \ No newline at end of file diff --git a/doctor-plugin/src/main/java/com/osacky/doctor/DoctorChildModulePlugin.kt b/doctor-plugin/src/main/java/com/osacky/doctor/DoctorChildModulePlugin.kt new file mode 100644 index 0000000..49e657b --- /dev/null +++ b/doctor-plugin/src/main/java/com/osacky/doctor/DoctorChildModulePlugin.kt @@ -0,0 +1,48 @@ +package com.osacky.doctor + +import com.osacky.doctor.internal.farthestEmptyParent +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.api.tasks.SourceTask +import org.gradle.api.tasks.testing.Test +import org.gradle.util.GradleVersion + +class DoctorChildModulePlugin : Plugin { + override fun apply(target: Project) { + val extension = target.getDoctorExtension() + target.tasks.withType(SourceTask::class.java).configureEach { + if (!gradleIgnoresEmptyDirectories() && extension.failOnEmptyDirectories.get()) { + // Fail build if empty directories are found. These cause build cache misses and should be ignored by Gradle. + doFirst { + source.visit { + if (file.isDirectory && file.listFiles().isEmpty()) { + val farthestEmptyParent = file.farthestEmptyParent() + throw IllegalStateException( + "Empty src dir(s) found. This causes build cache misses. Run the following command to fix it.\n" + + "rmdir ${farthestEmptyParent.absolutePath}", + ) + } + } + } + } + } + // Ensure we are not caching any test tasks. Tests may not declare all inputs properly or depend on things like the date and caching them can lead to dangerous false positives. + target.tasks.withType(Test::class.java).configureEach { + if (!extension.enableTestCaching.get()) { + outputs.upToDateWhen { false } + } + } + target.plugins.whenPluginAdded plugin@{ + if (this.javaClass.name == "com.android.build.gradle.AppPlugin") { + target.getAppProjectCollectorBuildService().addProject(target) + } + } + } + + /** + * Gradle now ignores empty directories starting in 6.8 + * https://docs.gradle.org/6.8-rc-1/release-notes.html#performance-improvements + **/ + private fun gradleIgnoresEmptyDirectories(): Boolean = GradleVersion.current() >= GradleVersion.version("6.8-rc-1") + +} \ No newline at end of file diff --git a/doctor-plugin/src/main/java/com/osacky/doctor/DoctorExtension.kt b/doctor-plugin/src/main/java/com/osacky/doctor/DoctorExtension.kt index d286e8c..33eedeb 100644 --- a/doctor-plugin/src/main/java/com/osacky/doctor/DoctorExtension.kt +++ b/doctor-plugin/src/main/java/com/osacky/doctor/DoctorExtension.kt @@ -2,7 +2,10 @@ package com.osacky.doctor import com.osacky.doctor.AppleRosettaTranslationCheckMode.ERROR import org.gradle.api.Action +import org.gradle.api.GradleException +import org.gradle.api.Project import org.gradle.api.model.ObjectFactory +import org.gradle.api.plugins.ExtraPropertiesExtension import org.gradle.kotlin.dsl.newInstance import org.gradle.kotlin.dsl.property import javax.inject.Inject @@ -100,6 +103,16 @@ open class DoctorExtension( fun javaHome(action: Action) { action.execute(javaHomeHandler) } + + companion object { + const val EXTRAS_KEY = "_doctorExtension_settings" + } +} + +fun Project.getDoctorExtension(): DoctorExtension { + val defaults = extensions.getByType(ExtraPropertiesExtension::class.java).get(DoctorExtension.EXTRAS_KEY) + as? DoctorExtension ?: throw GradleException("Settings extension type mismatch") + return defaults } abstract class JavaHomeHandler diff --git a/doctor-plugin/src/main/java/com/osacky/doctor/DoctorPlugin.kt b/doctor-plugin/src/main/java/com/osacky/doctor/DoctorPlugin.kt index a55a49d..3c173d3 100644 --- a/doctor-plugin/src/main/java/com/osacky/doctor/DoctorPlugin.kt +++ b/doctor-plugin/src/main/java/com/osacky/doctor/DoctorPlugin.kt @@ -11,7 +11,6 @@ import com.osacky.doctor.internal.PillBoxPrinter import com.osacky.doctor.internal.SystemClock import com.osacky.doctor.internal.UnixDaemonChecker import com.osacky.doctor.internal.UnsupportedOsDaemonChecker -import com.osacky.doctor.internal.farthestEmptyParent import com.osacky.doctor.internal.shouldUseCoCaClasses import org.gradle.api.Action import org.gradle.api.GradleException @@ -20,13 +19,10 @@ import org.gradle.api.Project import org.gradle.api.internal.GradleInternal import org.gradle.api.invocation.Gradle import org.gradle.api.tasks.Delete -import org.gradle.api.tasks.SourceTask -import org.gradle.api.tasks.testing.Test import org.gradle.internal.build.event.BuildEventListenerRegistryInternal import org.gradle.internal.jvm.Jvm import org.gradle.internal.operations.BuildOperationListener import org.gradle.internal.operations.BuildOperationListenerManager -import org.gradle.kotlin.dsl.create import org.gradle.kotlin.dsl.support.serviceOf import org.gradle.kotlin.dsl.withType import org.gradle.launcher.daemon.server.scaninfo.DaemonScanInfo @@ -39,7 +35,7 @@ class DoctorPlugin : Plugin { ensureMinimumSupportedGradleVersion() ensureAppliedInProjectRoot(target) - val extension = target.extensions.create("doctor") + val extension = target.getDoctorExtension() val os: OperatingSystem = DefaultNativePlatform.getCurrentOperatingSystem() val cliCommandExecutor = CliCommandExecutor(target) @@ -99,41 +95,11 @@ class DoctorPlugin : Plugin { tagFreshDaemon(target, buildScanApi) - val appPluginProjects = mutableSetOf() - ensureNoCleanTaskDependenciesIfNeeded(target, extension, pillBoxPrinter) - target.subprojects project@{ - tasks.withType(SourceTask::class.java).configureEach { - if (!gradleIgnoresEmptyDirectories() && extension.failOnEmptyDirectories.get()) { - // Fail build if empty directories are found. These cause build cache misses and should be ignored by Gradle. - doFirst { - source.visit { - if (file.isDirectory && file.listFiles().isEmpty()) { - val farthestEmptyParent = file.farthestEmptyParent() - throw IllegalStateException( - "Empty src dir(s) found. This causes build cache misses. Run the following command to fix it.\n" + - "rmdir ${farthestEmptyParent.absolutePath}", - ) - } - } - } - } - } - // Ensure we are not caching any test tasks. Tests may not declare all inputs properly or depend on things like the date and caching them can lead to dangerous false positives. - tasks.withType(Test::class.java).configureEach { - if (!extension.enableTestCaching.get()) { - outputs.upToDateWhen { false } - } - } - plugins.whenPluginAdded plugin@{ - if (this.javaClass.name == "com.android.build.gradle.AppPlugin") { - appPluginProjects.add(this@project) - } - } - } - target.gradle.taskGraph.whenReady { + val service = target.getAppProjectCollectorBuildService() + val appPluginProjects = service.getProjects() // If there is only one application plugin, we don't need to check that we're assembling all the applications. if (appPluginProjects.size <= 1 || extension.allowBuildingAllAndroidAppsSimultaneously.get()) { return@whenReady @@ -274,12 +240,6 @@ class DoctorPlugin : Plugin { ops } - /** - * Gradle now ignores empty directories starting in 6.8 - * https://docs.gradle.org/6.8-rc-1/release-notes.html#performance-improvements - **/ - private fun gradleIgnoresEmptyDirectories(): Boolean = GradleVersion.current() >= GradleVersion.version("6.8-rc-1") - private val Gradle.buildOperationListenerManager get() = (this as GradleInternal).services[BuildOperationListenerManager::class.java] class TheActionThing( diff --git a/doctor-plugin/src/main/java/com/osacky/doctor/DoctorSettingsPlugin.kt b/doctor-plugin/src/main/java/com/osacky/doctor/DoctorSettingsPlugin.kt new file mode 100644 index 0000000..08b8459 --- /dev/null +++ b/doctor-plugin/src/main/java/com/osacky/doctor/DoctorSettingsPlugin.kt @@ -0,0 +1,23 @@ +package com.osacky.doctor + +import org.gradle.api.Plugin +import org.gradle.api.initialization.Settings +import org.gradle.api.plugins.ExtraPropertiesExtension +import org.gradle.kotlin.dsl.create + +class DoctorSettingsPlugin : Plugin { + override fun apply(target: Settings) { + + val extension = target.extensions.create("doctor") + target.gradle.beforeProject { + extensions.getByType(ExtraPropertiesExtension::class.java) + .set(DoctorExtension.EXTRAS_KEY, extension) + + if (this.parent == null) { + plugins.apply(DoctorPlugin::class.java) + } else { + plugins.apply(DoctorChildModulePlugin::class.java) + } + } + } +} \ No newline at end of file diff --git a/doctor-plugin/src/parallelGCTest/java/com/osacky/doctor/ParallelGCIntegrationTest.kt b/doctor-plugin/src/parallelGCTest/java/com/osacky/doctor/ParallelGCIntegrationTest.kt index 7df810a..ccb3b0c 100644 --- a/doctor-plugin/src/parallelGCTest/java/com/osacky/doctor/ParallelGCIntegrationTest.kt +++ b/doctor-plugin/src/parallelGCTest/java/com/osacky/doctor/ParallelGCIntegrationTest.kt @@ -8,7 +8,8 @@ import org.junit.Test class ParallelGCIntegrationTest : AbstractIntegrationTest() { @Test fun testParallelGCWarningEnabled() { - testProjectRoot.writeBuildGradle( + testProjectRoot.writeBuildGradle("") + testProjectRoot.writeSettingsGradle( """ plugins { id "com.osacky.doctor" @@ -39,7 +40,8 @@ class ParallelGCIntegrationTest : AbstractIntegrationTest() { @Test fun testParallelGCWarningWhenUsingParallelGC() { - testProjectRoot.writeBuildGradle( + testProjectRoot.writeBuildGradle("") + testProjectRoot.writeSettingsGradle( """ plugins { id "com.osacky.doctor" diff --git a/doctor-plugin/src/test/java/com/osacky/doctor/ConfigurationCacheTest.kt b/doctor-plugin/src/test/java/com/osacky/doctor/ConfigurationCacheTest.kt index 922de69..6f10291 100644 --- a/doctor-plugin/src/test/java/com/osacky/doctor/ConfigurationCacheTest.kt +++ b/doctor-plugin/src/test/java/com/osacky/doctor/ConfigurationCacheTest.kt @@ -12,7 +12,10 @@ class ConfigurationCacheTest { @Test fun configurationCacheWorks() { - testProjectRoot.writeBuildGradle( + testProjectRoot.writeBuildGradle("") + val fixtureName = "java-fixture" + testProjectRoot.writeFileToName( + "settings.gradle", """ |plugins { | id "com.osacky.doctor" @@ -24,10 +27,9 @@ class ConfigurationCacheTest { | } | warnWhenNotUsingParallelGC = false |} - """.trimMargin("|"), + |include '$fixtureName' + """.trimMargin("|") ) - val fixtureName = "java-fixture" - testProjectRoot.writeFileToName("settings.gradle", "include '$fixtureName'") testProjectRoot.setupFixture(fixtureName) val runner = diff --git a/doctor-plugin/src/test/java/com/osacky/doctor/IsolatedProjectsTest.kt b/doctor-plugin/src/test/java/com/osacky/doctor/IsolatedProjectsTest.kt new file mode 100644 index 0000000..d89245c --- /dev/null +++ b/doctor-plugin/src/test/java/com/osacky/doctor/IsolatedProjectsTest.kt @@ -0,0 +1,59 @@ +package com.osacky.doctor + +import com.google.common.truth.Truth.assertThat +import org.gradle.testkit.runner.GradleRunner +import org.junit.Rule +import org.junit.Test +import org.junit.rules.TemporaryFolder + +class IsolatedProjectsTest { + @get:Rule + val testProjectRoot = TemporaryFolder() + + /** + * Running this test produces an isolated project warning report in the test project because the JVM toolchain is + * set to 8 in /doctor-plugin/build.gradle.kts. Once that is updated to 17 then the warning will go away. + */ + @Test + fun isolatedProjectsWorks() { + testProjectRoot.writeBuildGradle("") + val fixtureName = "java-fixture" + testProjectRoot.writeFileToName( + "settings.gradle", + """ + |plugins { + | id "com.osacky.doctor" + |} + |doctor { + | javaHome { + | disallowMultipleDaemons = false + | ensureJavaHomeMatches = false + | } + | warnWhenNotUsingParallelGC = false + |} + |include '$fixtureName' + """.trimMargin("|") + ) + testProjectRoot.setupFixture(fixtureName) + + val runner = + GradleRunner + .create() + .forwardOutput() + .withArguments("assemble", "--configuration-cache", "-Dorg.gradle.unsafe.isolated-projects=true") + .withProjectDir(testProjectRoot.root) + .withGradleVersion("8.13") + .withPluginClasspath() + + val result = runner.build() + + assertThat(result.output).contains("Isolated projects is an incubating feature.") + assertThat(result.output).contains("Configuration cache entry stored.") + assertThat(result.output).contains("BUILD SUCCESSFUL") + + val resultTwo = runner.build() + assertThat(resultTwo.output).contains("Isolated projects is an incubating feature.") + assertThat(resultTwo.output).contains("Reusing configuration cache.") + assertThat(resultTwo.output).contains("BUILD SUCCESSFUL") + } +} \ No newline at end of file diff --git a/doctor-plugin/src/test/java/com/osacky/doctor/JetifierWarningTest.kt b/doctor-plugin/src/test/java/com/osacky/doctor/JetifierWarningTest.kt index 3cbb209..13602df 100644 --- a/doctor-plugin/src/test/java/com/osacky/doctor/JetifierWarningTest.kt +++ b/doctor-plugin/src/test/java/com/osacky/doctor/JetifierWarningTest.kt @@ -14,7 +14,8 @@ class JetifierWarningTest { @Test fun testJetifierEnabledShowsWarning() { - testProjectRoot.writeBuildGradle( + testProjectRoot.writeBuildGradle("") + testProjectRoot.writeSettingsGradle( """ |plugins { | id "com.osacky.doctor" @@ -58,7 +59,8 @@ class JetifierWarningTest { @Test fun testJetifierDisabledShowNoWarning() { - testProjectRoot.writeBuildGradle( + testProjectRoot.writeBuildGradle("") + testProjectRoot.writeSettingsGradle( """ |plugins { | id "com.osacky.doctor" diff --git a/doctor-plugin/src/test/java/com/osacky/doctor/PluginIntegrationTest.kt b/doctor-plugin/src/test/java/com/osacky/doctor/PluginIntegrationTest.kt index 56caccd..2d880c8 100644 --- a/doctor-plugin/src/test/java/com/osacky/doctor/PluginIntegrationTest.kt +++ b/doctor-plugin/src/test/java/com/osacky/doctor/PluginIntegrationTest.kt @@ -36,7 +36,8 @@ class PluginIntegrationTest constructor( @Test fun testSupportedVersion() { assumeSupportedVersion() - writeBuildGradle( + writeBuildGradle("") + writeSettingsGradle( """ |plugins { | id "com.osacky.doctor" @@ -59,7 +60,8 @@ class PluginIntegrationTest constructor( @Test fun testFailOnOlderVersion() { assumeUnsupportedVersion() - writeBuildGradle( + writeBuildGradle("") + writeSettingsGradle( """ |plugins { | id "com.osacky.doctor" @@ -82,7 +84,8 @@ class PluginIntegrationTest constructor( @Test fun testFailWithMultipleDaemons() { assumeSupportedVersion() - writeBuildGradle( + writeBuildGradle("") + writeSettingsGradle( """ |plugins { | id "com.osacky.doctor" @@ -121,7 +124,8 @@ class PluginIntegrationTest constructor( fun testJavaHomeNotSet() { assumeSupportedVersion() - writeBuildGradle( + writeBuildGradle("") + writeSettingsGradle( """ |plugins { | id "com.osacky.doctor" @@ -136,7 +140,6 @@ class PluginIntegrationTest constructor( |} """.trimMargin("|"), ) - testProjectRoot.newFile("settings.gradle") val result = createRunner() @@ -157,7 +160,8 @@ class PluginIntegrationTest constructor( fun testJavaHomeNotSetWithConsoleError() { assumeSupportedVersion() - writeBuildGradle( + writeBuildGradle("") + writeSettingsGradle( """ |plugins { | id "com.osacky.doctor" @@ -171,7 +175,6 @@ class PluginIntegrationTest constructor( |} """.trimMargin("|"), ) - testProjectRoot.newFile("settings.gradle") val result = createRunner() @@ -193,7 +196,8 @@ class PluginIntegrationTest constructor( fun testJavaHomeNotSetWithCustomMessage() { assumeSupportedVersion() - writeBuildGradle( + writeBuildGradle("") + writeSettingsGradle( """ |plugins { | id "com.osacky.doctor" @@ -207,7 +211,6 @@ class PluginIntegrationTest constructor( |} """.trimMargin("|"), ) - testProjectRoot.newFile("settings.gradle") val result = createRunner() @@ -222,17 +225,19 @@ class PluginIntegrationTest constructor( assumeSupportedVersion() assumeCanRunAndroidBuild() testProjectRoot.newFile("local.properties").writeText("sdk.dir=${androidHome()}\n") - writeBuildGradle( - """ - buildscript { + writeBuildGradle(""" + buildscript { repositories { google() + mavenCentral() } dependencies { classpath("com.android.tools.build:gradle:$agpVersion") } } - + """.trimIndent()) + writeSettingsGradle( + """ plugins { id "com.osacky.doctor" } @@ -243,15 +248,10 @@ class PluginIntegrationTest constructor( } warnWhenNotUsingParallelGC = false } - """.trimIndent(), - ) - - testProjectRoot.writeFileToName( - "settings.gradle", - """ + include 'app-one' include 'app-two' - """.trimMargin(), + """.trimIndent(), ) val srcFolder = testProjectRoot.newFolder("app-one", "src", "main") @@ -305,17 +305,19 @@ class PluginIntegrationTest constructor( assumeSupportedVersion() assumeCanRunAndroidBuild() testProjectRoot.newFile("local.properties").writeText("sdk.dir=${androidHome()}\n") - writeBuildGradle( - """ - buildscript { + writeBuildGradle(""" + buildscript { repositories { google() + mavenCentral() } dependencies { classpath("com.android.tools.build:gradle:$agpVersion") } } - + """.trimIndent()) + writeSettingsGradle( + """ plugins { id "com.osacky.doctor" } @@ -326,15 +328,10 @@ class PluginIntegrationTest constructor( } warnWhenNotUsingParallelGC = false } - """.trimIndent(), - ) - - testProjectRoot.writeFileToName( - "settings.gradle", - """ + include 'app-one' include 'app-two' - """.trimMargin(), + """.trimIndent(), ) val srcFolder = testProjectRoot.newFolder("app-one", "src", "main") @@ -387,7 +384,9 @@ class PluginIntegrationTest constructor( fun testFailOnEmptyDirectories() { assumeSupportedVersion() assumeEmptyDirectoriesInInput() - writeBuildGradle( + writeBuildGradle("") + val fixtureName = "java-fixture" + writeSettingsGradle( """ |plugins { | id "com.osacky.doctor" @@ -400,10 +399,10 @@ class PluginIntegrationTest constructor( | failOnEmptyDirectories = true | warnWhenNotUsingParallelGC = false |} + | + |include '$fixtureName' """.trimMargin("|"), ) - val fixtureName = "java-fixture" - testProjectRoot.newFile("settings.gradle").writeText("include '$fixtureName'") testProjectRoot.setupFixture(fixtureName) testProjectRoot.newFolder("java-fixture", "src", "main", "java", "com", "foo") @@ -418,7 +417,9 @@ class PluginIntegrationTest constructor( @Test fun testDontFailOnEmptyDirectoriesWhenDisabled() { assumeSupportedVersion() - writeBuildGradle( + writeBuildGradle("") + val fixtureName = "java-fixture" + writeSettingsGradle( """ |plugins { | id "com.osacky.doctor" @@ -431,10 +432,10 @@ class PluginIntegrationTest constructor( | failOnEmptyDirectories = false | warnWhenNotUsingParallelGC = false |} + | + |include '$fixtureName' """.trimMargin("|"), ) - val fixtureName = "java-fixture" - testProjectRoot.newFile("settings.gradle").writeText("include '$fixtureName'") testProjectRoot.setupFixture(fixtureName) testProjectRoot.newFolder("java-fixture", "src", "main", "java", "com", "foo") @@ -473,6 +474,10 @@ class PluginIntegrationTest constructor( testProjectRoot.writeBuildGradle(build) } + private fun writeSettingsGradle(settings: String) { + testProjectRoot.writeSettingsGradle(settings) + } + private fun createFileInFolder( folder: File, fileName: String, diff --git a/doctor-plugin/src/test/java/com/osacky/doctor/ProjectRootIntegrationTest.kt b/doctor-plugin/src/test/java/com/osacky/doctor/ProjectRootIntegrationTest.kt index e4c68e6..eb95788 100644 --- a/doctor-plugin/src/test/java/com/osacky/doctor/ProjectRootIntegrationTest.kt +++ b/doctor-plugin/src/test/java/com/osacky/doctor/ProjectRootIntegrationTest.kt @@ -26,6 +26,6 @@ class ProjectRootIntegrationTest { .withArguments("assemble") .buildAndFail() - assertThat(result.output).contains("Gradle Doctor must be applied in the project root.") + assertThat(result.output).contains("org.gradle.api.internal.project.DefaultProject_Decorated cannot be cast to org.gradle.api.initialization.Settings") } } diff --git a/doctor-plugin/src/test/java/com/osacky/doctor/TestDaggerTime.kt b/doctor-plugin/src/test/java/com/osacky/doctor/TestDaggerTime.kt index feedfd4..3d97b01 100644 --- a/doctor-plugin/src/test/java/com/osacky/doctor/TestDaggerTime.kt +++ b/doctor-plugin/src/test/java/com/osacky/doctor/TestDaggerTime.kt @@ -13,7 +13,8 @@ class TestDaggerTime { @Test fun testDaggerJvm() { val fixtureName = "dagger-jvm" - testProjectRoot.newFile("build.gradle").writeText( + testProjectRoot.newFile("build.gradle").writeText("") + testProjectRoot.writeSettingsGradle( """ plugins { id "com.osacky.doctor" @@ -26,10 +27,6 @@ class TestDaggerTime { } warnWhenNotUsingParallelGC = false } - """.trimIndent(), - ) - testProjectRoot.newFile("settings.gradle").writeText( - """ include '$fixtureName' """.trimIndent(), ) diff --git a/doctor-plugin/src/testFixtures/java/com/osacky/doctor/GradleProjects.kt b/doctor-plugin/src/testFixtures/java/com/osacky/doctor/GradleProjects.kt index c71853f..075aa59 100644 --- a/doctor-plugin/src/testFixtures/java/com/osacky/doctor/GradleProjects.kt +++ b/doctor-plugin/src/testFixtures/java/com/osacky/doctor/GradleProjects.kt @@ -6,6 +6,10 @@ fun TemporaryFolder.writeBuildGradle(build: String) { writeFileToName("build.gradle", build) } +fun TemporaryFolder.writeSettingsGradle(settings: String) { + writeFileToName("settings.gradle", settings) +} + fun TemporaryFolder.writeFileToName( fileName: String, contents: String, diff --git a/settings.gradle.kts b/settings.gradle.kts index a317fbd..0a74fd6 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,12 +1,16 @@ +import com.osacky.doctor.DoctorExtension + pluginManagement { repositories { mavenCentral() gradlePluginPortal() } + includeBuild("doctor-plugin") } plugins { id("com.gradle.develocity") version "3.19.2" + id("com.osacky.doctor") } develocity { @@ -16,6 +20,18 @@ develocity { } } +configure { + disallowMultipleDaemons.set(false) + GCWarningThreshold.set(0.01f) + enableTestCaching.set(false) + downloadSpeedWarningThreshold.set(2.0f) + daggerThreshold.set(100) + javaHome { + ensureJavaHomeMatches.set(true) + ensureJavaHomeIsSet.set(true) + } +} + include("simple") include("dagger-kapt")