From 3339cb0c921cac51b4fa47138c08a81079796c89 Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Mon, 3 Mar 2025 14:00:22 -0500 Subject: [PATCH 1/6] Add validation task infrastructure + java version matcher This introduces a new concept of `validateFoundryProject` as a lifecycle task that can depend on a few common validations. The first one I'm adding here is a new one to validate that a `.java_version` file (if present) matches the `jdk` version defined in a version catalog, which we wanna support to make some other tooling more automatic like renovate and github actions. --- .../foundry/gradle/FoundryProperties.kt | 4 + .../foundry/gradle/FoundryRootPlugin.kt | 9 +++ .../kotlin/foundry/gradle/FoundryVersions.kt | 2 + .../gradle/tasks/FoundryValidationTask.kt | 31 ++++++++ .../foundry/gradle/tasks/LifecycleTask.kt | 40 ++++++++++ .../tasks/ValidateJavaVersionMatches.kt | 79 +++++++++++++++++++ 6 files changed, 165 insertions(+) create mode 100644 platforms/gradle/foundry-gradle-plugin/src/main/kotlin/foundry/gradle/tasks/FoundryValidationTask.kt create mode 100644 platforms/gradle/foundry-gradle-plugin/src/main/kotlin/foundry/gradle/tasks/LifecycleTask.kt create mode 100644 platforms/gradle/foundry-gradle-plugin/src/main/kotlin/foundry/gradle/tasks/ValidateJavaVersionMatches.kt diff --git a/platforms/gradle/foundry-gradle-plugin/src/main/kotlin/foundry/gradle/FoundryProperties.kt b/platforms/gradle/foundry-gradle-plugin/src/main/kotlin/foundry/gradle/FoundryProperties.kt index 4580a7779..b7bad84f7 100644 --- a/platforms/gradle/foundry-gradle-plugin/src/main/kotlin/foundry/gradle/FoundryProperties.kt +++ b/platforms/gradle/foundry-gradle-plugin/src/main/kotlin/foundry/gradle/FoundryProperties.kt @@ -779,6 +779,10 @@ internal constructor( KotlinVersion.fromVersion(it) } + /** Defines .java_version . */ + public val javaVersionFilePath: String? + get() = optionalStringProperty("foundry.jvm.java-version-file-path", blankIsNull = true) + /** Defines a required vendor for JDK toolchains. */ public val jvmVendor: Provider get() = diff --git a/platforms/gradle/foundry-gradle-plugin/src/main/kotlin/foundry/gradle/FoundryRootPlugin.kt b/platforms/gradle/foundry-gradle-plugin/src/main/kotlin/foundry/gradle/FoundryRootPlugin.kt index c26aeed56..56484543f 100644 --- a/platforms/gradle/foundry-gradle-plugin/src/main/kotlin/foundry/gradle/FoundryRootPlugin.kt +++ b/platforms/gradle/foundry-gradle-plugin/src/main/kotlin/foundry/gradle/FoundryRootPlugin.kt @@ -36,11 +36,13 @@ import foundry.gradle.properties.sneakyNull import foundry.gradle.stats.ModuleStatsTasks import foundry.gradle.tasks.AndroidTestApksTask import foundry.gradle.tasks.CoreBootstrapTask +import foundry.gradle.tasks.FoundryValidationTask import foundry.gradle.tasks.GjfDownloadTask import foundry.gradle.tasks.InstallCommitHooksTask import foundry.gradle.tasks.KtLintDownloadTask import foundry.gradle.tasks.KtfmtDownloadTask import foundry.gradle.tasks.SortDependenciesDownloadTask +import foundry.gradle.tasks.ValidateJavaVersionMatches import foundry.gradle.tasks.robolectric.UpdateRobolectricJarsTask import foundry.gradle.testing.EmulatorWtfTests import foundry.gradle.testing.RoborazziTests @@ -164,6 +166,13 @@ internal class FoundryRootPlugin @Inject constructor(private val buildFeatures: AndroidSourcesConfigurer.patchSdkSources(compileSdk, project, latestCompileSdkWithSources) } } + + FoundryValidationTask.registerLifecycleTask(project) + + foundryProperties.javaVersionFilePath?.let { javaVersionFilePath -> + ValidateJavaVersionMatches.register(project, javaVersionFilePath, foundryProperties.versions) + } + project.configureFoundryRootBuildscript( foundryProperties.versions.jdk.asProvider(project.providers), foundryProperties.jvmVendor.map(JvmVendorSpec::matching).orNull, diff --git a/platforms/gradle/foundry-gradle-plugin/src/main/kotlin/foundry/gradle/FoundryVersions.kt b/platforms/gradle/foundry-gradle-plugin/src/main/kotlin/foundry/gradle/FoundryVersions.kt index 71a5359be..b30e303c5 100644 --- a/platforms/gradle/foundry-gradle-plugin/src/main/kotlin/foundry/gradle/FoundryVersions.kt +++ b/platforms/gradle/foundry-gradle-plugin/src/main/kotlin/foundry/gradle/FoundryVersions.kt @@ -29,6 +29,7 @@ internal class FoundryVersions( private val libResolver: (String) -> Optional, bundleResolver: (String) -> Optional>, val boms: Set>, + val catalogName: String, ) { /** @@ -48,6 +49,7 @@ internal class FoundryVersions( it.endsWith(".bom") } .mapTo(LinkedHashSet()) { catalog.findLibrary(it).get() }, + catalogName = catalog.name, ) // Have to use Optional because ConcurrentHashMap doesn't allow nulls for absence diff --git a/platforms/gradle/foundry-gradle-plugin/src/main/kotlin/foundry/gradle/tasks/FoundryValidationTask.kt b/platforms/gradle/foundry-gradle-plugin/src/main/kotlin/foundry/gradle/tasks/FoundryValidationTask.kt new file mode 100644 index 000000000..10721fd2d --- /dev/null +++ b/platforms/gradle/foundry-gradle-plugin/src/main/kotlin/foundry/gradle/tasks/FoundryValidationTask.kt @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2025 Slack Technologies, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package foundry.gradle.tasks + +import org.gradle.api.Project +import org.gradle.api.Task +import org.gradle.api.tasks.TaskProvider + +/** Marker interface for Foundry validation tasks that can be depended on by type. */ +public interface FoundryValidationTask : Task { + public companion object { + internal fun registerLifecycleTask(project: Project): TaskProvider { + return LifecycleTask.register(project, "validateFoundryProject") { + dependsOn(project.tasks.withType(FoundryValidationTask::class.java)) + } + } + } +} diff --git a/platforms/gradle/foundry-gradle-plugin/src/main/kotlin/foundry/gradle/tasks/LifecycleTask.kt b/platforms/gradle/foundry-gradle-plugin/src/main/kotlin/foundry/gradle/tasks/LifecycleTask.kt new file mode 100644 index 000000000..fe104f00d --- /dev/null +++ b/platforms/gradle/foundry-gradle-plugin/src/main/kotlin/foundry/gradle/tasks/LifecycleTask.kt @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2025 Slack Technologies, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package foundry.gradle.tasks + +import foundry.gradle.register +import org.gradle.api.Action +import org.gradle.api.DefaultTask +import org.gradle.api.Project +import org.gradle.api.tasks.TaskProvider +import org.gradle.api.tasks.UntrackedTask + +@UntrackedTask(because = "Just a lifecycle task") +internal abstract class LifecycleTask : DefaultTask() { + companion object { + internal fun register( + project: Project, + name: String, + group: String = "foundry", + action: Action = Action {}, + ): TaskProvider { + return project.tasks.register(name) { + this.group = group + action.execute(this) + } + } + } +} diff --git a/platforms/gradle/foundry-gradle-plugin/src/main/kotlin/foundry/gradle/tasks/ValidateJavaVersionMatches.kt b/platforms/gradle/foundry-gradle-plugin/src/main/kotlin/foundry/gradle/tasks/ValidateJavaVersionMatches.kt new file mode 100644 index 000000000..16855cf9b --- /dev/null +++ b/platforms/gradle/foundry-gradle-plugin/src/main/kotlin/foundry/gradle/tasks/ValidateJavaVersionMatches.kt @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2025 Slack Technologies, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package foundry.gradle.tasks + +import foundry.gradle.FoundryVersions +import foundry.gradle.register +import org.gradle.api.DefaultTask +import org.gradle.api.Project +import org.gradle.api.file.RegularFileProperty +import org.gradle.api.provider.Property +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.InputFile +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.jetbrains.kotlin.com.intellij.util.containers.orNull + +/** + * A Gradle task that validates whether the Java version specified in a `.java_version` matches the + * expected version defined in a version catalog. If the versions match, an output file is generated + * with the status "valid". If they do not match, the task fails with a descriptive error message. + * + * This is useful for projects that define the JDK in both places, as some tools like Renovate and + * github actions work well with a `.java_version` file. + */ +public abstract class ValidateJavaVersionMatches : DefaultTask(), FoundryValidationTask { + @get:InputFile + @get:PathSensitive(PathSensitivity.NONE) + public abstract val javaVersionFile: RegularFileProperty + + @get:Input public abstract val catalogName: Property + @get:Input public abstract val catalogJdkVersion: Property + + @get:OutputFile public abstract val outputFile: RegularFileProperty + + init { + group = "foundry" + } + + @TaskAction + internal fun validate() { + val javaVersion = javaVersionFile.asFile.get().readText().trim().toInt() + val catalogVersion = catalogJdkVersion.get() + + check(javaVersion == catalogVersion) { + val filePath = javaVersionFile.asFile.get().absolutePath + "Java version ($javaVersion) in file '$filePath' does not match the JDK version in ${catalogName.get()}.versions.toml ($catalogVersion). Please ensure these are aligned" + } + + outputFile.asFile.get().writeText("valid") + } + + internal companion object { + fun register(project: Project, javaVersionFilePath: String, foundryVersions: FoundryVersions) { + project.tasks.register("validateJavaVersions") { + javaVersionFile.set(project.layout.projectDirectory.file(javaVersionFilePath)) + catalogJdkVersion.set(foundryVersions.jdk.orNull()) + catalogName.set(foundryVersions.catalogName) + outputFile.set( + project.layout.buildDirectory.file("foundry/validate_java_version/output.txt") + ) + } + } + } +} From eaec8ae89825956048d53fbb67aa0c4feac7dba5 Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Mon, 3 Mar 2025 14:10:38 -0500 Subject: [PATCH 2/6] Fix --- .../main/kotlin/foundry/gradle/FoundryRootPlugin.kt | 10 +++++++++- .../foundry/gradle/tasks/ValidateJavaVersionMatches.kt | 10 +++++++--- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/platforms/gradle/foundry-gradle-plugin/src/main/kotlin/foundry/gradle/FoundryRootPlugin.kt b/platforms/gradle/foundry-gradle-plugin/src/main/kotlin/foundry/gradle/FoundryRootPlugin.kt index 56484543f..858dc616b 100644 --- a/platforms/gradle/foundry-gradle-plugin/src/main/kotlin/foundry/gradle/FoundryRootPlugin.kt +++ b/platforms/gradle/foundry-gradle-plugin/src/main/kotlin/foundry/gradle/FoundryRootPlugin.kt @@ -51,6 +51,7 @@ import foundry.gradle.util.Thermals import foundry.gradle.util.ThermalsData import java.util.Locale import javax.inject.Inject +import kotlin.jvm.optionals.getOrNull import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.api.configuration.BuildFeatures @@ -170,7 +171,14 @@ internal class FoundryRootPlugin @Inject constructor(private val buildFeatures: FoundryValidationTask.registerLifecycleTask(project) foundryProperties.javaVersionFilePath?.let { javaVersionFilePath -> - ValidateJavaVersionMatches.register(project, javaVersionFilePath, foundryProperties.versions) + foundryProperties.versions.jdk.getOrNull()?.let { catalogJdk -> + ValidateJavaVersionMatches.register( + project, + javaVersionFilePath, + catalogJdk, + foundryProperties.versions, + ) + } } project.configureFoundryRootBuildscript( diff --git a/platforms/gradle/foundry-gradle-plugin/src/main/kotlin/foundry/gradle/tasks/ValidateJavaVersionMatches.kt b/platforms/gradle/foundry-gradle-plugin/src/main/kotlin/foundry/gradle/tasks/ValidateJavaVersionMatches.kt index 16855cf9b..fa31c86eb 100644 --- a/platforms/gradle/foundry-gradle-plugin/src/main/kotlin/foundry/gradle/tasks/ValidateJavaVersionMatches.kt +++ b/platforms/gradle/foundry-gradle-plugin/src/main/kotlin/foundry/gradle/tasks/ValidateJavaVersionMatches.kt @@ -27,7 +27,6 @@ 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.jetbrains.kotlin.com.intellij.util.containers.orNull /** * A Gradle task that validates whether the Java version specified in a `.java_version` matches the @@ -65,10 +64,15 @@ public abstract class ValidateJavaVersionMatches : DefaultTask(), FoundryValidat } internal companion object { - fun register(project: Project, javaVersionFilePath: String, foundryVersions: FoundryVersions) { + fun register( + project: Project, + javaVersionFilePath: String, + catalogJdk: Int, + foundryVersions: FoundryVersions, + ) { project.tasks.register("validateJavaVersions") { javaVersionFile.set(project.layout.projectDirectory.file(javaVersionFilePath)) - catalogJdkVersion.set(foundryVersions.jdk.orNull()) + catalogJdkVersion.set(catalogJdk) catalogName.set(foundryVersions.catalogName) outputFile.set( project.layout.buildDirectory.file("foundry/validate_java_version/output.txt") From 6206619a05583dd1737fc3fb7ff55f6645166402 Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Mon, 3 Mar 2025 14:36:35 -0500 Subject: [PATCH 3/6] More fixes --- .../foundry-gradle-plugin/best-practices-baseline.json | 2 +- .../foundry/gradle/tasks/ValidateJavaVersionMatches.kt | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/platforms/gradle/foundry-gradle-plugin/best-practices-baseline.json b/platforms/gradle/foundry-gradle-plugin/best-practices-baseline.json index 97f38115d..457d0dce9 100644 --- a/platforms/gradle/foundry-gradle-plugin/best-practices-baseline.json +++ b/platforms/gradle/foundry-gradle-plugin/best-practices-baseline.json @@ -1 +1 @@ -{"issues":[{"type":"get_subprojects","name":"getSubprojects","trace":{"trace":[{"owner":"foundry/gradle/FoundryRootPlugin$configureRootProject$5","name":"accept","descriptor":"(Ljava/lang/Object;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/FoundryRootPlugin$configureRootProject$5","name":"accept","descriptor":"(Ljava/lang/String;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/testing/EmulatorWtfTests","name":"configureRootProject","descriptor":"(Lorg/gradle/api/Project;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver$default","descriptor":"(Lfoundry/gradle/artifacts/Resolver$Companion;Lorg/gradle/api/Project;Lfoundry/gradle/artifacts/FoundryArtifact;ZILjava/lang/Object;)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver","descriptor":"(Lorg/gradle/api/Project;Lfoundry/gradle/artifacts/FoundryArtifact;Z)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver","descriptor":"(Lorg/gradle/api/Project;Lorg/gradle/api/attributes/Attribute;Ljava/io/Serializable;Ljava/lang/String;Ljava/lang/String;Z)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver","name":"addSubprojectDependencies","descriptor":"(Lorg/gradle/api/Project;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"org/gradle/api/Project","name":"getSubprojects","descriptor":"()Ljava/util/Set;","metadata":{"isTaskAction":false,"isVirtual":false}}]}},{"type":"get_subprojects","name":"getSubprojects","trace":{"trace":[{"owner":"foundry/gradle/FoundryBasePlugin","name":"apply","descriptor":"(Ljava/lang/Object;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/FoundryBasePlugin","name":"apply","descriptor":"(Lorg/gradle/api/Project;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/topography/ModuleTopographyTasks","name":"configureRootProject","descriptor":"(Lorg/gradle/api/Project;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver$default","descriptor":"(Lfoundry/gradle/artifacts/Resolver$Companion;Lorg/gradle/api/Project;Lfoundry/gradle/artifacts/FoundryArtifact;ZILjava/lang/Object;)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver","descriptor":"(Lorg/gradle/api/Project;Lfoundry/gradle/artifacts/FoundryArtifact;Z)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver","descriptor":"(Lorg/gradle/api/Project;Lorg/gradle/api/attributes/Attribute;Ljava/io/Serializable;Ljava/lang/String;Ljava/lang/String;Z)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver","name":"addSubprojectDependencies","descriptor":"(Lorg/gradle/api/Project;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"org/gradle/api/Project","name":"getSubprojects","descriptor":"()Ljava/util/Set;","metadata":{"isTaskAction":false,"isVirtual":false}}]}},{"type":"get_subprojects","name":"getSubprojects","trace":{"trace":[{"owner":"foundry/gradle/FoundryRootPlugin","name":"apply","descriptor":"(Ljava/lang/Object;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/FoundryRootPlugin","name":"apply","descriptor":"(Lorg/gradle/api/Project;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/FoundryRootPlugin","name":"configureRootProject","descriptor":"(Lorg/gradle/api/Project;Lfoundry/gradle/FoundryProperties;Lorg/gradle/api/provider/Provider;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/tasks/AndroidTestApksTask$Companion","name":"register$foundry_gradle_plugin","descriptor":"(Lorg/gradle/api/Project;)Lorg/gradle/api/tasks/TaskProvider;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver$default","descriptor":"(Lfoundry/gradle/artifacts/Resolver$Companion;Lorg/gradle/api/Project;Lfoundry/gradle/artifacts/FoundryArtifact;ZILjava/lang/Object;)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver","descriptor":"(Lorg/gradle/api/Project;Lfoundry/gradle/artifacts/FoundryArtifact;Z)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver","descriptor":"(Lorg/gradle/api/Project;Lorg/gradle/api/attributes/Attribute;Ljava/io/Serializable;Ljava/lang/String;Ljava/lang/String;Z)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver","name":"addSubprojectDependencies","descriptor":"(Lorg/gradle/api/Project;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"org/gradle/api/Project","name":"getSubprojects","descriptor":"()Ljava/util/Set;","metadata":{"isTaskAction":false,"isVirtual":false}}]}},{"type":"get_subprojects","name":"getSubprojects","trace":{"trace":[{"owner":"foundry/gradle/FoundryRootPlugin$configureRootProject$4","name":"accept","descriptor":"(Ljava/lang/Object;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/FoundryRootPlugin$configureRootProject$4","name":"accept","descriptor":"(Ljava/lang/String;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/testing/RoborazziTests","name":"configureRootProject","descriptor":"(Lorg/gradle/api/Project;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver$default","descriptor":"(Lfoundry/gradle/artifacts/Resolver$Companion;Lorg/gradle/api/Project;Lfoundry/gradle/artifacts/FoundryArtifact;ZILjava/lang/Object;)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver","descriptor":"(Lorg/gradle/api/Project;Lfoundry/gradle/artifacts/FoundryArtifact;Z)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver","descriptor":"(Lorg/gradle/api/Project;Lorg/gradle/api/attributes/Attribute;Ljava/io/Serializable;Ljava/lang/String;Ljava/lang/String;Z)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver","name":"addSubprojectDependencies","descriptor":"(Lorg/gradle/api/Project;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"org/gradle/api/Project","name":"getSubprojects","descriptor":"()Ljava/util/Set;","metadata":{"isTaskAction":false,"isVirtual":false}}]}},{"type":"get_subprojects","name":"getSubprojects","trace":{"trace":[{"owner":"foundry/gradle/stats/ModuleStatsTasks$configureRoot$1$1","name":"call","descriptor":"()Ljava/lang/Object;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/stats/ModuleStatsTasks$configureRoot$1$1","name":"call","descriptor":"()Ljava/util/Map;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"org/gradle/api/Project","name":"getSubprojects","descriptor":"()Ljava/util/Set;","metadata":{"isTaskAction":false,"isVirtual":false}}]}},{"type":"get_subprojects","name":"getSubprojects","trace":{"trace":[{"owner":"foundry/gradle/FoundryRootPlugin$configureRootProject$14","name":"execute","descriptor":"(Ljava/lang/Object;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/FoundryRootPlugin$configureRootProject$14","name":"execute","descriptor":"(Lorg/gradle/api/plugins/AppliedPlugin;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/dependencyrake/MissingIdentifiersAggregatorTask$Companion","name":"register","descriptor":"(Lorg/gradle/api/Project;)Lorg/gradle/api/tasks/TaskProvider;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver$default","descriptor":"(Lfoundry/gradle/artifacts/Resolver$Companion;Lorg/gradle/api/Project;Lfoundry/gradle/artifacts/FoundryArtifact;ZILjava/lang/Object;)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver","descriptor":"(Lorg/gradle/api/Project;Lfoundry/gradle/artifacts/FoundryArtifact;Z)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver","descriptor":"(Lorg/gradle/api/Project;Lorg/gradle/api/attributes/Attribute;Ljava/io/Serializable;Ljava/lang/String;Ljava/lang/String;Z)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver","name":"addSubprojectDependencies","descriptor":"(Lorg/gradle/api/Project;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"org/gradle/api/Project","name":"getSubprojects","descriptor":"()Ljava/util/Set;","metadata":{"isTaskAction":false,"isVirtual":false}}]}},{"type":"get_subprojects","name":"getSubprojects","trace":{"trace":[{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver$default","descriptor":"(Lfoundry/gradle/artifacts/Resolver$Companion;Lorg/gradle/api/Project;Lorg/gradle/api/attributes/Attribute;Ljava/io/Serializable;Ljava/lang/String;Ljava/lang/String;ZILjava/lang/Object;)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver","descriptor":"(Lorg/gradle/api/Project;Lorg/gradle/api/attributes/Attribute;Ljava/io/Serializable;Ljava/lang/String;Ljava/lang/String;Z)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver","name":"addSubprojectDependencies","descriptor":"(Lorg/gradle/api/Project;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"org/gradle/api/Project","name":"getSubprojects","descriptor":"()Ljava/util/Set;","metadata":{"isTaskAction":false,"isVirtual":false}}]}}]} \ No newline at end of file +{"issues":[{"type":"get_subprojects","name":"getSubprojects","trace":{"trace":[{"owner":"foundry/gradle/FoundryBasePlugin","name":"apply","descriptor":"(Ljava/lang/Object;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/FoundryBasePlugin","name":"apply","descriptor":"(Lorg/gradle/api/Project;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/topography/ModuleTopographyTasks","name":"configureRootProject","descriptor":"(Lorg/gradle/api/Project;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver$default","descriptor":"(Lfoundry/gradle/artifacts/Resolver$Companion;Lorg/gradle/api/Project;Lfoundry/gradle/artifacts/FoundryArtifact;ZILjava/lang/Object;)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver","descriptor":"(Lorg/gradle/api/Project;Lfoundry/gradle/artifacts/FoundryArtifact;Z)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver","descriptor":"(Lorg/gradle/api/Project;Lorg/gradle/api/attributes/Attribute;Ljava/io/Serializable;Ljava/lang/String;Ljava/lang/String;Z)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver","name":"addSubprojectDependencies","descriptor":"(Lorg/gradle/api/Project;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"org/gradle/api/Project","name":"getSubprojects","descriptor":"()Ljava/util/Set;","metadata":{"isTaskAction":false,"isVirtual":false}}]}},{"type":"get_subprojects","name":"getSubprojects","trace":{"trace":[{"owner":"foundry/gradle/FoundryRootPlugin","name":"apply","descriptor":"(Ljava/lang/Object;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/FoundryRootPlugin","name":"apply","descriptor":"(Lorg/gradle/api/Project;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/FoundryRootPlugin","name":"configureRootProject","descriptor":"(Lorg/gradle/api/Project;Lfoundry/gradle/FoundryProperties;Lorg/gradle/api/provider/Provider;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/tasks/AndroidTestApksTask$Companion","name":"register$foundry_gradle_plugin","descriptor":"(Lorg/gradle/api/Project;)Lorg/gradle/api/tasks/TaskProvider;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver$default","descriptor":"(Lfoundry/gradle/artifacts/Resolver$Companion;Lorg/gradle/api/Project;Lfoundry/gradle/artifacts/FoundryArtifact;ZILjava/lang/Object;)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver","descriptor":"(Lorg/gradle/api/Project;Lfoundry/gradle/artifacts/FoundryArtifact;Z)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver","descriptor":"(Lorg/gradle/api/Project;Lorg/gradle/api/attributes/Attribute;Ljava/io/Serializable;Ljava/lang/String;Ljava/lang/String;Z)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver","name":"addSubprojectDependencies","descriptor":"(Lorg/gradle/api/Project;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"org/gradle/api/Project","name":"getSubprojects","descriptor":"()Ljava/util/Set;","metadata":{"isTaskAction":false,"isVirtual":false}}]}},{"type":"get_subprojects","name":"getSubprojects","trace":{"trace":[{"owner":"foundry/gradle/FoundryRootPlugin$configureRootProject$15","name":"execute","descriptor":"(Ljava/lang/Object;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/FoundryRootPlugin$configureRootProject$15","name":"execute","descriptor":"(Lorg/gradle/api/plugins/AppliedPlugin;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/dependencyrake/MissingIdentifiersAggregatorTask$Companion","name":"register","descriptor":"(Lorg/gradle/api/Project;)Lorg/gradle/api/tasks/TaskProvider;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver$default","descriptor":"(Lfoundry/gradle/artifacts/Resolver$Companion;Lorg/gradle/api/Project;Lfoundry/gradle/artifacts/FoundryArtifact;ZILjava/lang/Object;)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver","descriptor":"(Lorg/gradle/api/Project;Lfoundry/gradle/artifacts/FoundryArtifact;Z)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver","descriptor":"(Lorg/gradle/api/Project;Lorg/gradle/api/attributes/Attribute;Ljava/io/Serializable;Ljava/lang/String;Ljava/lang/String;Z)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver","name":"addSubprojectDependencies","descriptor":"(Lorg/gradle/api/Project;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"org/gradle/api/Project","name":"getSubprojects","descriptor":"()Ljava/util/Set;","metadata":{"isTaskAction":false,"isVirtual":false}}]}},{"type":"get_subprojects","name":"getSubprojects","trace":{"trace":[{"owner":"foundry/gradle/stats/ModuleStatsTasks$configureRoot$1$1","name":"call","descriptor":"()Ljava/lang/Object;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/stats/ModuleStatsTasks$configureRoot$1$1","name":"call","descriptor":"()Ljava/util/Map;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"org/gradle/api/Project","name":"getSubprojects","descriptor":"()Ljava/util/Set;","metadata":{"isTaskAction":false,"isVirtual":false}}]}},{"type":"get_subprojects","name":"getSubprojects","trace":{"trace":[{"owner":"foundry/gradle/FoundryRootPlugin$configureRootProject$5","name":"accept","descriptor":"(Ljava/lang/Object;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/FoundryRootPlugin$configureRootProject$5","name":"accept","descriptor":"(Ljava/lang/String;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/testing/RoborazziTests","name":"configureRootProject","descriptor":"(Lorg/gradle/api/Project;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver$default","descriptor":"(Lfoundry/gradle/artifacts/Resolver$Companion;Lorg/gradle/api/Project;Lfoundry/gradle/artifacts/FoundryArtifact;ZILjava/lang/Object;)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver","descriptor":"(Lorg/gradle/api/Project;Lfoundry/gradle/artifacts/FoundryArtifact;Z)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver","descriptor":"(Lorg/gradle/api/Project;Lorg/gradle/api/attributes/Attribute;Ljava/io/Serializable;Ljava/lang/String;Ljava/lang/String;Z)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver","name":"addSubprojectDependencies","descriptor":"(Lorg/gradle/api/Project;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"org/gradle/api/Project","name":"getSubprojects","descriptor":"()Ljava/util/Set;","metadata":{"isTaskAction":false,"isVirtual":false}}]}},{"type":"get_subprojects","name":"getSubprojects","trace":{"trace":[{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver$default","descriptor":"(Lfoundry/gradle/artifacts/Resolver$Companion;Lorg/gradle/api/Project;Lorg/gradle/api/attributes/Attribute;Ljava/io/Serializable;Ljava/lang/String;Ljava/lang/String;ZILjava/lang/Object;)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver","descriptor":"(Lorg/gradle/api/Project;Lorg/gradle/api/attributes/Attribute;Ljava/io/Serializable;Ljava/lang/String;Ljava/lang/String;Z)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver","name":"addSubprojectDependencies","descriptor":"(Lorg/gradle/api/Project;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"org/gradle/api/Project","name":"getSubprojects","descriptor":"()Ljava/util/Set;","metadata":{"isTaskAction":false,"isVirtual":false}}]}},{"type":"get_subprojects","name":"getSubprojects","trace":{"trace":[{"owner":"foundry/gradle/FoundryRootPlugin$configureRootProject$6","name":"accept","descriptor":"(Ljava/lang/Object;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/FoundryRootPlugin$configureRootProject$6","name":"accept","descriptor":"(Ljava/lang/String;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/testing/EmulatorWtfTests","name":"configureRootProject","descriptor":"(Lorg/gradle/api/Project;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver$default","descriptor":"(Lfoundry/gradle/artifacts/Resolver$Companion;Lorg/gradle/api/Project;Lfoundry/gradle/artifacts/FoundryArtifact;ZILjava/lang/Object;)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver","descriptor":"(Lorg/gradle/api/Project;Lfoundry/gradle/artifacts/FoundryArtifact;Z)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver","descriptor":"(Lorg/gradle/api/Project;Lorg/gradle/api/attributes/Attribute;Ljava/io/Serializable;Ljava/lang/String;Ljava/lang/String;Z)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver","name":"addSubprojectDependencies","descriptor":"(Lorg/gradle/api/Project;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"org/gradle/api/Project","name":"getSubprojects","descriptor":"()Ljava/util/Set;","metadata":{"isTaskAction":false,"isVirtual":false}}]}}]} \ No newline at end of file diff --git a/platforms/gradle/foundry-gradle-plugin/src/main/kotlin/foundry/gradle/tasks/ValidateJavaVersionMatches.kt b/platforms/gradle/foundry-gradle-plugin/src/main/kotlin/foundry/gradle/tasks/ValidateJavaVersionMatches.kt index fa31c86eb..e987a7c4a 100644 --- a/platforms/gradle/foundry-gradle-plugin/src/main/kotlin/foundry/gradle/tasks/ValidateJavaVersionMatches.kt +++ b/platforms/gradle/foundry-gradle-plugin/src/main/kotlin/foundry/gradle/tasks/ValidateJavaVersionMatches.kt @@ -41,6 +41,7 @@ public abstract class ValidateJavaVersionMatches : DefaultTask(), FoundryValidat @get:PathSensitive(PathSensitivity.NONE) public abstract val javaVersionFile: RegularFileProperty + @get:Input public abstract val javaVersionFileRelativePath: Property @get:Input public abstract val catalogName: Property @get:Input public abstract val catalogJdkVersion: Property @@ -56,8 +57,7 @@ public abstract class ValidateJavaVersionMatches : DefaultTask(), FoundryValidat val catalogVersion = catalogJdkVersion.get() check(javaVersion == catalogVersion) { - val filePath = javaVersionFile.asFile.get().absolutePath - "Java version ($javaVersion) in file '$filePath' does not match the JDK version in ${catalogName.get()}.versions.toml ($catalogVersion). Please ensure these are aligned" + "Java version ($javaVersion) in file '${javaVersionFileRelativePath.get()}' does not match the JDK version in ${catalogName.get()}.versions.toml ($catalogVersion). Please ensure these are aligned" } outputFile.asFile.get().writeText("valid") @@ -72,6 +72,7 @@ public abstract class ValidateJavaVersionMatches : DefaultTask(), FoundryValidat ) { project.tasks.register("validateJavaVersions") { javaVersionFile.set(project.layout.projectDirectory.file(javaVersionFilePath)) + javaVersionFileRelativePath.set(javaVersionFilePath) catalogJdkVersion.set(catalogJdk) catalogName.set(foundryVersions.catalogName) outputFile.set( From 6a3f271d484ada0fa8f96572dacf19e4a3359a18 Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Mon, 3 Mar 2025 14:41:42 -0500 Subject: [PATCH 4/6] It's cacheable --- .../kotlin/foundry/gradle/tasks/ValidateJavaVersionMatches.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/platforms/gradle/foundry-gradle-plugin/src/main/kotlin/foundry/gradle/tasks/ValidateJavaVersionMatches.kt b/platforms/gradle/foundry-gradle-plugin/src/main/kotlin/foundry/gradle/tasks/ValidateJavaVersionMatches.kt index e987a7c4a..7a006329a 100644 --- a/platforms/gradle/foundry-gradle-plugin/src/main/kotlin/foundry/gradle/tasks/ValidateJavaVersionMatches.kt +++ b/platforms/gradle/foundry-gradle-plugin/src/main/kotlin/foundry/gradle/tasks/ValidateJavaVersionMatches.kt @@ -21,6 +21,7 @@ import org.gradle.api.DefaultTask import org.gradle.api.Project import org.gradle.api.file.RegularFileProperty import org.gradle.api.provider.Property +import org.gradle.api.tasks.CacheableTask import org.gradle.api.tasks.Input import org.gradle.api.tasks.InputFile import org.gradle.api.tasks.OutputFile @@ -36,6 +37,7 @@ import org.gradle.api.tasks.TaskAction * This is useful for projects that define the JDK in both places, as some tools like Renovate and * github actions work well with a `.java_version` file. */ +@CacheableTask public abstract class ValidateJavaVersionMatches : DefaultTask(), FoundryValidationTask { @get:InputFile @get:PathSensitive(PathSensitivity.NONE) From 7507caa6536d37a5a5fe40166834ab7c4453779e Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Mon, 10 Mar 2025 15:19:25 -0400 Subject: [PATCH 5/6] Generify to support kotlin versions too --- .../foundry/gradle/FoundryProperties.kt | 6 ++- .../foundry/gradle/FoundryRootPlugin.kt | 25 ++++++++--- ...ionMatches.kt => ValidateVersionsMatch.kt} | 44 ++++++++++--------- 3 files changed, 47 insertions(+), 28 deletions(-) rename platforms/gradle/foundry-gradle-plugin/src/main/kotlin/foundry/gradle/tasks/{ValidateJavaVersionMatches.kt => ValidateVersionsMatch.kt} (50%) diff --git a/platforms/gradle/foundry-gradle-plugin/src/main/kotlin/foundry/gradle/FoundryProperties.kt b/platforms/gradle/foundry-gradle-plugin/src/main/kotlin/foundry/gradle/FoundryProperties.kt index b7bad84f7..310f27d1d 100644 --- a/platforms/gradle/foundry-gradle-plugin/src/main/kotlin/foundry/gradle/FoundryProperties.kt +++ b/platforms/gradle/foundry-gradle-plugin/src/main/kotlin/foundry/gradle/FoundryProperties.kt @@ -779,7 +779,11 @@ internal constructor( KotlinVersion.fromVersion(it) } - /** Defines .java_version . */ + /** Defines .kotlin_version. */ + public val kotlinVersionFilePath: String? + get() = optionalStringProperty("foundry.kotlin.kotlin-version-file-path", blankIsNull = true) + + /** Defines .java_version. */ public val javaVersionFilePath: String? get() = optionalStringProperty("foundry.jvm.java-version-file-path", blankIsNull = true) diff --git a/platforms/gradle/foundry-gradle-plugin/src/main/kotlin/foundry/gradle/FoundryRootPlugin.kt b/platforms/gradle/foundry-gradle-plugin/src/main/kotlin/foundry/gradle/FoundryRootPlugin.kt index 858dc616b..0086303be 100644 --- a/platforms/gradle/foundry-gradle-plugin/src/main/kotlin/foundry/gradle/FoundryRootPlugin.kt +++ b/platforms/gradle/foundry-gradle-plugin/src/main/kotlin/foundry/gradle/FoundryRootPlugin.kt @@ -42,7 +42,7 @@ import foundry.gradle.tasks.InstallCommitHooksTask import foundry.gradle.tasks.KtLintDownloadTask import foundry.gradle.tasks.KtfmtDownloadTask import foundry.gradle.tasks.SortDependenciesDownloadTask -import foundry.gradle.tasks.ValidateJavaVersionMatches +import foundry.gradle.tasks.ValidateVersionsMatch import foundry.gradle.tasks.robolectric.UpdateRobolectricJarsTask import foundry.gradle.testing.EmulatorWtfTests import foundry.gradle.testing.RoborazziTests @@ -171,16 +171,27 @@ internal class FoundryRootPlugin @Inject constructor(private val buildFeatures: FoundryValidationTask.registerLifecycleTask(project) foundryProperties.javaVersionFilePath?.let { javaVersionFilePath -> - foundryProperties.versions.jdk.getOrNull()?.let { catalogJdk -> - ValidateJavaVersionMatches.register( - project, - javaVersionFilePath, - catalogJdk, - foundryProperties.versions, + foundryProperties.versions.jdk.getOrNull()?.let { catalogVersion -> + ValidateVersionsMatch.register( + project = project, + type = "javaVersion", + versionFilePath = javaVersionFilePath, + catalogVersion = catalogVersion.toString(), + foundryVersions = foundryProperties.versions, ) } } + foundryProperties.kotlinVersionFilePath?.let { javaVersionFilePath -> + ValidateVersionsMatch.register( + project = project, + type = "kotlinVersion", + versionFilePath = javaVersionFilePath, + catalogVersion = foundryProperties.versions.kotlin, + foundryVersions = foundryProperties.versions, + ) + } + project.configureFoundryRootBuildscript( foundryProperties.versions.jdk.asProvider(project.providers), foundryProperties.jvmVendor.map(JvmVendorSpec::matching).orNull, diff --git a/platforms/gradle/foundry-gradle-plugin/src/main/kotlin/foundry/gradle/tasks/ValidateJavaVersionMatches.kt b/platforms/gradle/foundry-gradle-plugin/src/main/kotlin/foundry/gradle/tasks/ValidateVersionsMatch.kt similarity index 50% rename from platforms/gradle/foundry-gradle-plugin/src/main/kotlin/foundry/gradle/tasks/ValidateJavaVersionMatches.kt rename to platforms/gradle/foundry-gradle-plugin/src/main/kotlin/foundry/gradle/tasks/ValidateVersionsMatch.kt index 7a006329a..7eab49186 100644 --- a/platforms/gradle/foundry-gradle-plugin/src/main/kotlin/foundry/gradle/tasks/ValidateJavaVersionMatches.kt +++ b/platforms/gradle/foundry-gradle-plugin/src/main/kotlin/foundry/gradle/tasks/ValidateVersionsMatch.kt @@ -16,6 +16,7 @@ package foundry.gradle.tasks import foundry.gradle.FoundryVersions +import foundry.gradle.capitalizeUS import foundry.gradle.register import org.gradle.api.DefaultTask import org.gradle.api.Project @@ -30,22 +31,24 @@ import org.gradle.api.tasks.PathSensitivity import org.gradle.api.tasks.TaskAction /** - * A Gradle task that validates whether the Java version specified in a `.java_version` matches the - * expected version defined in a version catalog. If the versions match, an output file is generated - * with the status "valid". If they do not match, the task fails with a descriptive error message. + * A Gradle task that validates whether version specified in a given [versionFile] (for example: + * `.java_version`) matches the expected version defined in a version catalog ([catalogVersion]). If + * the versions match, an [outputFile] is generated with the status "valid". If they do not match, + * the task fails with a descriptive error message. * - * This is useful for projects that define the JDK in both places, as some tools like Renovate and - * github actions work well with a `.java_version` file. + * This is useful for projects that define the version in multiple places, as some tools like + * Renovate and GitHub actions work well with a `.java_version` file and some caching mechanisms + * want a single manifest file. */ @CacheableTask -public abstract class ValidateJavaVersionMatches : DefaultTask(), FoundryValidationTask { +public abstract class ValidateVersionsMatch : DefaultTask(), FoundryValidationTask { @get:InputFile @get:PathSensitive(PathSensitivity.NONE) - public abstract val javaVersionFile: RegularFileProperty + public abstract val versionFile: RegularFileProperty - @get:Input public abstract val javaVersionFileRelativePath: Property + @get:Input public abstract val versionFileRelativePath: Property @get:Input public abstract val catalogName: Property - @get:Input public abstract val catalogJdkVersion: Property + @get:Input public abstract val catalogVersion: Property @get:OutputFile public abstract val outputFile: RegularFileProperty @@ -55,11 +58,11 @@ public abstract class ValidateJavaVersionMatches : DefaultTask(), FoundryValidat @TaskAction internal fun validate() { - val javaVersion = javaVersionFile.asFile.get().readText().trim().toInt() - val catalogVersion = catalogJdkVersion.get() + val fileVersion = versionFile.asFile.get().readText().trim() + val requiredVersion = catalogVersion.get() - check(javaVersion == catalogVersion) { - "Java version ($javaVersion) in file '${javaVersionFileRelativePath.get()}' does not match the JDK version in ${catalogName.get()}.versions.toml ($catalogVersion). Please ensure these are aligned" + check(fileVersion == requiredVersion) { + "Version ($fileVersion) in file '${versionFileRelativePath.get()}' does not match the version in ${catalogName.get()}.versions.toml ($requiredVersion). Please ensure these are aligned" } outputFile.asFile.get().writeText("valid") @@ -68,17 +71,18 @@ public abstract class ValidateJavaVersionMatches : DefaultTask(), FoundryValidat internal companion object { fun register( project: Project, - javaVersionFilePath: String, - catalogJdk: Int, + type: String, + versionFilePath: String, + catalogVersion: String, foundryVersions: FoundryVersions, ) { - project.tasks.register("validateJavaVersions") { - javaVersionFile.set(project.layout.projectDirectory.file(javaVersionFilePath)) - javaVersionFileRelativePath.set(javaVersionFilePath) - catalogJdkVersion.set(catalogJdk) + project.tasks.register("validate${type.capitalizeUS()}Matches") { + versionFile.set(project.layout.projectDirectory.file(versionFilePath)) + versionFileRelativePath.set(versionFilePath) + this.catalogVersion.set(catalogVersion) catalogName.set(foundryVersions.catalogName) outputFile.set( - project.layout.buildDirectory.file("foundry/validate_java_version/output.txt") + project.layout.buildDirectory.file("foundry/version-matches/$type/valid.txt") ) } } From 132e8a49026967a97f192b7e32bd68c54e997b07 Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Mon, 10 Mar 2025 15:25:15 -0400 Subject: [PATCH 6/6] Update baseline --- CHANGELOG.md | 2 ++ .../gradle/foundry-gradle-plugin/best-practices-baseline.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a68d78552..d30c5b097 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ Changelog **Unreleased** -------------- +- Add optional `validate(Kotlin|Java)VersionMatches` tasks to keep files like `.java_version` synced with version catalogs. + 0.24.11 ------- diff --git a/platforms/gradle/foundry-gradle-plugin/best-practices-baseline.json b/platforms/gradle/foundry-gradle-plugin/best-practices-baseline.json index 457d0dce9..d9de5d6c2 100644 --- a/platforms/gradle/foundry-gradle-plugin/best-practices-baseline.json +++ b/platforms/gradle/foundry-gradle-plugin/best-practices-baseline.json @@ -1 +1 @@ -{"issues":[{"type":"get_subprojects","name":"getSubprojects","trace":{"trace":[{"owner":"foundry/gradle/FoundryBasePlugin","name":"apply","descriptor":"(Ljava/lang/Object;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/FoundryBasePlugin","name":"apply","descriptor":"(Lorg/gradle/api/Project;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/topography/ModuleTopographyTasks","name":"configureRootProject","descriptor":"(Lorg/gradle/api/Project;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver$default","descriptor":"(Lfoundry/gradle/artifacts/Resolver$Companion;Lorg/gradle/api/Project;Lfoundry/gradle/artifacts/FoundryArtifact;ZILjava/lang/Object;)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver","descriptor":"(Lorg/gradle/api/Project;Lfoundry/gradle/artifacts/FoundryArtifact;Z)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver","descriptor":"(Lorg/gradle/api/Project;Lorg/gradle/api/attributes/Attribute;Ljava/io/Serializable;Ljava/lang/String;Ljava/lang/String;Z)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver","name":"addSubprojectDependencies","descriptor":"(Lorg/gradle/api/Project;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"org/gradle/api/Project","name":"getSubprojects","descriptor":"()Ljava/util/Set;","metadata":{"isTaskAction":false,"isVirtual":false}}]}},{"type":"get_subprojects","name":"getSubprojects","trace":{"trace":[{"owner":"foundry/gradle/FoundryRootPlugin","name":"apply","descriptor":"(Ljava/lang/Object;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/FoundryRootPlugin","name":"apply","descriptor":"(Lorg/gradle/api/Project;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/FoundryRootPlugin","name":"configureRootProject","descriptor":"(Lorg/gradle/api/Project;Lfoundry/gradle/FoundryProperties;Lorg/gradle/api/provider/Provider;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/tasks/AndroidTestApksTask$Companion","name":"register$foundry_gradle_plugin","descriptor":"(Lorg/gradle/api/Project;)Lorg/gradle/api/tasks/TaskProvider;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver$default","descriptor":"(Lfoundry/gradle/artifacts/Resolver$Companion;Lorg/gradle/api/Project;Lfoundry/gradle/artifacts/FoundryArtifact;ZILjava/lang/Object;)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver","descriptor":"(Lorg/gradle/api/Project;Lfoundry/gradle/artifacts/FoundryArtifact;Z)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver","descriptor":"(Lorg/gradle/api/Project;Lorg/gradle/api/attributes/Attribute;Ljava/io/Serializable;Ljava/lang/String;Ljava/lang/String;Z)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver","name":"addSubprojectDependencies","descriptor":"(Lorg/gradle/api/Project;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"org/gradle/api/Project","name":"getSubprojects","descriptor":"()Ljava/util/Set;","metadata":{"isTaskAction":false,"isVirtual":false}}]}},{"type":"get_subprojects","name":"getSubprojects","trace":{"trace":[{"owner":"foundry/gradle/FoundryRootPlugin$configureRootProject$15","name":"execute","descriptor":"(Ljava/lang/Object;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/FoundryRootPlugin$configureRootProject$15","name":"execute","descriptor":"(Lorg/gradle/api/plugins/AppliedPlugin;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/dependencyrake/MissingIdentifiersAggregatorTask$Companion","name":"register","descriptor":"(Lorg/gradle/api/Project;)Lorg/gradle/api/tasks/TaskProvider;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver$default","descriptor":"(Lfoundry/gradle/artifacts/Resolver$Companion;Lorg/gradle/api/Project;Lfoundry/gradle/artifacts/FoundryArtifact;ZILjava/lang/Object;)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver","descriptor":"(Lorg/gradle/api/Project;Lfoundry/gradle/artifacts/FoundryArtifact;Z)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver","descriptor":"(Lorg/gradle/api/Project;Lorg/gradle/api/attributes/Attribute;Ljava/io/Serializable;Ljava/lang/String;Ljava/lang/String;Z)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver","name":"addSubprojectDependencies","descriptor":"(Lorg/gradle/api/Project;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"org/gradle/api/Project","name":"getSubprojects","descriptor":"()Ljava/util/Set;","metadata":{"isTaskAction":false,"isVirtual":false}}]}},{"type":"get_subprojects","name":"getSubprojects","trace":{"trace":[{"owner":"foundry/gradle/stats/ModuleStatsTasks$configureRoot$1$1","name":"call","descriptor":"()Ljava/lang/Object;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/stats/ModuleStatsTasks$configureRoot$1$1","name":"call","descriptor":"()Ljava/util/Map;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"org/gradle/api/Project","name":"getSubprojects","descriptor":"()Ljava/util/Set;","metadata":{"isTaskAction":false,"isVirtual":false}}]}},{"type":"get_subprojects","name":"getSubprojects","trace":{"trace":[{"owner":"foundry/gradle/FoundryRootPlugin$configureRootProject$5","name":"accept","descriptor":"(Ljava/lang/Object;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/FoundryRootPlugin$configureRootProject$5","name":"accept","descriptor":"(Ljava/lang/String;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/testing/RoborazziTests","name":"configureRootProject","descriptor":"(Lorg/gradle/api/Project;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver$default","descriptor":"(Lfoundry/gradle/artifacts/Resolver$Companion;Lorg/gradle/api/Project;Lfoundry/gradle/artifacts/FoundryArtifact;ZILjava/lang/Object;)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver","descriptor":"(Lorg/gradle/api/Project;Lfoundry/gradle/artifacts/FoundryArtifact;Z)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver","descriptor":"(Lorg/gradle/api/Project;Lorg/gradle/api/attributes/Attribute;Ljava/io/Serializable;Ljava/lang/String;Ljava/lang/String;Z)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver","name":"addSubprojectDependencies","descriptor":"(Lorg/gradle/api/Project;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"org/gradle/api/Project","name":"getSubprojects","descriptor":"()Ljava/util/Set;","metadata":{"isTaskAction":false,"isVirtual":false}}]}},{"type":"get_subprojects","name":"getSubprojects","trace":{"trace":[{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver$default","descriptor":"(Lfoundry/gradle/artifacts/Resolver$Companion;Lorg/gradle/api/Project;Lorg/gradle/api/attributes/Attribute;Ljava/io/Serializable;Ljava/lang/String;Ljava/lang/String;ZILjava/lang/Object;)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver","descriptor":"(Lorg/gradle/api/Project;Lorg/gradle/api/attributes/Attribute;Ljava/io/Serializable;Ljava/lang/String;Ljava/lang/String;Z)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver","name":"addSubprojectDependencies","descriptor":"(Lorg/gradle/api/Project;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"org/gradle/api/Project","name":"getSubprojects","descriptor":"()Ljava/util/Set;","metadata":{"isTaskAction":false,"isVirtual":false}}]}},{"type":"get_subprojects","name":"getSubprojects","trace":{"trace":[{"owner":"foundry/gradle/FoundryRootPlugin$configureRootProject$6","name":"accept","descriptor":"(Ljava/lang/Object;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/FoundryRootPlugin$configureRootProject$6","name":"accept","descriptor":"(Ljava/lang/String;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/testing/EmulatorWtfTests","name":"configureRootProject","descriptor":"(Lorg/gradle/api/Project;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver$default","descriptor":"(Lfoundry/gradle/artifacts/Resolver$Companion;Lorg/gradle/api/Project;Lfoundry/gradle/artifacts/FoundryArtifact;ZILjava/lang/Object;)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver","descriptor":"(Lorg/gradle/api/Project;Lfoundry/gradle/artifacts/FoundryArtifact;Z)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver","descriptor":"(Lorg/gradle/api/Project;Lorg/gradle/api/attributes/Attribute;Ljava/io/Serializable;Ljava/lang/String;Ljava/lang/String;Z)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver","name":"addSubprojectDependencies","descriptor":"(Lorg/gradle/api/Project;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"org/gradle/api/Project","name":"getSubprojects","descriptor":"()Ljava/util/Set;","metadata":{"isTaskAction":false,"isVirtual":false}}]}}]} \ No newline at end of file +{"issues":[{"type":"get_subprojects","name":"getSubprojects","trace":{"trace":[{"owner":"foundry/gradle/FoundryBasePlugin","name":"apply","descriptor":"(Ljava/lang/Object;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/FoundryBasePlugin","name":"apply","descriptor":"(Lorg/gradle/api/Project;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/topography/ModuleTopographyTasks","name":"configureRootProject","descriptor":"(Lorg/gradle/api/Project;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver$default","descriptor":"(Lfoundry/gradle/artifacts/Resolver$Companion;Lorg/gradle/api/Project;Lfoundry/gradle/artifacts/FoundryArtifact;ZILjava/lang/Object;)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver","descriptor":"(Lorg/gradle/api/Project;Lfoundry/gradle/artifacts/FoundryArtifact;Z)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver","descriptor":"(Lorg/gradle/api/Project;Lorg/gradle/api/attributes/Attribute;Ljava/io/Serializable;Ljava/lang/String;Ljava/lang/String;Z)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver","name":"addSubprojectDependencies","descriptor":"(Lorg/gradle/api/Project;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"org/gradle/api/Project","name":"getSubprojects","descriptor":"()Ljava/util/Set;","metadata":{"isTaskAction":false,"isVirtual":false}}]}},{"type":"get_subprojects","name":"getSubprojects","trace":{"trace":[{"owner":"foundry/gradle/FoundryRootPlugin","name":"apply","descriptor":"(Ljava/lang/Object;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/FoundryRootPlugin","name":"apply","descriptor":"(Lorg/gradle/api/Project;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/FoundryRootPlugin","name":"configureRootProject","descriptor":"(Lorg/gradle/api/Project;Lfoundry/gradle/FoundryProperties;Lorg/gradle/api/provider/Provider;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/tasks/AndroidTestApksTask$Companion","name":"register$foundry_gradle_plugin","descriptor":"(Lorg/gradle/api/Project;)Lorg/gradle/api/tasks/TaskProvider;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver$default","descriptor":"(Lfoundry/gradle/artifacts/Resolver$Companion;Lorg/gradle/api/Project;Lfoundry/gradle/artifacts/FoundryArtifact;ZILjava/lang/Object;)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver","descriptor":"(Lorg/gradle/api/Project;Lfoundry/gradle/artifacts/FoundryArtifact;Z)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver","descriptor":"(Lorg/gradle/api/Project;Lorg/gradle/api/attributes/Attribute;Ljava/io/Serializable;Ljava/lang/String;Ljava/lang/String;Z)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver","name":"addSubprojectDependencies","descriptor":"(Lorg/gradle/api/Project;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"org/gradle/api/Project","name":"getSubprojects","descriptor":"()Ljava/util/Set;","metadata":{"isTaskAction":false,"isVirtual":false}}]}},{"type":"get_subprojects","name":"getSubprojects","trace":{"trace":[{"owner":"foundry/gradle/stats/ModuleStatsTasks$configureRoot$1$1","name":"call","descriptor":"()Ljava/lang/Object;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/stats/ModuleStatsTasks$configureRoot$1$1","name":"call","descriptor":"()Ljava/util/Map;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"org/gradle/api/Project","name":"getSubprojects","descriptor":"()Ljava/util/Set;","metadata":{"isTaskAction":false,"isVirtual":false}}]}},{"type":"get_subprojects","name":"getSubprojects","trace":{"trace":[{"owner":"foundry/gradle/FoundryRootPlugin$configureRootProject$6","name":"accept","descriptor":"(Ljava/lang/Object;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/FoundryRootPlugin$configureRootProject$6","name":"accept","descriptor":"(Ljava/lang/String;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/testing/RoborazziTests","name":"configureRootProject","descriptor":"(Lorg/gradle/api/Project;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver$default","descriptor":"(Lfoundry/gradle/artifacts/Resolver$Companion;Lorg/gradle/api/Project;Lfoundry/gradle/artifacts/FoundryArtifact;ZILjava/lang/Object;)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver","descriptor":"(Lorg/gradle/api/Project;Lfoundry/gradle/artifacts/FoundryArtifact;Z)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver","descriptor":"(Lorg/gradle/api/Project;Lorg/gradle/api/attributes/Attribute;Ljava/io/Serializable;Ljava/lang/String;Ljava/lang/String;Z)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver","name":"addSubprojectDependencies","descriptor":"(Lorg/gradle/api/Project;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"org/gradle/api/Project","name":"getSubprojects","descriptor":"()Ljava/util/Set;","metadata":{"isTaskAction":false,"isVirtual":false}}]}},{"type":"get_subprojects","name":"getSubprojects","trace":{"trace":[{"owner":"foundry/gradle/FoundryRootPlugin$configureRootProject$16","name":"execute","descriptor":"(Ljava/lang/Object;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/FoundryRootPlugin$configureRootProject$16","name":"execute","descriptor":"(Lorg/gradle/api/plugins/AppliedPlugin;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/dependencyrake/MissingIdentifiersAggregatorTask$Companion","name":"register","descriptor":"(Lorg/gradle/api/Project;)Lorg/gradle/api/tasks/TaskProvider;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver$default","descriptor":"(Lfoundry/gradle/artifacts/Resolver$Companion;Lorg/gradle/api/Project;Lfoundry/gradle/artifacts/FoundryArtifact;ZILjava/lang/Object;)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver","descriptor":"(Lorg/gradle/api/Project;Lfoundry/gradle/artifacts/FoundryArtifact;Z)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver","descriptor":"(Lorg/gradle/api/Project;Lorg/gradle/api/attributes/Attribute;Ljava/io/Serializable;Ljava/lang/String;Ljava/lang/String;Z)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver","name":"addSubprojectDependencies","descriptor":"(Lorg/gradle/api/Project;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"org/gradle/api/Project","name":"getSubprojects","descriptor":"()Ljava/util/Set;","metadata":{"isTaskAction":false,"isVirtual":false}}]}},{"type":"get_subprojects","name":"getSubprojects","trace":{"trace":[{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver$default","descriptor":"(Lfoundry/gradle/artifacts/Resolver$Companion;Lorg/gradle/api/Project;Lorg/gradle/api/attributes/Attribute;Ljava/io/Serializable;Ljava/lang/String;Ljava/lang/String;ZILjava/lang/Object;)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver","descriptor":"(Lorg/gradle/api/Project;Lorg/gradle/api/attributes/Attribute;Ljava/io/Serializable;Ljava/lang/String;Ljava/lang/String;Z)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver","name":"addSubprojectDependencies","descriptor":"(Lorg/gradle/api/Project;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"org/gradle/api/Project","name":"getSubprojects","descriptor":"()Ljava/util/Set;","metadata":{"isTaskAction":false,"isVirtual":false}}]}},{"type":"get_subprojects","name":"getSubprojects","trace":{"trace":[{"owner":"foundry/gradle/FoundryRootPlugin$configureRootProject$7","name":"accept","descriptor":"(Ljava/lang/Object;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/FoundryRootPlugin$configureRootProject$7","name":"accept","descriptor":"(Ljava/lang/String;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/testing/EmulatorWtfTests","name":"configureRootProject","descriptor":"(Lorg/gradle/api/Project;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver$default","descriptor":"(Lfoundry/gradle/artifacts/Resolver$Companion;Lorg/gradle/api/Project;Lfoundry/gradle/artifacts/FoundryArtifact;ZILjava/lang/Object;)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver","descriptor":"(Lorg/gradle/api/Project;Lfoundry/gradle/artifacts/FoundryArtifact;Z)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver$Companion","name":"interProjectResolver","descriptor":"(Lorg/gradle/api/Project;Lorg/gradle/api/attributes/Attribute;Ljava/io/Serializable;Ljava/lang/String;Ljava/lang/String;Z)Lfoundry/gradle/artifacts/Resolver;","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"foundry/gradle/artifacts/Resolver","name":"addSubprojectDependencies","descriptor":"(Lorg/gradle/api/Project;)V","metadata":{"isTaskAction":false,"isVirtual":false}},{"owner":"org/gradle/api/Project","name":"getSubprojects","descriptor":"()Ljava/util/Set;","metadata":{"isTaskAction":false,"isVirtual":false}}]}}]} \ No newline at end of file