From 0697dd3aadd6c13d9e2d321c75173992bfbaac3b Mon Sep 17 00:00:00 2001 From: Daymon <17409137+daymxn@users.noreply.github.com> Date: Thu, 24 Oct 2024 15:05:21 -0500 Subject: [PATCH] Modernize FirebaseLibraryExtension (#6377) Per [b/270576405](https://b.corp.google.com/issues/270576405), This migrates `FirebaseLibraryExtension` to Kotlin, and takes advantage of more modern gradle features (such as properties/conventions) to help with build time and maintenance. This also adds documentation for all the exposed properties and options on `FirebaseLibraryExtension`. Future `TODO`s have been left denoting possible future modernization efforts. This PR also fixes the following: - [b/374137268](https://b.corp.google.com/issues/374137268) -> Migrate buildSrc to spotless --- .../firebase-appcheck-debug-testing.gradle | 2 +- .../firebase-appcheck-debug.gradle | 2 +- .../firebase-appcheck-playintegrity.gradle | 2 +- .../firebase-appcheck.gradle | 2 +- appcheck/firebase-appcheck/ktx/ktx.gradle | 2 +- buildSrc/build.gradle.kts | 20 +- .../firebase/gradle/NdkBinaryFixTask.kt | 2 +- .../plugins/BaseFirebaseLibraryPlugin.kt | 124 +++++++- .../firebase/gradle/plugins/Changelog.kt | 4 +- .../gradle/plugins/CheckHeadDependencies.kt | 2 +- .../gradle/plugins/DackkaGenerationTask.kt | 12 +- .../firebase/gradle/plugins/DackkaPlugin.kt | 31 +- ...gin.kt => FirebaseAndroidLibraryPlugin.kt} | 76 +++-- .../plugins/FirebaseJavaLibraryPlugin.kt | 19 +- .../plugins/FirebaseLibraryExtension.java | 203 ------------- .../plugins/FirebaseLibraryExtension.kt | 266 ++++++++++++++++++ .../FirebaseProprietaryLibraryPlugin.kt | 38 --- .../gradle/plugins/GitSubmodulePlugin.kt | 4 +- .../firebase/gradle/plugins/GradleUtils.kt | 7 +- .../firebase/gradle/plugins/KotlinUtils.kt | 8 +- .../firebase/gradle/plugins/LibraryGroups.kt | 8 +- .../gradle/plugins/MakeReleaseNotesTask.kt | 6 +- .../firebase/gradle/plugins/Metalava.kt | 18 +- .../firebase/gradle/plugins/ModuleVersion.kt | 17 +- .../plugins/MoveUnreleasedChangesTask.kt | 11 +- .../firebase/gradle/plugins/PomValidator.kt | 2 +- .../gradle/plugins/PostReleasePlugin.kt | 9 +- .../firebase/gradle/plugins/ProjectUtils.kt | 2 +- .../gradle/plugins/PublishingPlugin.kt | 22 +- .../firebase/gradle/plugins/ReleaseConfig.kt | 5 +- .../gradle/plugins/ReleaseGenerator.kt | 13 +- .../ReleaseNotesConfigurationExtension.kt | 11 +- .../plugins/UpdatePinnedDependenciesTask.kt | 18 +- .../firebase/gradle/plugins/VendorPlugin.kt | 4 +- .../gradle/plugins/VersionBumpTask.kt | 9 +- .../ci/ContinuousIntegrationExtension.java | 3 +- .../firebase/gradle/plugins/ci/Coverage.java | 7 +- .../gradle/plugins/ci/SmokeTestsPlugin.java | 5 +- .../ci/device/FirebaseTestLabExtension.java | 7 +- .../gradle/plugins/semver/AccessDescriptor.kt | 1 + .../gradle/plugins/semver/ApiDiffer.kt | 4 +- .../gradle/plugins/semver/ClassInfo.kt | 2 +- .../gradle/plugins/semver/DeltaType.kt | 62 ++-- .../gradle/plugins/semver/GmavenCopier.kt | 2 +- .../gradle/plugins/FirebaseTestController.kt | 10 +- .../plugins/LicenseResolverPluginTests.kt | 4 +- .../firebase/gradle/plugins/Memoization.kt | 1 + .../gradle/plugins/PublishingPluginTests.kt | 31 +- .../plugins/UpdatePinnedDependenciesTests.kt | 8 +- .../firebase/gradle/plugins/publishing.kt | 14 +- .../firebase-appdistribution-api.gradle | 2 +- firebase-appdistribution-api/ktx/ktx.gradle | 2 +- .../firebase-appdistribution.gradle | 2 +- firebase-common/firebase-common.gradle.kts | 2 +- firebase-common/ktx/ktx.gradle.kts | 2 +- firebase-config/firebase-config.gradle.kts | 2 +- firebase-config/ktx/ktx.gradle | 2 +- .../firebase-crashlytics-ndk.gradle | 2 +- .../firebase-crashlytics.gradle | 2 +- firebase-crashlytics/ktx/ktx.gradle | 2 +- .../firebase-database.gradle.kts | 2 +- firebase-database/ktx/ktx.gradle.kts | 2 +- .../firebase-dataconnect.gradle.kts | 2 +- firebase-dataconnect/google-services.json | 2 +- .../firebase-dynamic-links.gradle | 2 +- firebase-dynamic-links/ktx/ktx.gradle | 2 +- firebase-firestore/firebase-firestore.gradle | 2 +- firebase-firestore/ktx/ktx.gradle | 2 +- .../firebase-functions.gradle.kts | 2 +- firebase-functions/ktx/ktx.gradle.kts | 2 +- .../firebase-inappmessaging-display.gradle | 2 +- .../ktx/ktx.gradle | 2 +- .../firebase-inappmessaging.gradle | 2 +- firebase-inappmessaging/ktx/ktx.gradle | 2 +- .../firebase-installations.gradle | 2 +- firebase-installations/ktx/ktx.gradle | 2 +- .../firebase-messaging-directboot.gradle | 2 +- firebase-messaging/firebase-messaging.gradle | 2 +- firebase-messaging/ktx/ktx.gradle | 2 +- .../firebase-ml-modeldownloader.gradle | 2 +- firebase-ml-modeldownloader/ktx/ktx.gradle | 2 +- firebase-perf/firebase-perf.gradle | 2 +- firebase-perf/ktx/ktx.gradle | 2 +- .../firebase-sessions.gradle.kts | 2 +- firebase-storage/firebase-storage.gradle | 2 +- firebase-storage/ktx/ktx.gradle | 2 +- gradle/libs.versions.toml | 2 +- .../transport-backend-cct.gradle | 2 +- .../transport-runtime.gradle | 2 +- 89 files changed, 695 insertions(+), 525 deletions(-) rename buildSrc/src/main/java/com/google/firebase/gradle/plugins/{FirebaseLibraryPlugin.kt => FirebaseAndroidLibraryPlugin.kt} (76%) delete mode 100644 buildSrc/src/main/java/com/google/firebase/gradle/plugins/FirebaseLibraryExtension.java create mode 100644 buildSrc/src/main/java/com/google/firebase/gradle/plugins/FirebaseLibraryExtension.kt delete mode 100644 buildSrc/src/main/java/com/google/firebase/gradle/plugins/FirebaseProprietaryLibraryPlugin.kt diff --git a/appcheck/firebase-appcheck-debug-testing/firebase-appcheck-debug-testing.gradle b/appcheck/firebase-appcheck-debug-testing/firebase-appcheck-debug-testing.gradle index dda6c064cb0..c022f76fbdc 100644 --- a/appcheck/firebase-appcheck-debug-testing/firebase-appcheck-debug-testing.gradle +++ b/appcheck/firebase-appcheck-debug-testing/firebase-appcheck-debug-testing.gradle @@ -18,7 +18,7 @@ plugins { } firebaseLibrary { - libraryGroup "appcheck" + libraryGroup = "appcheck" testLab.enabled = true publishSources = true releaseNotes { diff --git a/appcheck/firebase-appcheck-debug/firebase-appcheck-debug.gradle b/appcheck/firebase-appcheck-debug/firebase-appcheck-debug.gradle index 6876a7456f3..63d459f6ba5 100644 --- a/appcheck/firebase-appcheck-debug/firebase-appcheck-debug.gradle +++ b/appcheck/firebase-appcheck-debug/firebase-appcheck-debug.gradle @@ -17,7 +17,7 @@ plugins { } firebaseLibrary { - libraryGroup "appcheck" + libraryGroup = "appcheck" publishSources = true releaseNotes { name.set("{{app_check}} Debug") diff --git a/appcheck/firebase-appcheck-playintegrity/firebase-appcheck-playintegrity.gradle b/appcheck/firebase-appcheck-playintegrity/firebase-appcheck-playintegrity.gradle index 00c2b5d130a..018efb4100a 100644 --- a/appcheck/firebase-appcheck-playintegrity/firebase-appcheck-playintegrity.gradle +++ b/appcheck/firebase-appcheck-playintegrity/firebase-appcheck-playintegrity.gradle @@ -17,7 +17,7 @@ plugins { } firebaseLibrary { - libraryGroup "appcheck" + libraryGroup = "appcheck" publishSources = true releaseNotes { name.set("{{app_check}} Play integrity") diff --git a/appcheck/firebase-appcheck/firebase-appcheck.gradle b/appcheck/firebase-appcheck/firebase-appcheck.gradle index 707607fe7d2..9706d01818a 100644 --- a/appcheck/firebase-appcheck/firebase-appcheck.gradle +++ b/appcheck/firebase-appcheck/firebase-appcheck.gradle @@ -18,7 +18,7 @@ plugins { } firebaseLibrary { - libraryGroup "appcheck" + libraryGroup = "appcheck" publishSources = true releaseNotes { name.set("{{app_check}}") diff --git a/appcheck/firebase-appcheck/ktx/ktx.gradle b/appcheck/firebase-appcheck/ktx/ktx.gradle index 6ba439c38de..32ed6eb083a 100644 --- a/appcheck/firebase-appcheck/ktx/ktx.gradle +++ b/appcheck/firebase-appcheck/ktx/ktx.gradle @@ -18,7 +18,7 @@ plugins { } firebaseLibrary { - libraryGroup "appcheck" + libraryGroup = "appcheck" testLab.enabled = true publishJavadoc = false releaseNotes { diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 8604f9447e5..ab77d58e547 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -13,8 +13,8 @@ // limitations under the License. plugins { - id("com.ncorti.ktfmt.gradle") version "0.11.0" alias(libs.plugins.kotlinx.serialization) + alias(libs.plugins.spotless) `kotlin-dsl` } @@ -26,15 +26,23 @@ repositories { maven(url = "https://plugins.gradle.org/m2/") } +spotless { + java { + target("src/**/*.java") + targetExclude("**/test/resources/**") + googleJavaFormat("1.22.0").reorderImports(true).skipJavadocFormatting() + } + kotlin { + target("src/**/*.kt") + ktfmt("0.52").googleStyle() + } +} + // Refer latest "perf-plugin" released version on https://maven.google.com/web/index.html?q=perf-plugin#com.google.firebase:perf-plugin // The System property allows us to integrate with an unreleased version from https://bityl.co/3oYt. // Refer go/fireperf-plugin-test-on-head for more details. val perfPluginVersion = System.getenv("FIREBASE_PERF_PLUGIN_VERSION") ?: "1.4.1" -ktfmt { - googleStyle() -} - dependencies { // Firebase performance plugin, it should be added here because of how gradle dependency // resolution works, otherwise it breaks Fireperf Test Apps. @@ -84,7 +92,7 @@ gradlePlugin { } register("firebaseLibraryPlugin") { id = "firebase-library" - implementationClass = "com.google.firebase.gradle.plugins.FirebaseLibraryPlugin" + implementationClass = "com.google.firebase.gradle.plugins.FirebaseAndroidLibraryPlugin" } register("firebaseJavaLibraryPlugin") { id = "firebase-java-library" diff --git a/buildSrc/src/main/java/com/google/firebase/gradle/NdkBinaryFixTask.kt b/buildSrc/src/main/java/com/google/firebase/gradle/NdkBinaryFixTask.kt index e5403468871..c4948366de2 100644 --- a/buildSrc/src/main/java/com/google/firebase/gradle/NdkBinaryFixTask.kt +++ b/buildSrc/src/main/java/com/google/firebase/gradle/NdkBinaryFixTask.kt @@ -42,7 +42,7 @@ abstract class NdkBinaryFixTask : DefaultTask() { Files.copy( inputFile.get().asFile.toPath(), outputFile.toPath(), - StandardCopyOption.REPLACE_EXISTING + StandardCopyOption.REPLACE_EXISTING, ) } } diff --git a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/BaseFirebaseLibraryPlugin.kt b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/BaseFirebaseLibraryPlugin.kt index 82477b0d74d..f9108053f10 100644 --- a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/BaseFirebaseLibraryPlugin.kt +++ b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/BaseFirebaseLibraryPlugin.kt @@ -23,12 +23,14 @@ import java.nio.file.Paths import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.api.artifacts.ProjectDependency +import org.gradle.api.provider.Provider import org.gradle.api.publish.PublishingExtension import org.gradle.api.publish.maven.MavenPom import org.gradle.api.publish.maven.MavenPublication import org.gradle.api.publish.maven.plugins.MavenPublishPlugin import org.gradle.api.tasks.TaskProvider import org.gradle.kotlin.dsl.apply +import org.gradle.kotlin.dsl.assign import org.gradle.kotlin.dsl.configure import org.gradle.kotlin.dsl.create import org.gradle.kotlin.dsl.findByType @@ -37,7 +39,61 @@ import org.gradle.kotlin.dsl.provideDelegate import org.gradle.kotlin.dsl.register import org.w3c.dom.Element +/** + * Plugin for Firebase Libraries. + * + * Implements shared functionality between Java and Android libraries. + * + * @see [FirebaseAndroidLibraryPlugin] + * @see [FirebaseJavaLibraryPlugin] + * @see [FirebaseLibraryExtension] + */ abstract class BaseFirebaseLibraryPlugin : Plugin { + protected fun setupDefaults(project: Project, library: FirebaseLibraryExtension) { + with(library) { + previewMode.convention("") + publishJavadoc.convention(true) + publishSources.convention(true) + artifactId.convention(project.name) + groupId.convention(project.provider { project.group.toString() }) + libraryGroup.convention(artifactId) + + customizePom { + licenses { + license { + name = "The Apache Software License, Version 2.0" + url = "http://www.apache.org/licenses/LICENSE-2.0.txt" + } + } + scm { + connection = "scm:git:https://github.com/firebase/firebase-android-sdk.git" + url = "https://github.com/firebase/firebase-android-sdk" + } + } + + releaseNotes { + enabled.convention(true) + hasKTX.convention(true) + artifactId.convention(project.name) + artifactName.convention(project.name) + } + + val parent = project.parent + // TODO(): remove when we get rid of ktx modules + if (project.name == "ktx" && parent !== null) { + artifactId.convention(parent.provider { "${parent.name}-ktx" }) + groupId.convention(parent.provider { "${parent.group}" }) + } + + androidLintCheckProjects.convention( + project + .provideProperty("firebase.checks.lintProjects") + .map { it.split(",") } + .orElse(emptyList()) + ) + } + } + protected fun registerMakeReleaseNotesTask(project: Project) = project.tasks.register("makeReleaseNotes") { val changelog = project.file("CHANGELOG.md") @@ -59,8 +115,8 @@ abstract class BaseFirebaseLibraryPlugin : Plugin { project.afterEvaluate { configurations.all { if ("lintChecks" == name) { - for (checkProject in library.staticAnalysis.androidLintCheckProjects) { - project.dependencies.add("lintChecks", project.project(checkProject!!)) + for (checkProject in library.androidLintCheckProjects.get()) { + project.dependencies.add("lintChecks", project.project(checkProject)) } } } @@ -75,7 +131,7 @@ abstract class BaseFirebaseLibraryPlugin : Plugin { Paths.get( project.rootProject.buildDir.path, "apiinfo", - project.path.substring(1).replace(":", "_") + project.path.substring(1).replace(":", "_"), ) ) val outputApiFile = File(outputFile.absolutePath + "_api.txt") @@ -122,23 +178,26 @@ abstract class BaseFirebaseLibraryPlugin : Plugin { * configures maven pom generation. * * @see [applyPomTransformations] - * @see [FirebaseLibraryExtension.applyPomCustomization] + * @see [FirebaseLibraryExtension.customizePomAction] */ protected fun configurePublishing(project: Project, firebaseLibrary: FirebaseLibraryExtension) { with(project) { apply() + + // TODO(b/371625225): sources jar is missing from java libs extensions.configure { repositories.maven { url = rootProject.fileFromBuildDir("m2repository").toURI() name = "BuildDir" } publications.create("mavenAar") { + // TODO(https://github.com/gradle/gradle/issues/18619): Remove afterEvaluate when + // properties are supported afterEvaluate { - artifactId = - firebaseLibrary.artifactId.get() // these dont get populated until afterEvaluate :( + artifactId = firebaseLibrary.artifactId.get() groupId = firebaseLibrary.groupId.get() - firebaseLibrary.applyPomCustomization(pom) + pom(firebaseLibrary.customizePomAction) firebaseLibrary.applyPomTransformations(pom) from(components.findByName(firebaseLibrary.type.componentName)) } @@ -155,7 +214,6 @@ abstract class BaseFirebaseLibraryPlugin : Plugin { * @param pom the [MavenPom] to prepare * @see [addTypeWithAARSupport] */ - // TODO(b/270576405): Combine with applyPomCustomization when migrating FirebaseLibraryExtension private fun FirebaseLibraryExtension.applyPomTransformations(pom: MavenPom) { pom.withXml { val dependencies = asElement().findElementsByTag("dependency") @@ -198,7 +256,7 @@ abstract class BaseFirebaseLibraryPlugin : Plugin { /** * A list of _all_ dependencies that publish `aar` artifacts. * - * This is collected via the [runtimeClasspath][FirebaseLibraryExtension.getRuntimeClasspath], and + * This is collected via the [runtimeClasspath][FirebaseLibraryExtension.runtimeClasspath], and * includes project level dependencies as well as external dependencies. * * The dependencies are mapped to their [mavenName][toMavenName]. @@ -209,15 +267,17 @@ abstract class BaseFirebaseLibraryPlugin : Plugin { // TODO(b/277607560): Remove when Gradle's MavenPublishPlugin adds functionality for aar types fun FirebaseLibraryExtension.resolveAndroidDependencies() = resolveExternalAndroidLibraries() + - resolveProjectLevelDependencies().filter { it.type == LibraryType.ANDROID }.map { it.mavenName } + resolveProjectLevelDependencies() + .filter { it.type == LibraryType.ANDROID } + .map { it.mavenName.get() } /** * A list of project level dependencies. * - * This is collected via the [runtimeClasspath][FirebaseLibraryExtension.getRuntimeClasspath]. + * This is collected via the [runtimeClasspath][FirebaseLibraryExtension.runtimeClasspath]. * * @throws RuntimeException if a project level dependency is found that doesn't have - * [FirebaseLibraryExtension] + * [FirebaseLibraryExtension] */ // TODO(b/277607560): Remove when Gradle's MavenPublishPlugin adds functionality for aar types fun FirebaseLibraryExtension.resolveProjectLevelDependencies() = @@ -264,16 +324,23 @@ fun FirebaseLibraryExtension.resolveExternalAndroidLibraries() = * ``` * "com.google.firebase:firebase-common:16.0.5" * ``` + * + * @see [mavenName] */ val FirebaseLibraryExtension.artifactName: String - get() = "$mavenName:$version" + get() = "${mavenName.get()}:$version" /** * Fetches the latest version for this SDK from GMaven. * * Uses [GmavenHelper] to make the request. + * + * To get the latest released version per the local `gradle.properties`, use [latestReleasedVersion] + * . + * + * @see [ModuleVersion] */ -val FirebaseLibraryExtension.latestVersion: ModuleVersion +val FirebaseLibraryExtension.latestGMavenVersion: ModuleVersion get() { val latestVersion = GmavenHelper(groupId.get(), artifactId.get()).getLatestReleasedVersion() @@ -283,6 +350,22 @@ val FirebaseLibraryExtension.latestVersion: ModuleVersion ) } +/** + * The latest version released, per the `gradle.properties` file. + * + * Checks for the property `latestReleasedVersion`, which should be in the `gradle.properties` files + * of released SDKs (alongside the current `version`). + * + * To fetch the latest released version per GMaven, use [latestGMavenVersion]. + * + * ```properties + * version=19.2.1 + * latestReleasedVersion=19.2.0 + * ``` + */ +val FirebaseLibraryExtension.latestReleasedVersion: Provider + get() = project.provideProperty("latestReleasedVersion") + /** * Fetches the namespace for this SDK from the [LibraryExtension]. * @@ -298,3 +381,16 @@ val FirebaseLibraryExtension.namespace: String get() = project.extensions.getByType().namespace ?: throw RuntimeException("Project doesn't have a defined namespace: ${project.path}") + +/** + * The name of this library on maven, without the version. + * + * For example, the following could be a maven name: + * ``` + * "com.google.firebase:firebase-common" + * ``` + * + * @see [artifactName] + */ +val FirebaseLibraryExtension.mavenName: Provider + get() = groupId.zip(artifactId) { groupId, artifactId -> "$groupId:$artifactId" } diff --git a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/Changelog.kt b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/Changelog.kt index 6d90bfad6b8..e3ea7ebdf5c 100644 --- a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/Changelog.kt +++ b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/Changelog.kt @@ -118,7 +118,7 @@ data class Changelog(val releases: List) { data class ReleaseEntry( val version: ModuleVersion?, val content: ReleaseContent, - val ktx: ReleaseContent? + val ktx: ReleaseContent?, ) { override fun toString(): String { @@ -151,7 +151,7 @@ data class ReleaseEntry( * This exists to provide a means for tooling to create new sections explicitly, versus offering * default values to [ReleaseEntry] * - as this could lead to edge case scenarios where empty [ReleaseEntry] instances are - * accidentally created. + * accidentally created. */ val Empty = ReleaseEntry(null, ReleaseContent("", emptyList()), null) diff --git a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/CheckHeadDependencies.kt b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/CheckHeadDependencies.kt index 4e5bb48127d..d23fdbd8541 100644 --- a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/CheckHeadDependencies.kt +++ b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/CheckHeadDependencies.kt @@ -30,7 +30,7 @@ import org.gradle.api.tasks.TaskAction * [FirebaseLibraryExtension.artifactId], so that the check is version agnostic. * * @throws GradleException if any project level dependencies are found that are not included in the - * release + * release */ abstract class CheckHeadDependencies : DefaultTask() { @get:Input abstract val projectsToPublish: ListProperty diff --git a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/DackkaGenerationTask.kt b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/DackkaGenerationTask.kt index 08573735f98..663ac35365a 100644 --- a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/DackkaGenerationTask.kt +++ b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/DackkaGenerationTask.kt @@ -116,7 +116,7 @@ constructor(private val workerExecutor: WorkerExecutor) : GenerateDocumentationT "kotlin.OptIn", "kotlin.ParameterName", "kotlin.js.JsName", - "java.lang.Override" + "java.lang.Override", ) val annotationsNotToDisplayKotlin = listOf("kotlin.ExtensionFunctionType") @@ -137,7 +137,7 @@ constructor(private val workerExecutor: WorkerExecutor) : GenerateDocumentationT "externalDocumentationLinks" to createExternalLinks(packageListFiles).map { mapOf("url" to it.externalLink, "packageListUrl" to it.packageList.toURI()) - } + }, ) ), "offlineMode" to "true", @@ -159,12 +159,12 @@ constructor(private val workerExecutor: WorkerExecutor) : GenerateDocumentationT "includedHeadTagsPathKotlin" to "docs/reference/kotlin/_reference-head-tags.html", "annotationsNotToDisplay" to annotationsNotToDisplay, - "annotationsNotToDisplayKotlin" to annotationsNotToDisplayKotlin + "annotationsNotToDisplayKotlin" to annotationsNotToDisplayKotlin, ) ) - .toString() + .toString(), ) - ) + ), ) return JSONObject(jsonMap) @@ -180,7 +180,7 @@ constructor(private val workerExecutor: WorkerExecutor) : GenerateDocumentationT "google" to "https://developers.google.com/android/reference/", "firebase" to "https://firebase.google.com/docs/reference/kotlin/", "coroutines" to "https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/", - "kotlin" to "https://kotlinlang.org/api/latest/jvm/stdlib/" + "kotlin" to "https://kotlinlang.org/api/latest/jvm/stdlib/", ) return packageLists diff --git a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/DackkaPlugin.kt b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/DackkaPlugin.kt index c4cd9de6019..32cc65d6edc 100644 --- a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/DackkaPlugin.kt +++ b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/DackkaPlugin.kt @@ -123,15 +123,16 @@ abstract class DackkaPlugin : Plugin { // TODO(b/270576405): remove afterEvalutate after fixed project.afterEvaluate { if (weShouldPublish(this)) { - val dackkaOutputDirectory = provider { fileFromBuildDir("dackkaRawOutput") } - val transformedFilesDirectory = provider { fileFromBuildDir("dackkaTransformedFiles") } + val generateDocumentation = registerGenerateDackkaDocumentationTask(project) + + val outputDir = generateDocumentation.flatMap { it.outputDirectory } + + val firesiteTransform = registerFiresiteTransformTask(project, outputDir) + + val transformedDir = firesiteTransform.flatMap { it.outputDirectory } - val generateDocumentation = - registerGenerateDackkaDocumentationTask(project, dackkaOutputDirectory) - val firesiteTransform = - registerFiresiteTransformTask(project, dackkaOutputDirectory, transformedFilesDirectory) val copyDocsToCommonDirectory = - registerCopyDocsToCommonDirectoryTask(project, transformedFilesDirectory) + registerCopyDocsToCommonDirectoryTask(project, transformedDir) kotlinDoc.configure { dependsOn(generateDocumentation, firesiteTransform, copyDocsToCommonDirectory) @@ -150,7 +151,7 @@ abstract class DackkaPlugin : Plugin { * * This is done via the [FirebaseLibraryExtension.publishJavadoc] property. */ - private fun weShouldPublish(project: Project) = project.firebaseLibrary.publishJavadoc + private fun weShouldPublish(project: Project) = project.firebaseLibrary.publishJavadoc.get() /** * Applies common configuration to the [javadocConfig], that is otherwise not present. @@ -167,8 +168,7 @@ abstract class DackkaPlugin : Plugin { } private fun registerGenerateDackkaDocumentationTask( - project: Project, - targetDirectory: Provider, + project: Project ): TaskProvider = project.tasks.register("generateDackkaDocumentation") { with(project.extensions.getByType()) { @@ -181,9 +181,11 @@ abstract class DackkaPlugin : Plugin { sourceSets.flatMap { it.javaDirectories } + sourceSets.flatMap { it.kotlinDirectories } + val outputDir by tempFile("dackkaRawOutput") + sources.set(sourceDirectories) dependencies.set(classpath) - outputDirectory.set(targetDirectory) + outputDirectory.set(outputDir) suppressedFiles.set(emptyList()) packageListFiles.set(fetchPackageLists(project)) @@ -211,13 +213,12 @@ abstract class DackkaPlugin : Plugin { private fun registerFiresiteTransformTask( project: Project, dackkaOutputDirectory: Provider, - targetDirectory: Provider ) = project.tasks.register("firesiteTransform") { - dependsOnAndMustRunAfter("generateDackkaDocumentation") + val outputDir by tempFile("dackkaTransformedFiles") dackkaFiles.set(dackkaOutputDirectory.childFile("docs/reference")) - outputDirectory.set(targetDirectory) + outputDirectory.set(outputDir) } private fun registerCopyDocsToCommonDirectoryTask( @@ -225,8 +226,6 @@ abstract class DackkaPlugin : Plugin { transformedFilesDirectory: Provider, ) = project.tasks.register("copyDocsToCommonDirectory") { - mustRunAfter("firesiteTransform") - from(transformedFilesDirectory) into(project.rootProject.fileFromBuildDir("firebase-kotlindoc")) } diff --git a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/FirebaseLibraryPlugin.kt b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/FirebaseAndroidLibraryPlugin.kt similarity index 76% rename from buildSrc/src/main/java/com/google/firebase/gradle/plugins/FirebaseLibraryPlugin.kt rename to buildSrc/src/main/java/com/google/firebase/gradle/plugins/FirebaseAndroidLibraryPlugin.kt index ef3e05e5506..e07d9ac161f 100644 --- a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/FirebaseLibraryPlugin.kt +++ b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/FirebaseAndroidLibraryPlugin.kt @@ -18,6 +18,7 @@ package com.google.firebase.gradle.plugins import com.android.build.gradle.LibraryExtension import com.android.build.gradle.LibraryPlugin +import com.android.build.gradle.internal.crash.afterEvaluate import com.google.firebase.gradle.plugins.LibraryType.ANDROID import com.google.firebase.gradle.plugins.ci.device.FirebaseTestServer import com.google.firebase.gradle.plugins.license.LicenseResolverPlugin @@ -36,8 +37,20 @@ import org.gradle.kotlin.dsl.register import org.gradle.kotlin.dsl.withType import org.jetbrains.kotlin.gradle.tasks.KotlinCompile -// TODO() maybe rename to FirebaseAndroidLibraryPlugin; makes more sense alongside java one -class FirebaseLibraryPlugin : BaseFirebaseLibraryPlugin() { +/** + * Plugin for Android Firebase Libraries. + * + * ```kts + * plugins { + * id("firebase-library") + * } + * ``` + * + * @see [FirebaseJavaLibraryPlugin] + * @see [BaseFirebaseLibraryPlugin] + * @see [FirebaseLibraryExtension] + */ +class FirebaseAndroidLibraryPlugin : BaseFirebaseLibraryPlugin() { override fun apply(project: Project) { project.apply() @@ -62,30 +75,35 @@ class FirebaseLibraryPlugin : BaseFirebaseLibraryPlugin() { val firebaseLibrary = project.extensions.create("firebaseLibrary", project, ANDROID) val android = project.extensions.getByType() - android.compileOptions { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 - } - android.buildFeatures.buildConfig = true + with(android) { + compileOptions { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } - // In the case of and android library signing config only affects instrumentation test APK. - // We need it signed with default debug credentials in order for FTL to accept the APK. - android.buildTypes { getByName("release").signingConfig = getByName("debug").signingConfig } + buildFeatures.buildConfig = true - android.defaultConfig { - buildConfigField("String", "VERSION_NAME", "\"" + project.version + "\"") - } + /** + * If a library's signing config only affects the instrumentation test APK, we need it signed + * with default debug credentials for Test Lab to accept it. + */ + buildTypes { named("release") { signingConfig = getByName("debug").signingConfig } } - // see https://github.com/robolectric/robolectric/issues/5456 - android.testOptions.unitTests.all { - it.systemProperty("robolectric.dependency.repo.id", "central") - it.systemProperty("robolectric.dependency.repo.url", "https://repo1.maven.org/maven2") - it.systemProperty("javax.net.ssl.trustStoreType", "JKS") + defaultConfig { buildConfigField("String", "VERSION_NAME", "\"${project.version}\"") } + + // TODO(b/372022757): Remove when we update robolectric + testOptions.unitTests.all { + it.systemProperty("robolectric.dependency.repo.id", "central") + it.systemProperty("robolectric.dependency.repo.url", "https://repo1.maven.org/maven2") + it.systemProperty("javax.net.ssl.trustStoreType", "JKS") + } + + testServer(FirebaseTestServer(project, firebaseLibrary.testLab, android)) } + setupDefaults(project, firebaseLibrary) setupApiInformationAnalysis(project, android) - android.testServer(FirebaseTestServer(project, firebaseLibrary.testLab, android)) setupStaticAnalysis(project, firebaseLibrary) getIsPomValidTask(project, firebaseLibrary) setupVersionCheckTasks(project, firebaseLibrary) @@ -94,10 +112,10 @@ class FirebaseLibraryPlugin : BaseFirebaseLibraryPlugin() { private fun setupVersionCheckTasks(project: Project, firebaseLibrary: FirebaseLibraryExtension) { project.tasks.register("gmavenVersionCheck") { - groupId.value(firebaseLibrary.groupId.get()) - artifactId.value(firebaseLibrary.artifactId.get()) - version.value(firebaseLibrary.version) - latestReleasedVersion.value(firebaseLibrary.latestReleasedVersion.orElseGet { "" }) + groupId.set(firebaseLibrary.groupId) + artifactId.set(firebaseLibrary.artifactId) + version.set(firebaseLibrary.version) + latestReleasedVersion.set(firebaseLibrary.latestReleasedVersion.orElse("")) } project.mkdir("semver") project.mkdir("semver/previous-version") @@ -105,8 +123,8 @@ class FirebaseLibraryPlugin : BaseFirebaseLibraryPlugin() { dependsOn("bundleReleaseAar") project.file("semver/previous.aar").delete() - groupId.value(firebaseLibrary.groupId.get()) - artifactId.value(firebaseLibrary.artifactId.get()) + groupId.value(firebaseLibrary.groupId) + artifactId.value(firebaseLibrary.artifactId) aarAndroidFile.value(true) filePath.value(project.file("semver/previous.aar").absolutePath) } @@ -181,7 +199,13 @@ class FirebaseLibraryPlugin : BaseFirebaseLibraryPlugin() { firebaseLibrary: FirebaseLibraryExtension, android: LibraryExtension, ) { - android.publishing.singleVariant("release") { withSourcesJar() } + android.publishing.singleVariant("release") { + project.afterEvaluate { + if (firebaseLibrary.publishSources.get()) { + withSourcesJar() + } + } + } project.tasks.withType { isEnabled = false } configurePublishing(project, firebaseLibrary) diff --git a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/FirebaseJavaLibraryPlugin.kt b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/FirebaseJavaLibraryPlugin.kt index 0638a300bb3..a3ba6df64a1 100644 --- a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/FirebaseJavaLibraryPlugin.kt +++ b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/FirebaseJavaLibraryPlugin.kt @@ -31,15 +31,29 @@ import org.gradle.kotlin.dsl.register import org.gradle.kotlin.dsl.withType import org.jetbrains.kotlin.gradle.tasks.KotlinCompile +/** + * Plugin for Java Firebase Libraries. + * + * ```kts + * plugins { + * id("firebase-java-library") + * } + * ``` + * + * @see [FirebaseAndroidLibraryPlugin] + * @see [BaseFirebaseLibraryPlugin] + * @see [FirebaseLibraryExtension] + */ class FirebaseJavaLibraryPlugin : BaseFirebaseLibraryPlugin() { override fun apply(project: Project) { project.apply() - project.apply() setupFirebaseLibraryExtension(project) registerMakeReleaseNotesTask(project) + project.apply() + // reduce the likelihood of kotlin module files colliding. project.tasks.withType { kotlinOptions.freeCompilerArgs = ImmutableList.of("-module-name", kotlinModuleName(project)) @@ -50,6 +64,7 @@ class FirebaseJavaLibraryPlugin : BaseFirebaseLibraryPlugin() { val firebaseLibrary = project.extensions.create("firebaseLibrary", project, JAVA) + setupDefaults(project, firebaseLibrary) setupStaticAnalysis(project, firebaseLibrary) setupApiInformationAnalysis(project) getIsPomValidTask(project, firebaseLibrary) @@ -62,7 +77,7 @@ class FirebaseJavaLibraryPlugin : BaseFirebaseLibraryPlugin() { groupId.value(firebaseLibrary.groupId.get()) artifactId.value(firebaseLibrary.artifactId.get()) version.value(firebaseLibrary.version) - latestReleasedVersion.value(firebaseLibrary.latestReleasedVersion.orElseGet { "" }) + latestReleasedVersion.value(firebaseLibrary.latestReleasedVersion.orElse("")) } project.mkdir("semver") project.tasks.register("copyPreviousArtifacts") { diff --git a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/FirebaseLibraryExtension.java b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/FirebaseLibraryExtension.java deleted file mode 100644 index 824160c1497..00000000000 --- a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/FirebaseLibraryExtension.java +++ /dev/null @@ -1,203 +0,0 @@ -// Copyright 2019 Google 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 -// -// http://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 com.google.firebase.gradle.plugins; - -import com.android.build.gradle.LibraryExtension; -import com.google.common.collect.ImmutableSet; -import com.google.firebase.gradle.plugins.ci.device.FirebaseTestLabExtension; -import java.io.File; -import java.util.Collections; -import java.util.Optional; -import java.util.Set; -import javax.inject.Inject; -import org.gradle.api.Action; -import org.gradle.api.Project; -import org.gradle.api.internal.provider.DefaultProvider; -import org.gradle.api.plugins.JavaPluginConvention; -import org.gradle.api.provider.Property; -import org.gradle.api.publish.maven.MavenPom; - -// TODO(b/270576405): rewrite in kotlin, and utilize conventions -public class FirebaseLibraryExtension { - - public final Project project; - public final LibraryType type; - /** Indicates whether the library has public javadoc. */ - public boolean publishJavadoc = true; - - /** Indicates whether sources are published alongside the library. */ - public boolean publishSources; - - /** - * Indicates the library is in a preview mode (alpha, beta, ...), and must publish with a tag - */ - public String previewMode = ""; - - /** Static analysis configuration. */ - public final FirebaseStaticAnalysis staticAnalysis; - - /** Firebase Test Lab configuration/ */ - public final FirebaseTestLabExtension testLab; - - /** Release notes configuration. */ - public final ReleaseNotesConfigurationExtension releaseNotes; - - public Property groupId; - public Property artifactId; - - String libraryGroupName; - - private Action customizePomAction = - pom -> { - pom.licenses( - licenses -> - licenses.license( - license -> { - license.getName().set("The Apache Software License, Version 2.0"); - license.getUrl().set("http://www.apache.org/licenses/LICENSE-2.0.txt"); - })); - pom.scm( - scm -> { - scm.getConnection() - .set("scm:git:https://github.com/firebase/firebase-android-sdk.git"); - scm.getUrl().set("https://github.com/firebase/firebase-android-sdk"); - }); - }; - - @Inject - public FirebaseLibraryExtension(Project project, LibraryType type) { - this.project = project; - this.type = type; - this.testLab = new FirebaseTestLabExtension(project.getObjects()); - this.artifactId = project.getObjects().property(String.class); - this.groupId = project.getObjects().property(String.class); - this.releaseNotes = project.getExtensions().create("releaseNotes", ReleaseNotesConfigurationExtension.class); - this.releaseNotes.getEnabled().convention(true); - this.releaseNotes.getHasKTX().convention(true); - this.releaseNotes.getArtifactName().convention(project.getName()); - - if ("ktx".equals(project.getName()) && project.getParent() != null) { - artifactId.set(new DefaultProvider<>(() -> project.getParent().getName() + "-ktx")); - groupId.set(new DefaultProvider<>(() -> project.getParent().getGroup().toString())); - } else { - artifactId.set(new DefaultProvider<>(project::getName)); - groupId.set(new DefaultProvider<>(() -> project.getGroup().toString())); - } - this.staticAnalysis = initializeStaticAnalysis(project); - libraryGroupName = this.artifactId.get(); - } - - private FirebaseStaticAnalysis initializeStaticAnalysis(Project project) { - return new FirebaseStaticAnalysis( - projectsFromProperty(project, "firebase.checks.lintProjects")); - } - - private Set projectsFromProperty(Project project, String propertyName) { - if (!project.hasProperty(propertyName)) { - return Collections.emptySet(); - } - return ImmutableSet.copyOf(project.property(propertyName).toString().split(",", -1)); - } - - /** Configure Firebase Test Lab. */ - public void testLab(Action action) { - action.execute(testLab); - } - - /** - * Register to be released alongside another Firebase Library project. - * - *

This will force the released version of the current project to match the one it's released - * with. - */ - public void libraryGroup(String libraryGroupName) { - this.libraryGroupName = libraryGroupName; - } - - /** Provides a hook to customize pom generation. */ - public void customizePom(Action action) { - customizePomAction = action; - } - - public void releaseNotes(Action action) { - action.execute(releaseNotes); - } - - public void applyPomCustomization(MavenPom pom) { - if (customizePomAction != null) { - customizePomAction.execute(pom); - } - } - - public void staticAnalysis(Action action) { - action.execute(staticAnalysis); - } - - public String getVersion() { - return project.getVersion().toString(); - } - - public Optional getLatestReleasedVersion() { - if (project.hasProperty("latestReleasedVersion")) { - return Optional.of(project.property("latestReleasedVersion").toString()); - } - return Optional.empty(); - } - - public String getMavenName() { - return groupId.get() + ":" + artifactId.get(); - } - - public String getPath() { - return project.getPath(); - } - - public Set getSrcDirs() { - switch (type) { - case ANDROID: - return project - .getExtensions() - .getByType(LibraryExtension.class) - .getSourceSets() - .getByName("main") - .getJava() - .getSrcDirs(); - case JAVA: - return project - .getConvention() - .getPlugin(JavaPluginConvention.class) - .getSourceSets() - .getByName("main") - .getJava() - .getSrcDirs(); - default: - throw new IllegalStateException("Unsupported project type: " + type); - } - } - - public String getRuntimeClasspath() { - if (type.equals(LibraryType.ANDROID)) { - return "releaseRuntimeClasspath"; - } - return "runtimeClasspath"; - } - - @Override - public String toString() { - return String.format( - "FirebaseLibraryExtension{name=\"%s:%s\", project=\"%s\", type=\"%s\"}", - groupId.get(), artifactId.get(), getPath(), type); - } -} diff --git a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/FirebaseLibraryExtension.kt b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/FirebaseLibraryExtension.kt new file mode 100644 index 00000000000..a4453ff8ab7 --- /dev/null +++ b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/FirebaseLibraryExtension.kt @@ -0,0 +1,266 @@ +// Copyright 2019 Google 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 +// +// http://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 com.google.firebase.gradle.plugins + +import com.google.firebase.gradle.plugins.ci.device.FirebaseTestLabExtension +import javax.inject.Inject +import org.gradle.api.Action +import org.gradle.api.Project +import org.gradle.api.provider.Property +import org.gradle.api.provider.SetProperty +import org.gradle.api.publish.maven.MavenPom +import org.gradle.kotlin.dsl.create + +/** + * Configuration class for Firebase Libraries. + * + * Defines configurable settings for Firebase Library SDKs, which can be configured in their gradle + * files. + * + * ```kts + * plugins { + * id("firebase-library") + * } + * + * firebaseLibrary { + * libraryGroup = "firestore" + * testLab { + * enabled = true + * timeout = '45m' + * } + * releaseNotes { + * name.set("{{firestore}}") + * versionName.set("firestore") + * } + * } + * ``` + * + * @see [FirebaseAndroidLibraryPlugin] + * @see [FirebaseJavaLibraryPlugin] + */ +// TODO(b/372730478): Ensure downstream usage of properties in done is a lazy manner +abstract class FirebaseLibraryExtension +@Inject +constructor(val project: Project, val type: LibraryType) { + /** + * Publish Javadocs/KDocs for this library. + * + * Documentation is generated via the [DackkaPlugin], and can be manually invoked with the task + * `kotlindoc`. + * + * Defaults to `true`. + * + * ```sh + * ./gradlew :firebase-common:kotlindoc + * ``` + * + * @see [FirebaseLibraryExtension] + */ + abstract val publishJavadoc: Property + + /** + * Publish source files for this library. + * + * Publishing sources alongside your standard `jar` or `aar` allows the IDE to offer better + * auto-complete and inline linkage. + * + * If your SDK lives in the public repo, there's no real reason for you to have this disabled. + * + * Defaults to `true`. + * + * @see [FirebaseLibraryExtension] + */ + abstract val publishSources: Property + + /** + * Indicates the library is in a preview mode (such as `alpha` or `beta`). + * + * Setting a [previewMode] will cause a descriptive error to be thrown if you attempt to release + * the library without the [previewMode] provided as a suffix to your version in + * `gradle.properties`. + * + * This can help prevent yourself from accidentally releasing a library before it's ready. + * + * ```kt + * firebaseLibrary { + * previewMode = "alpha" + * } + * ``` + * ```properties + * # gradle.properties + * version=16.0.0-alpha + * ``` + * + * @see [FirebaseLibraryExtension] + */ + abstract val previewMode: Property + + /** + * The group for which this library is published under. + * + * Unless the group of your package is separate from your published group, you don't need to + * configure this. + * + * Defaults to the project's `group`. + * + * ```kt + * firebaseLibrary { + * groupId = "com.google.firebase" + * } + * ``` + * + * @see [FirebaseLibraryExtension] + */ + abstract val groupId: Property + + /** + * The name of the artifact for which this library is published under. + * + * Unless the name of your gradle project is different than the name you publish under, you don't + * need to configure this. + * + * Defaults to the project's `name`. + * + * ```kt + * firebaseLibrary { + * artifactId = "firebase-common" + * } + * ``` + * + * @see [FirebaseLibraryExtension] + */ + abstract val artifactId: Property + + /** + * An internal name to signal that this library is linked with another. + * + * Libraries with the same [libraryGroup] are released together. This also forces all libraries in + * the group to _share_ the same version. + * + * Libraries in the same group are also allowed to _always_ have a project level dependency on one + * another- meaning they won't be changed to pinned dependencies after a release. + * + * ```kt + * firebaseLibrary { + * libraryGroup = "messaging" + * artifactId = "firebase-messaging" + * } + * ``` + * ```kt + * firebaseLibrary { + * libraryGroup = "messaging" + * artifactId = "firebase-messaging-directboot" + * } + * ``` + * + * @see [FirebaseLibraryExtension] + */ + abstract val libraryGroup: Property + + /** + * A collection of projects to bind lint checks from. + * + * Projects specified will be included in the output for related `lintChecks` tasks on this + * library. + * + * Typically only used to enabled `firebase-lint`, but can be used to configure custom linting as + * well. + * + * Defaults to `:tools:lint` + * + * ```kt + * firebaseLibrary { + * androidLintCheckProjects = listOf(":tools:lint") + * } + * ``` + * + * Can also be specified via a gradle property with `firebase.checks.lintProjects`. + * + * ``` + * ./gradlew :firebase-common:build -Pfirebase.checks.lintProjects=":tools:lint,:custom:lint" + * ``` + * + * @see [FirebaseLibraryExtension] + */ + abstract val androidLintCheckProjects: SetProperty + + /** + * Firebase Test Lab configuration. + * + * @see [FirebaseTestLabExtension] + * @see [FirebaseLibraryExtension] + */ + val testLab: FirebaseTestLabExtension = + project.objects.newInstance(FirebaseTestLabExtension::class.java) + + /** + * Configurations for generated release notes. + * + * @see [ReleaseNotesConfigurationExtension] + * @see [FirebaseLibraryExtension] + */ + val releaseNotes: ReleaseNotesConfigurationExtension = + project.extensions.create("releaseNotes") + + /** + * Configurable action to apply when generating a pom file for a release. + * + * @see [customizePom] + * @hide + */ + internal var customizePomAction: Action = Action {} + private set + + /** + * Firebase Test Lab configuration. + * + * @see [FirebaseTestLabExtension] + * @see [FirebaseLibraryExtension] + */ + fun testLab(action: Action) { + action.execute(testLab) + } + + /** + * Apply custom configurations for pom generation. + * + * @see [customizePomAction] + * @see [FirebaseLibraryExtension] + */ + fun customizePom(action: Action) { + customizePomAction = action + } + + /** + * Configurations for generated release notes. + * + * @see [ReleaseNotesConfigurationExtension] + * @see [FirebaseLibraryExtension] + */ + fun releaseNotes(action: Action) { + action.execute(releaseNotes) + } + + val version: String + get() = project.version.toString() + + val path: String = project.path + + val runtimeClasspath: String = + if (type == LibraryType.ANDROID) "releaseRuntimeClasspath" else "runtimeClasspath" + + override fun toString(): String { + return """FirebaseLibraryExtension{name="$mavenName", project="$path", type="$type"}""" + } +} diff --git a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/FirebaseProprietaryLibraryPlugin.kt b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/FirebaseProprietaryLibraryPlugin.kt deleted file mode 100644 index c63eb056d43..00000000000 --- a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/FirebaseProprietaryLibraryPlugin.kt +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2021 Google 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 - * - * http://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 com.google.firebase.gradle.plugins - -import org.gradle.api.Plugin -import org.gradle.api.Project -import org.gradle.kotlin.dsl.apply - -class FirebaseProprietaryLibraryPlugin : Plugin { - override fun apply(project: Project) { - project.apply(plugin = "firebase-library") - - val library = project.extensions.getByType(FirebaseLibraryExtension::class.java) - library.publishSources = false - library.customizePom { - licenses { - license { - name.set("Android Software Development Kit License") - url.set("https://developer.android.com/studio/terms.html") - } - } - } - } -} diff --git a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/GitSubmodulePlugin.kt b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/GitSubmodulePlugin.kt index aec3efbb6c8..54a722fcacb 100644 --- a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/GitSubmodulePlugin.kt +++ b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/GitSubmodulePlugin.kt @@ -40,8 +40,8 @@ interface GitSubmodulePluginExtension { * the future. More importantly though, this provides a way for us to make sure the submodules are * initilized whenever we are building said SDKs- while keeping our system clean and modular. * - * This plugin is automatically applied to all SDKs that utilize [FirebaseLibraryPlugin], and is - * subsequently bound to the `preBuild` task that is apart of all gradle modules. + * This plugin is automatically applied to all SDKs that utilize [FirebaseAndroidLibraryPlugin], and + * is subsequently bound to the `preBuild` task that is apart of all gradle modules. * * The following tasks are registered when this plugin is applied: * - [initializeGitSubmodules][registerInitializeGitSubmodulesTask] diff --git a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/GradleUtils.kt b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/GradleUtils.kt index ca794d66754..9a071df3f69 100644 --- a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/GradleUtils.kt +++ b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/GradleUtils.kt @@ -69,9 +69,9 @@ fun File.childFile(childPath: String) = File("$path/$childPath") * newline character. * * @param terminateWithNewline Whether to terminate the file with a newline character. Defaults to - * `true`. + * `true`. * @param block A function that takes a string as input and returns a new string. This function is - * used to transform the lines of the file before they are rewritten. + * used to transform the lines of the file before they are rewritten. * * ``` * val file = File("my-file.txt") @@ -121,13 +121,12 @@ fun File.listFilesOrEmpty() = listFiles().orEmpty() * @param overwrite Whether to overwrite the file if it already exists. * @param bufferSize The size of the buffer to use for the copy operation. * @return The new file. - * * @see copyTo */ fun File.copyToDirectory( target: File, overwrite: Boolean = false, - bufferSize: Int = DEFAULT_BUFFER_SIZE + bufferSize: Int = DEFAULT_BUFFER_SIZE, ): File = copyTo(target.childFile(name), overwrite, bufferSize) /** diff --git a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/KotlinUtils.kt b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/KotlinUtils.kt index 4dd3382ba81..c261d89d075 100644 --- a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/KotlinUtils.kt +++ b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/KotlinUtils.kt @@ -55,7 +55,7 @@ public fun Sequence.takeAll(): Sequence = take(count()) * ``` * * @throws NoSuchElementException if the [Element] does not have descendant [Element]s with tags - * that match the components of an Artifact string; groupId, artifactId, version. + * that match the components of an Artifact string; groupId, artifactId, version. */ fun Element.toArtifactString() = "${textByTag("groupId")}:${textByTag("artifactId")}:${textByTag("version")}" @@ -77,7 +77,7 @@ fun Element.toArtifactString() = * ``` * * @throws NoSuchElementException if the [Element] does not have descendant [Element]s with tags - * that match the components of an Artifact string; groupId, artifactId, version. + * that match the components of an Artifact string; groupId, artifactId, version. */ fun Element.toMavenName() = "${textByTag("groupId")}:${textByTag("artifactId")}" @@ -145,7 +145,7 @@ fun multiLine(vararg strings: Any?) = strings.joinToString("\n") * * @param input the string to search through * @param startIndex an index to start search with, by default zero. Must be not less than zero and - * not greater than `input.length()` + * not greater than `input.length()` * @throws RuntimeException if a match is not found */ fun Regex.findOrThrow(input: CharSequence, startIndex: Int = 0) = @@ -201,7 +201,7 @@ fun List.separateAt(index: Int) = slice(0 until index) to slice(index..la * * @param regex the [Regex] to use to match against values in this list * @param transform a callback to call with [MathResults][MatchResult] when matches are found. If - * the [transform] returns null, then the value remains unchanged. + * the [transform] returns null, then the value remains unchanged. */ fun List.replaceMatches(regex: Regex, transform: (MatchResult) -> String?) = map { val newValue = regex.find(it)?.let(transform) diff --git a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/LibraryGroups.kt b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/LibraryGroups.kt index c06e7aaf95d..2c030388e5e 100644 --- a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/LibraryGroups.kt +++ b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/LibraryGroups.kt @@ -33,7 +33,7 @@ fun computeLibraryGroups(project: Project): Map, - libraryGroups: Map> + libraryGroups: Map>, ): List = expandWithLibraryGroup(librariesToRelease, libraryGroups) - librariesToRelease /** Returns a list that includes [libraries] and all their library group members. */ fun expandWithLibraryGroup( libraries: List, - libraryGroups: Map> + libraryGroups: Map>, ) = libraries - .flatMap { libraryGroups.getOrDefault(it.libraryGroupName, emptyList()) } + .flatMap { libraryGroups.getOrDefault(it.libraryGroup.get(), emptyList()) } .distinctBy { it.artifactId.get() } val FirebaseLibraryExtension.moduleVersion: ModuleVersion? diff --git a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/MakeReleaseNotesTask.kt b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/MakeReleaseNotesTask.kt index bb03233bb98..bdd5520325c 100644 --- a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/MakeReleaseNotesTask.kt +++ b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/MakeReleaseNotesTask.kt @@ -38,7 +38,7 @@ import org.gradle.work.DisableCachingByDefault * @property releaseNotesFile The output file to write the release notes to * @property skipMissingEntries Continue the build if the release notes are missing entries * @throws StopActionException If metadata does not exist for the given project, or there are no - * changes to release + * changes to release * @see make */ @DisableCachingByDefault @@ -178,7 +178,7 @@ abstract class MakeReleaseNotesTask : DefaultTask() { * - Look for numbers that will be surrounded by either brackets or parentheses * - These numbers might be preceded by `GitHub ` * - These numbers might also be followed by parentheses with `//` followed by some text (a - * link) + * link) * - At the end there might be `{: .external}` * * For example: @@ -211,7 +211,7 @@ abstract class MakeReleaseNotesTask : DefaultTask() { private val LINK_REGEX = Regex( "(?:GitHub )?(?:\\[|\\()#(\\d+)(?:\\]|\\))(?:\\(.+?\\))?(?:\\{: \\.external\\})?", - RegexOption.MULTILINE + RegexOption.MULTILINE, ) } } diff --git a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/Metalava.kt b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/Metalava.kt index e823fd3437f..859451ad67a 100644 --- a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/Metalava.kt +++ b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/Metalava.kt @@ -50,7 +50,7 @@ val Project.docStubs: File? fun Project.runMetalavaWithArgs( arguments: List, ignoreFailure: Boolean = false, - stdOut: OutputStream? = null + stdOut: OutputStream? = null, ) { val allArgs = listOf( @@ -58,7 +58,7 @@ fun Project.runMetalavaWithArgs( "--hide", "HiddenSuperclass", // We allow having a hidden parent class "--hide", - "HiddenAbstractMethod" + "HiddenAbstractMethod", ) + arguments project.javaexec { @@ -95,7 +95,7 @@ abstract class GenerateStubsTask : DefaultTask() { classPath.joinToString(":"), "--include-annotations", "--doc-stubs", - outputDir.absolutePath + outputDir.absolutePath, ) ) } @@ -129,12 +129,12 @@ abstract class GenerateApiTxtTask : DefaultTask() { classPath.joinToString(":"), "--api", apiTxtFile.get().absolutePath, - "--format=v2" + "--format=v2", ) + if (updateBaseline.get()) listOf("--update-baseline") else if (baselineFile.get().exists()) listOf("--baseline", baselineFile.get().absolutePath) else listOf(), - ignoreFailure = true + ignoreFailure = true, ) } } @@ -171,9 +171,9 @@ abstract class ApiInformationTask : DefaultTask() { classPath.joinToString(":"), "--api", outputApiFile.get().absolutePath, - "--format=v2" + "--format=v2", ), - ignoreFailure = true + ignoreFailure = true, ) project.runMetalavaWithArgs( @@ -189,13 +189,13 @@ abstract class ApiInformationTask : DefaultTask() { "--error", "AddedField", "--format=v2", - "--no-color" + "--no-color", ) + if (updateBaseline.get()) listOf("--update-baseline") else if (baselineFile.get().exists()) listOf("--baseline", baselineFile.get().absolutePath) else listOf(), ignoreFailure = true, - stdOut = FileOutputStream(outputFile.get()) + stdOut = FileOutputStream(outputFile.get()), ) } } diff --git a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/ModuleVersion.kt b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/ModuleVersion.kt index 841d6c058c0..ad3c45c59f3 100644 --- a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/ModuleVersion.kt +++ b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/ModuleVersion.kt @@ -25,7 +25,7 @@ enum class VersionType { MAJOR, MINOR, PATCH, - PRE + PRE, } /** @@ -41,7 +41,7 @@ enum class PreReleaseVersionType { ALPHA, BETA, EAP, - RC + RC, } /** @@ -87,7 +87,7 @@ data class PreReleaseVersion(val type: PreReleaseVersionType, val build: Int = 1 * * @param type a case insensitive string of any [PreReleaseVersionType] * @param build a string number; gets automatically converted to double digits, and defaults to - * one if blank + * one if blank * @return a [PreReleaseVersion] created from the string, or null if the string was invalid. */ fun fromStringsOrNull(type: String, build: String): PreReleaseVersion? = @@ -136,7 +136,7 @@ data class ModuleVersion( val major: Int, val minor: Int, val patch: Int, - val pre: PreReleaseVersion? = null + val pre: PreReleaseVersion? = null, ) : Comparable { /** Formatted as `MAJOR.MINOR.PATCH-PRE` */ @@ -150,7 +150,7 @@ data class ModuleVersion( { it.minor }, { it.patch }, { it.pre == null }, // a version with no prerelease version takes precedence - { it.pre } + { it.pre }, ) companion object { @@ -176,7 +176,8 @@ data class ModuleVersion( * ``` */ val VERSION_REGEX = - "(?\\d+)\\.(?\\d+)\\.(?\\d+)(?:\\-\\b)?(?

\\w\\D+)?(?\\B\\d+)?".toRegex()
+      "(?\\d+)\\.(?\\d+)\\.(?\\d+)(?:\\-\\b)?(?
\\w\\D+)?(?\\B\\d+)?"
+        .toRegex()
 
     /**
      * Extrapolates the version variables from a provided [String], and turns them into a
@@ -202,7 +203,7 @@ data class ModuleVersion(
                 major.toInt(),
                 minor.toInt(),
                 patch.toInt(),
-                PreReleaseVersion.fromStringsOrNull(pre, build)
+                PreReleaseVersion.fromStringsOrNull(pre, build),
               )
               .takeUnless { it.pre == null && (pre.isNotEmpty() || build.isNotEmpty()) }
           }
@@ -214,7 +215,7 @@ data class ModuleVersion(
    * Returns a copy of this [ModuleVersion], with the given [VersionType] increased by one.
    *
    * @param version the [VersionType] to increase; defaults to the lowest valid version ([pre] else
-   * [patch]).
+   *   [patch]).
    */
   fun bump(version: VersionType? = null) =
     version
diff --git a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/MoveUnreleasedChangesTask.kt b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/MoveUnreleasedChangesTask.kt
index 85aab91a4c6..39c8b8675a4 100644
--- a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/MoveUnreleasedChangesTask.kt
+++ b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/MoveUnreleasedChangesTask.kt
@@ -33,12 +33,11 @@ import org.gradle.kotlin.dsl.provideDelegate
  * a release, such that the changes that went out in said release are moved into their own section
  * for auditing purposes.
  *
- * @see PostReleasePlugin
- *
  * @property changelogFile A [File] to use as the [Changelog]. Defaults to the `CHANGELOG.md` file
- * at the project's root.
+ *   at the project's root.
  * @property releaseVersion A [ModuleVersion] of what to set the version to. Defaults to the
- * project's current version.
+ *   project's current version.
+ * @see PostReleasePlugin
  */
 abstract class MoveUnreleasedChangesTask : DefaultTask() {
   @get:[Optional InputFile]
@@ -71,8 +70,8 @@ abstract class MoveUnreleasedChangesTask : DefaultTask() {
    *
    * That is, it attaches the release version and creates the KTX content.
    *
-   * @see createEntryForKTX
    * @throws StopActionException if [unreleased] does not have any content
+   * @see createEntryForKTX
    */
   private fun createEntryForRelease(unreleased: ReleaseEntry): ReleaseEntry {
     if (!unreleased.hasContent())
@@ -99,7 +98,7 @@ abstract class MoveUnreleasedChangesTask : DefaultTask() {
       nonEmptyKTXContent
         ?: ReleaseContent(
           KTXTransitiveReleaseText(releaseNotesConfig.artifactName.get()),
-          emptyList()
+          emptyList(),
         )
 
     return ktxContent.takeIf { releaseNotesConfig.hasKTX.get() }
diff --git a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/PomValidator.kt b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/PomValidator.kt
index aa56d88c4c3..dce89b4499d 100644
--- a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/PomValidator.kt
+++ b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/PomValidator.kt
@@ -75,7 +75,7 @@ abstract class PomValidator : DefaultTask() {
   data class DependencyDiff(
     val artifactId: String,
     val oldVersion: ModuleVersion,
-    val currentVersion: ModuleVersion
+    val currentVersion: ModuleVersion,
   )
 
   fun diffWithPomFromURL(url: String): String {
diff --git a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/PostReleasePlugin.kt b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/PostReleasePlugin.kt
index a54d5b40b6b..4b34c9f737f 100644
--- a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/PostReleasePlugin.kt
+++ b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/PostReleasePlugin.kt
@@ -58,9 +58,8 @@ class PostReleasePlugin : Plugin {
    * has released). If this property is present, it should be updated to the related version that
    * went out during the release.
    *
-   * @see VersionBumpTask
-   *
    * @param project the [Project] to register this task to
+   * @see VersionBumpTask
    */
   fun registerVersionBumpTask(project: Project) =
     project.tasks.register("versionBump")
@@ -73,9 +72,8 @@ class PostReleasePlugin : Plugin {
    * moved into a seperate section that specifies the version it went out with, and the `Unreleased`
    * section should be wiped clear for new changes to come; for the next release.
    *
-   * @see MoveUnreleasedChangesTask
-   *
    * @param project the [Project] to register this task to
+   * @see MoveUnreleasedChangesTask
    */
   fun registerMoveUnreleasedChangesTask(project: Project) =
     project.tasks.register("moveUnreleasedChanges") {
@@ -90,9 +88,8 @@ class PostReleasePlugin : Plugin {
    * need to convert these project level dependencies back to pinned dependencies- with the latest
    * released version attached.
    *
-   * @see UpdatePinnedDependenciesTask
-   *
    * @param project the [Project] to register this task to
+   * @see UpdatePinnedDependenciesTask
    */
   fun registerUpdatePinnedDependenciesTask(project: Project) =
     project.tasks.register("updatePinnedDependencies") {
diff --git a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/ProjectUtils.kt b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/ProjectUtils.kt
index 4080530f6a4..cbc724ad6ba 100644
--- a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/ProjectUtils.kt
+++ b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/ProjectUtils.kt
@@ -110,7 +110,7 @@ val Project.isKTXLibary: Boolean
  *
  * @param property the name of the property to look for
  */
-inline fun  Project.provideProperty(property: String) = provider {
+inline fun  Project.provideProperty(property: String): Provider = provider {
   val maybeProperty = findProperty(property)
 
   // using when instead of an if statement so we can expand as needed
diff --git a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/PublishingPlugin.kt b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/PublishingPlugin.kt
index 76144e74d0b..da1c9e2b724 100644
--- a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/PublishingPlugin.kt
+++ b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/PublishingPlugin.kt
@@ -38,7 +38,7 @@ import org.gradle.kotlin.dsl.named
 import org.gradle.kotlin.dsl.register
 
 /**
- * Plugin for providing tasks to release [FirebaseLibrary][FirebaseLibraryPlugin] projects.
+ * Plugin for providing tasks to release [FirebaseLibrary][FirebaseAndroidLibraryPlugin] projects.
  *
  * Projects to release are computed via [computeReleasingLibraries]. A multitude of tasks are then
  * registered at the root project.
@@ -48,18 +48,18 @@ import org.gradle.kotlin.dsl.register
  * - [VALIDATE_POM_TASK][registerValidatePomForReleaseTask]
  * - [VALIDATE_PROJECTS_TO_PUBLISH_TASK][registerValidateProjectsToPublishTask]
  * - [BUILD_MAVEN_ZIP_TASK] -> Creates a zip file of the contents of
- * [PUBLISH_RELEASING_LIBS_TO_BUILD_TASK] [registerPublishReleasingLibrariesToBuildDirTask]
+ *   [PUBLISH_RELEASING_LIBS_TO_BUILD_TASK] [registerPublishReleasingLibrariesToBuildDirTask]
  * - [BUILD_KOTLINDOC_ZIP_TASK] -> Creates a zip file of the contents of
- * [GENERATE_KOTLINDOC_FOR_RELEASE_TASK] [registerGenerateKotlindocForReleaseTask]
+ *   [GENERATE_KOTLINDOC_FOR_RELEASE_TASK] [registerGenerateKotlindocForReleaseTask]
  * - [BUILD_RELEASE_NOTES_ZIP_TASK] -> Creates a zip file of the contents of
- * [PREPARE_RELEASE_NOTES_FOR_DROP][registerPrepareReleaseNotesForDropTask]
+ *   [PREPARE_RELEASE_NOTES_FOR_DROP][registerPrepareReleaseNotesForDropTask]
  * - [FIREBASE_PUBLISH_TASK] -> Runs all the tasks above
  *
  * The following are additional tasks provided- that are either for convenience sake, or are used
  * outside of the standard [FIREBASE_PUBLISH_TASK] workflow (possibly at a later time in the release
  * cycle):
  * - [BUILD_BOM_ZIP_TASK] -> Creates a zip file of the contents of [GENERATE_BOM_TASK]
- * [registerGenerateBomTask]
+ *   [registerGenerateBomTask]
  * - [RELEASE_GENEATOR_TASK][registerGenerateReleaseConfigFilesTask]
  * - [RELEASE_REPORT_GENERATOR_TASK][registerGenerateReleaseReportFilesTask]
  * - [PUBLISH_RELEASING_LIBS_TO_LOCAL_TASK][registerPublishReleasingLibrariesToMavenLocalTask]
@@ -175,7 +175,7 @@ abstract class PublishingPlugin : Plugin {
   }
 
   /**
-   * Figures out the [ReleaseMetadata] for with this release.
+   * Figures out the [ReleaseMetadata] for this release.
    *
    * Metadata can be provided either via the project properties or a [ReleaseConfig] file.
    *
@@ -244,7 +244,7 @@ abstract class PublishingPlugin : Plugin {
     val libraryGroupsToRelease =
       inputProjects
         .flatMap { it.resolveProjectLevelDependencies() + it }
-        .map { it.libraryGroupName }
+        .map { it.libraryGroup.get() }
     val projectsToRelease =
       libraryGroups
         .filterKeys { it in libraryGroupsToRelease }
@@ -298,7 +298,7 @@ abstract class PublishingPlugin : Plugin {
    *
    * A collection of [PomValidator] for each releasing project.
    *
-   * Ensures that pom dependencies are not accidently downgraded.
+   * Ensures that pom dependencies are not accidentally downgraded.
    */
   private fun registerValidatePomForReleaseTask(
     project: Project,
@@ -350,9 +350,9 @@ abstract class PublishingPlugin : Plugin {
           )
         }
         for (releasingLibrary in releasinglibraries) {
-          if (!releasingLibrary.version.contains(releasingLibrary.previewMode)) {
+          if (!releasingLibrary.version.contains(releasingLibrary.previewMode.get())) {
             throw GradleException(
-              "You are releasing a ${releasingLibrary.previewMode} SDK (${releasingLibrary.artifactId.get()}) as ${releasingLibrary.version}!"
+              "You are releasing a ${releasingLibrary.previewMode.get()} SDK (${releasingLibrary.artifactId.get()}) as ${releasingLibrary.version}!"
             )
           }
         }
@@ -608,7 +608,7 @@ abstract class PublishingPlugin : Plugin {
  *
  * @property releasingLibraries A list of libraries that should be released
  * @property name The name of the release (such as `m123`)
- * @see computeReleaseMetadata
+ * @see PublishingPlugin.computeReleaseMetadata
  */
 data class ReleaseMetadata(
   val releasingLibraries: List,
diff --git a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/ReleaseConfig.kt b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/ReleaseConfig.kt
index 844599b6c2e..06e484bbb57 100644
--- a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/ReleaseConfig.kt
+++ b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/ReleaseConfig.kt
@@ -27,12 +27,11 @@ import kotlinx.serialization.json.Json
  *
  * Allows a type safe representation of data generated for an official release.
  *
+ * @property name the name of a release, such as `m130`
+ * @property libraries a list of project paths intending to release
  * @see ReleaseGenerator
  * @see fromFile
  * @see toFile
- *
- * @property name the name of a release, such as `m130`
- * @property libraries a list of project paths intending to release
  */
 @Serializable
 data class ReleaseConfig(val name: String, val libraries: List) {
diff --git a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/ReleaseGenerator.kt b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/ReleaseGenerator.kt
index 0be620e52f7..f908aa873e3 100644
--- a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/ReleaseGenerator.kt
+++ b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/ReleaseGenerator.kt
@@ -18,7 +18,6 @@ package com.google.firebase.gradle.plugins
 
 import java.io.File
 import kotlinx.serialization.Serializable
-import kotlinx.serialization.decodeFromString
 import kotlinx.serialization.encodeToString
 import kotlinx.serialization.json.Json
 import org.eclipse.jgit.api.Git
@@ -43,7 +42,7 @@ import org.gradle.api.tasks.TaskAction
  *
  * @property changesByLibraryName contains libs which have opted into the release, and their changes
  * @property changedLibrariesWithNoChangelog contains libs not opted into the release, despite
- * having changes
+ *   having changes
  */
 @Serializable
 data class ReleaseReport(
@@ -184,8 +183,7 @@ abstract class ReleaseGenerator : DefaultTask() {
       .setListMode(ListBranchCommand.ListMode.REMOTE)
       .call()
       .firstOrNull { it.name == "refs/remotes/origin/releases/$branchName" }
-      ?.objectId
-      ?: throw RuntimeException("Could not find branch named $branchName")
+      ?.objectId ?: throw RuntimeException("Could not find branch named $branchName")
 
   private fun getChangedLibraries(
     repo: Git,
@@ -197,7 +195,7 @@ abstract class ReleaseGenerator : DefaultTask() {
       .filter {
         checkDirChanges(repo, previousReleaseRef, currentReleaseRef, "${getRelativeDir(it)}/")
       }
-      .flatMap { libraryGroups.getOrDefault(it.firebaseLibrary.libraryGroupName, emptyList()) }
+      .flatMap { libraryGroups.getOrDefault(it.firebaseLibrary.libraryGroup.get(), emptyList()) }
       .map { it.path }
       .toSet()
 
@@ -217,7 +215,10 @@ abstract class ReleaseGenerator : DefaultTask() {
         )
       }
       .flatMap {
-        libraryGroups.getOrDefault(it.firebaseLibrary.libraryGroupName, listOf(it.firebaseLibrary))
+        libraryGroups.getOrDefault(
+          it.firebaseLibrary.libraryGroup.get(),
+          listOf(it.firebaseLibrary),
+        )
       }
       .map { it.project }
       .toSet()
diff --git a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/ReleaseNotesConfigurationExtension.kt b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/ReleaseNotesConfigurationExtension.kt
index dc87c094135..f257052b09e 100644
--- a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/ReleaseNotesConfigurationExtension.kt
+++ b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/ReleaseNotesConfigurationExtension.kt
@@ -27,18 +27,13 @@ import org.gradle.api.provider.Property
  * mappings.
  *
  * @property enabled Whether to generate release notes for this library. Defaults to true.
- *
  * @property name The variable name mapping for this library, defined on G3.
- *
  * @property versionName The version name mapping for this library, defined on G3.
- *
  * @property hasKTX The library has a sub module with the suffix '-ktx' that releases alongside this
- * library, and should have the transitive text added to the release notes. Defaults to true. Will
- * likely be removed when we officially drop KTX libraries.
- *
+ *   library, and should have the transitive text added to the release notes. Defaults to true. Will
+ *   likely be removed when we officially drop KTX libraries.
  * @property artifactName The name of the generation artifact. _Only_ required if your project's
- * name is different than your generated artifact name. Defaults to the project name.
- *
+ *   name is different than your generated artifact name. Defaults to the project name.
  * @see MakeReleaseNotesTask
  */
 abstract class ReleaseNotesConfigurationExtension {
diff --git a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/UpdatePinnedDependenciesTask.kt b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/UpdatePinnedDependenciesTask.kt
index db068592c6a..36564d7be78 100644
--- a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/UpdatePinnedDependenciesTask.kt
+++ b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/UpdatePinnedDependenciesTask.kt
@@ -48,9 +48,9 @@ import org.gradle.api.tasks.TaskAction
  * *Assuming that `17.0.1` is the latest version of `firebase-appcheck-interop`*
  *
  * @property buildFile A [File] that should be used as the source to update from. Typically the
- * `build.gradle` or `build.gradle.kts` file for a given project.
+ *   `build.gradle` or `build.gradle.kts` file for a given project.
  * @property outputFile A [File] that should be used to write the new text to. Typically the same as
- * the input file ([buildFile]).
+ *   the input file ([buildFile]).
  * @see PostReleasePlugin
  */
 abstract class UpdatePinnedDependenciesTask : DefaultTask() {
@@ -78,12 +78,12 @@ abstract class UpdatePinnedDependenciesTask : DefaultTask() {
   private fun validateDependenciesHaveChanged(
     dependenciesToChange: List,
     oldContent: List,
-    updatedContent: List
+    updatedContent: List,
   ) {
     if (oldContent == updatedContent)
       throw RuntimeException(
         "Expected the following project level dependencies, but found none: " +
-          "${dependenciesToChange.joinToString("\n") { it.mavenName }}"
+          dependenciesToChange.joinToString("\n") { it.mavenName.get() }
       )
 
     val diff = oldContent.diff(updatedContent)
@@ -101,7 +101,7 @@ abstract class UpdatePinnedDependenciesTask : DefaultTask() {
 
     if (librariesNotChanged.isNotEmpty())
       throw RuntimeException(
-        "The following libraries were not found, but should have been:\n ${librariesNotChanged.joinToString("\n") { it.mavenName }}"
+        "The following libraries were not found, but should have been:\n ${librariesNotChanged.joinToString("\n") { it.mavenName.get() }}"
       )
 
     if (librariesCorrectlyChanged.size > dependenciesToChange.size)
@@ -114,7 +114,7 @@ abstract class UpdatePinnedDependenciesTask : DefaultTask() {
     libraryGroups: Map>
   ) =
     with(project.firebaseLibrary) {
-      projectLevelDependencies - libraryGroups.getOrDefault(libraryGroupName, emptyList())
+      projectLevelDependencies - libraryGroups.getOrDefault(libraryGroup.get(), emptyList())
     }
 
   private val FirebaseLibraryExtension.projectLevelDependencies: List
@@ -122,14 +122,14 @@ abstract class UpdatePinnedDependenciesTask : DefaultTask() {
 
   private fun replaceProjectLevelDependencies(
     buildFileContent: List,
-    libraries: List
+    libraries: List,
   ) =
     buildFileContent.replaceMatches(DEPENDENCY_REGEX) {
       val projectName = it.firstCapturedValue
       val projectToChange = libraries.find { it.path == projectName }
-      val latestVersion = projectToChange?.latestVersion
+      val latestVersion = projectToChange?.latestGMavenVersion
 
-      latestVersion?.let { "\"${projectToChange.mavenName}:$latestVersion\"" }
+      latestVersion?.let { "\"${projectToChange.mavenName.get()}:$latestVersion\"" }
     }
 
   companion object {
diff --git a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/VendorPlugin.kt b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/VendorPlugin.kt
index 0bcd4ab68be..11552396078 100644
--- a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/VendorPlugin.kt
+++ b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/VendorPlugin.kt
@@ -89,7 +89,7 @@ class VendorPlugin : Plugin {
           ScopedArtifact.CLASSES,
           VendorTask::inputJars,
           VendorTask::inputDirs,
-          VendorTask::outputJar
+          VendorTask::outputJar,
         )
     }
   }
@@ -175,7 +175,7 @@ abstract class VendorTask @Inject constructor(private val execOperations: ExecOp
             "process",
             rulesFile.absolutePath,
             inputJar.absolutePath,
-            outputJar.asFile.get().absolutePath
+            outputJar.asFile.get().absolutePath,
           )
         systemProperties = mapOf("verbose" to "true", "misplacedClassStrategy" to "FATAL")
       }
diff --git a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/VersionBumpTask.kt b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/VersionBumpTask.kt
index 34c5539eea6..6b12253d400 100644
--- a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/VersionBumpTask.kt
+++ b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/VersionBumpTask.kt
@@ -33,14 +33,13 @@ import org.gradle.kotlin.dsl.provideDelegate
  * modules to be one patch higher than their currently released counterparts, and update their
  * latest released version.
  *
- * @see PostReleasePlugin
- *
  * @property versionFile A [File] that contains the `version` property. Defaults to the
- * `gradle.properties` file at the project's root.
+ *   `gradle.properties` file at the project's root.
  * @property releasedVersion A [ModuleVersion] of what to bump from. Defaults to the project
- * version.
+ *   version.
  * @property newVersion A [ModuleVersion] of what to set the version to. Defaults to one patch
- * higher than [releasedVersion]
+ *   higher than [releasedVersion]
+ * @see PostReleasePlugin
  */
 abstract class VersionBumpTask : DefaultTask() {
   @get:[Optional InputFile]
diff --git a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/ci/ContinuousIntegrationExtension.java b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/ci/ContinuousIntegrationExtension.java
index b90487ecad1..6c6c617aebe 100644
--- a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/ci/ContinuousIntegrationExtension.java
+++ b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/ci/ContinuousIntegrationExtension.java
@@ -18,11 +18,12 @@
 import java.util.List;
 import java.util.regex.Pattern;
 
+// TODO(b/372719032): Migrate to Kotlin/Conventions
 /** Contains plugin configuration properties. */
 public class ContinuousIntegrationExtension {
 
   /** List of paths that the plugin should ignore when querying the Git commit. */
-  private List ignorePaths = new ArrayList<>();
+  public List ignorePaths = new ArrayList<>();
 
   public List getIgnorePaths() {
     return ignorePaths;
diff --git a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/ci/Coverage.java b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/ci/Coverage.java
index 8a429bb88d6..7da0afe8bdd 100644
--- a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/ci/Coverage.java
+++ b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/ci/Coverage.java
@@ -25,12 +25,13 @@
 import org.gradle.testing.jacoco.plugins.JacocoTaskExtension;
 import org.gradle.testing.jacoco.tasks.JacocoReport;
 
+// TODO(b/372719915): Migrate to Kotlin/Modern gradle plugin
 public final class Coverage {
 
   private Coverage() {}
 
   public static void apply(FirebaseLibraryExtension firebaseLibrary) {
-    Project project = firebaseLibrary.project;
+    Project project = firebaseLibrary.getProject();
     project.apply(ImmutableMap.of("plugin", "jacoco"));
     File reportsDir = new File(project.getBuildDir(), "/reports/jacoco");
     JacocoPluginExtension jacoco = project.getExtensions().getByType(JacocoPluginExtension.class);
@@ -97,12 +98,12 @@ public static void apply(FirebaseLibraryExtension firebaseLibrary) {
                     reports
                         .getHtml()
                         .setDestination(
-                            new File(reportsDir, firebaseLibrary.artifactId.get() + "/html"));
+                            new File(reportsDir, firebaseLibrary.getArtifactId().get() + "/html"));
                     reports.getXml().getRequired().set(true);
                     reports
                         .getXml()
                         .setDestination(
-                            new File(reportsDir, firebaseLibrary.artifactId.get() + ".xml"));
+                            new File(reportsDir, firebaseLibrary.getArtifactId().get() + ".xml"));
                   });
               task.getOutputs().upToDateWhen(t -> false);
             });
diff --git a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/ci/SmokeTestsPlugin.java b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/ci/SmokeTestsPlugin.java
index 3556c1b62b9..d3473c35284 100644
--- a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/ci/SmokeTestsPlugin.java
+++ b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/ci/SmokeTestsPlugin.java
@@ -34,6 +34,7 @@
 import org.json.JSONArray;
 import org.json.JSONObject;
 
+// TODO(b/372719175): Migrate to Kotlin
 /** Builds Firebase libraries for consumption by the smoke tests. */
 public class SmokeTestsPlugin implements Plugin {
   @Override
@@ -58,8 +59,8 @@ public void apply(Project project) {
                       return;
                     }
 
-                    String groupId = firebaseLibrary.groupId.get();
-                    String artifactId = firebaseLibrary.artifactId.get();
+                    String groupId = firebaseLibrary.getGroupId().get();
+                    String artifactId = firebaseLibrary.getArtifactId().get();
                     String artifact =
                         String.format("%s:%s:%s", groupId, artifactId, sub.getVersion());
                     allArtifacts.add(artifact);
diff --git a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/ci/device/FirebaseTestLabExtension.java b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/ci/device/FirebaseTestLabExtension.java
index 6bbe72b18bb..ab76a5831be 100644
--- a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/ci/device/FirebaseTestLabExtension.java
+++ b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/ci/device/FirebaseTestLabExtension.java
@@ -21,10 +21,11 @@
 import org.gradle.api.model.ObjectFactory;
 import org.gradle.api.provider.SetProperty;
 
+// TODO(b/372917264): Migrate to Kotlin/Conventions
 public class FirebaseTestLabExtension {
-  private final SetProperty devices;
-  private String timeout;
-  private boolean enabled;
+  public final SetProperty devices;
+  public String timeout;
+  public boolean enabled;
 
   @Inject
   public FirebaseTestLabExtension(ObjectFactory objectFactory) {
diff --git a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/semver/AccessDescriptor.kt b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/semver/AccessDescriptor.kt
index ccea115da0c..a61591bbe04 100644
--- a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/semver/AccessDescriptor.kt
+++ b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/semver/AccessDescriptor.kt
@@ -61,6 +61,7 @@ class AccessDescriptor(private val access: Int) {
     }
     return outputStringList.joinToString(" ")
   }
+
   /** Returns true if the given access modifier matches the given opcode. */
   fun accessIs(opcode: Int): Boolean = (access and opcode) != 0
 }
diff --git a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/semver/ApiDiffer.kt b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/semver/ApiDiffer.kt
index 6796a55f190..e2fc5f9e3ea 100644
--- a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/semver/ApiDiffer.kt
+++ b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/semver/ApiDiffer.kt
@@ -68,7 +68,7 @@ abstract class ApiDiffer : DefaultTask() {
         apiDeltas.joinToString(
           prefix =
             "Here is a list of all the minor/major version bump changes which are made since the last release.\n",
-          separator = "\n"
+          separator = "\n",
         ) {
           "[${it.versionDelta}] ${it.description}"
         }
@@ -79,7 +79,7 @@ abstract class ApiDiffer : DefaultTask() {
         deltaViolations.joinToString(
           prefix =
             "Here is a list of all the violations which needs to be fixed before we could release.\n",
-          separator = "\n"
+          separator = "\n",
         ) {
           "[${it.versionDelta}] ${it.description}"
         }
diff --git a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/semver/ClassInfo.kt b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/semver/ClassInfo.kt
index c9db9a3fe9e..669fe026b4f 100644
--- a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/semver/ClassInfo.kt
+++ b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/semver/ClassInfo.kt
@@ -55,7 +55,7 @@ class ClassInfo(node: ClassNode, classNodes: Map) {
 
   fun getAllNonStaticMethods(
     node: ClassNode?,
-    classNodes: Map
+    classNodes: Map,
   ): Map {
     if (node == null) {
       return emptyMap()
diff --git a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/semver/DeltaType.kt b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/semver/DeltaType.kt
index ba01169252e..6029403630d 100644
--- a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/semver/DeltaType.kt
+++ b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/semver/DeltaType.kt
@@ -34,7 +34,7 @@ enum class DeltaType {
             "",
             String.format("Class %s removed.", before.name),
             REMOVED_CLASS,
-            VersionDelta.MAJOR
+            VersionDelta.MAJOR,
           )
         )
       }
@@ -61,10 +61,10 @@ enum class DeltaType {
           String.format(
             "Method %s on class %s was removed.",
             getMethodSignature(method),
-            before.name
+            before.name,
           ),
           REMOVED_METHOD,
-          VersionDelta.MAJOR
+          VersionDelta.MAJOR,
         )
       }
     }
@@ -88,7 +88,7 @@ enum class DeltaType {
           field!!.name,
           String.format("Field %s on class %s was removed.", field.name, before.name),
           REMOVED_FIELD,
-          VersionDelta.MAJOR
+          VersionDelta.MAJOR,
         )
       }
     }
@@ -167,7 +167,7 @@ enum class DeltaType {
             "",
             String.format("Class %s has reduced visibility.", after.name),
             REDUCED_VISIBILITY,
-            VersionDelta.MAJOR
+            VersionDelta.MAJOR,
           )
         )
       }
@@ -185,10 +185,10 @@ enum class DeltaType {
               String.format(
                 "Method %s on class %s has reduced its visiblity.",
                 getMethodSignature(method),
-                after.name
+                after.name,
               ),
               REDUCED_VISIBILITY,
-              VersionDelta.MAJOR
+              VersionDelta.MAJOR,
             )
           )
         }
@@ -205,10 +205,10 @@ enum class DeltaType {
               String.format(
                 "Field %s on class %s has reduced its visiblity.",
                 field.name,
-                after.name
+                after.name,
               ),
               REDUCED_VISIBILITY,
-              VersionDelta.MAJOR
+              VersionDelta.MAJOR,
             )
           )
         }
@@ -240,7 +240,7 @@ enum class DeltaType {
           method!!.name,
           String.format("Method %s on class %s became static.", getMethodSignature(method), after),
           CHANGED_TO_STATIC,
-          VersionDelta.MAJOR
+          VersionDelta.MAJOR,
         )
       }
     }
@@ -261,10 +261,10 @@ enum class DeltaType {
               String.format(
                 "Method %s on class %s throws new exceptions.",
                 getMethodSignature(afterMethod),
-                after.name
+                after.name,
               ),
               NEW_EXCEPTIONS,
-              VersionDelta.MINOR
+              VersionDelta.MINOR,
             )
           )
         }
@@ -288,10 +288,10 @@ enum class DeltaType {
               String.format(
                 "Method %s on class %s throws fewer exceptions.",
                 getMethodSignature(afterMethod),
-                after.name
+                after.name,
               ),
               DELETE_EXCEPTIONS,
-              VersionDelta.MAJOR
+              VersionDelta.MAJOR,
             )
           )
         }
@@ -313,7 +313,7 @@ enum class DeltaType {
             "",
             String.format("Class %s made abstract.", after.name),
             CLASS_MADE_ABSTRACT,
-            VersionDelta.MAJOR
+            VersionDelta.MAJOR,
           )
         )
       }
@@ -340,10 +340,10 @@ enum class DeltaType {
               String.format(
                 "Method %s on class %s became abstract.",
                 getMethodSignature(afterMethod),
-                after.name
+                after.name,
               ),
               METHOD_MADE_ABSTRACT,
-              VersionDelta.MAJOR
+              VersionDelta.MAJOR,
             )
           )
         }
@@ -371,10 +371,10 @@ enum class DeltaType {
               String.format(
                 "Method %s on class %s became final.",
                 getMethodSignature(afterMethod),
-                after.name
+                after.name,
               ),
               METHOD_MADE_FINAL,
-              VersionDelta.MAJOR
+              VersionDelta.MAJOR,
             )
           )
         }
@@ -396,7 +396,7 @@ enum class DeltaType {
             "",
             String.format("Class %s made final.", after.name),
             CLASS_MADE_FINAL,
-            VersionDelta.MAJOR
+            VersionDelta.MAJOR,
           )
         )
       }
@@ -415,7 +415,7 @@ enum class DeltaType {
             "",
             String.format("Class %s added.", after.name),
             ADDED_CLASS,
-            VersionDelta.MINOR
+            VersionDelta.MINOR,
           )
         )
       }
@@ -441,7 +441,7 @@ enum class DeltaType {
           method!!.name,
           String.format("Method %s on class %s was added.", getMethodSignature(method), after.name),
           ADDED_METHOD,
-          VersionDelta.MINOR
+          VersionDelta.MINOR,
         )
       }
     }
@@ -466,7 +466,7 @@ enum class DeltaType {
           field!!.name,
           String.format("Field %s on class %s was added.", field.name, after.name),
           ADDED_FIELD,
-          VersionDelta.MINOR
+          VersionDelta.MINOR,
         )
       }
     }
@@ -547,7 +547,7 @@ enum class DeltaType {
             "",
             String.format("Class %s has increased visibility.", after.name),
             INCREASED_VISIBILITY,
-            VersionDelta.MINOR
+            VersionDelta.MINOR,
           )
         )
       }
@@ -563,10 +563,10 @@ enum class DeltaType {
               String.format(
                 "Method %s on class %s has increased its visiblity.",
                 getMethodSignature(method),
-                after.name
+                after.name,
               ),
               INCREASED_VISIBILITY,
-              VersionDelta.MINOR
+              VersionDelta.MINOR,
             )
           )
         }
@@ -582,10 +582,10 @@ enum class DeltaType {
               String.format(
                 "Field %s on class %s has reduced its visiblity.",
                 field.name,
-                after.name
+                after.name,
               ),
               INCREASED_VISIBILITY,
-              VersionDelta.MINOR
+              VersionDelta.MINOR,
             )
           )
         }
@@ -622,7 +622,7 @@ enum class DeltaType {
           method!!.name,
           String.format("Method %s on class %s removed static.", getMethodSignature(method), after),
           CHANGED_FROM_STATIC,
-          VersionDelta.MINOR
+          VersionDelta.MINOR,
         )
       }
     }
@@ -651,7 +651,7 @@ enum class DeltaType {
       AccessDescriptor(methodNode.access).getVerboseDescription(),
       Type.getReturnType(methodNode.desc).className,
       methodNode.name,
-      parameterClasses.joinToString(", ")
+      parameterClasses.joinToString(", "),
     )
   }
 
@@ -672,6 +672,7 @@ enum class DeltaType {
     }
     return false
   }
+
   /** Returns true if the class is local or anonymous. */
   fun isLocalOrAnonymous(classNode: ClassNode): Boolean {
     // JVMS 4.7.7 says a class has an EnclosingMethod attribute iff it is local or anonymous.
@@ -686,6 +687,7 @@ enum class DeltaType {
     val withoutPackage = normalizedPath.substring(normalizedPath.lastIndexOf('/') + 1)
     return withoutPackage.substring(withoutPackage.lastIndexOf('$') + 1)
   }
+
   fun hasNonPublicFieldSignature(fieldNode: FieldNode): Boolean {
     val fieldType = Type.getType(fieldNode.desc)
     return UtilityClass.isObfuscatedSymbol(getUnqualifiedClassname(fieldType.getClassName()))
diff --git a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/semver/GmavenCopier.kt b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/semver/GmavenCopier.kt
index 72beb5302fc..c8bcc7b5fa0 100644
--- a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/semver/GmavenCopier.kt
+++ b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/semver/GmavenCopier.kt
@@ -44,7 +44,7 @@ abstract class GmavenCopier : DefaultTask() {
     val gMavenPath =
       mavenHelper.getArtifactForVersion(
         mavenHelper.getLatestReleasedVersion(),
-        !aarAndroidFile.get()
+        !aarAndroidFile.get(),
       )
     URL(gMavenPath).openStream().use { Files.copy(it, Paths.get(filePath.get())) }
   }
diff --git a/buildSrc/src/test/kotlin/com/google/firebase/gradle/plugins/FirebaseTestController.kt b/buildSrc/src/test/kotlin/com/google/firebase/gradle/plugins/FirebaseTestController.kt
index 00831a17877..16684706909 100644
--- a/buildSrc/src/test/kotlin/com/google/firebase/gradle/plugins/FirebaseTestController.kt
+++ b/buildSrc/src/test/kotlin/com/google/firebase/gradle/plugins/FirebaseTestController.kt
@@ -32,7 +32,7 @@ import org.junit.rules.TemporaryFolder
  * - Link your test projects with the controller via [withProjects]
  * - Use the [GradleRunner] to run your build at the [rootDirectory]
  * - Use any of the provided extension methods to inspect the build files and make assertions in
- * your test
+ *   your test
  *
  * Some example of the provided extension methods are:
  * - [Project.buildFile]
@@ -41,12 +41,11 @@ import org.junit.rules.TemporaryFolder
  * To see a more involved example of this workflow, you can take a look at test classes that
  * implement this class, eg; [UpdatePinnedDependenciesTests] and [PublishingPluginTests].
  *
+ * @property rootDirectory the root [TemporaryFolder] that all files will be created under.
  * @see project
  * @see createReleaseWithConfig
  * @see createReleaseWithProjects
  * @see withProjects
- *
- * @property rootDirectory the root [TemporaryFolder] that all files will be created under.
  */
 class FirebaseTestController(val rootDirectory: TemporaryFolder) {
 
@@ -121,8 +120,7 @@ class FirebaseTestController(val rootDirectory: TemporaryFolder) {
    * they are invoked during the build process.
    *
    * @param projects a variable amount of [Project] to create subdirectories for and include in the
-   * build process.
-   *
+   *   build process.
    * @see include
    */
   fun withProjects(vararg projects: Project) {
@@ -138,7 +136,6 @@ class FirebaseTestController(val rootDirectory: TemporaryFolder) {
    * Creates a `release.json` file at the [rootDirectory].
    *
    * @param release the [ReleaseConfig] to convert into a `json` file.
-   *
    * @see createReleaseWithProjects
    */
   fun createReleaseWithConfig(release: ReleaseConfig) {
@@ -152,7 +149,6 @@ class FirebaseTestController(val rootDirectory: TemporaryFolder) {
    * different name, then pass your own [ReleaseConfig] instead via [createReleaseWithConfig].
    *
    * @param projects a variable amount of [Project] to include in the release file.
-   *
    * @see createReleaseWithConfig
    */
   fun createReleaseWithProjects(vararg projects: Project) {
diff --git a/buildSrc/src/test/kotlin/com/google/firebase/gradle/plugins/LicenseResolverPluginTests.kt b/buildSrc/src/test/kotlin/com/google/firebase/gradle/plugins/LicenseResolverPluginTests.kt
index 8a71a06adad..c03323f6823 100644
--- a/buildSrc/src/test/kotlin/com/google/firebase/gradle/plugins/LicenseResolverPluginTests.kt
+++ b/buildSrc/src/test/kotlin/com/google/firebase/gradle/plugins/LicenseResolverPluginTests.kt
@@ -103,10 +103,10 @@ class LicenseResolverPluginTests {
       .fromJson(
         File(
             "${testProjectDir.root}/build/generated/third_party_licenses/",
-            "third_party_licenses.json"
+            "third_party_licenses.json",
           )
           .readText(),
-        object : TypeToken>() {}.type
+        object : TypeToken>() {}.type,
       )
 
   private fun getLicenseText(): String =
diff --git a/buildSrc/src/test/kotlin/com/google/firebase/gradle/plugins/Memoization.kt b/buildSrc/src/test/kotlin/com/google/firebase/gradle/plugins/Memoization.kt
index 055def99b44..388b728e988 100644
--- a/buildSrc/src/test/kotlin/com/google/firebase/gradle/plugins/Memoization.kt
+++ b/buildSrc/src/test/kotlin/com/google/firebase/gradle/plugins/Memoization.kt
@@ -18,6 +18,7 @@ package com.google.firebase.gradle.plugins
 
 class Memoize1(val f: (T) -> R) : (T) -> R {
   private val values = mutableMapOf()
+
   override fun invoke(x: T): R {
     return values.getOrPut(x, { f(x) })
   }
diff --git a/buildSrc/src/test/kotlin/com/google/firebase/gradle/plugins/PublishingPluginTests.kt b/buildSrc/src/test/kotlin/com/google/firebase/gradle/plugins/PublishingPluginTests.kt
index ee6778f6455..07896f978a6 100644
--- a/buildSrc/src/test/kotlin/com/google/firebase/gradle/plugins/PublishingPluginTests.kt
+++ b/buildSrc/src/test/kotlin/com/google/firebase/gradle/plugins/PublishingPluginTests.kt
@@ -41,13 +41,14 @@ class PublishingPluginTests {
           name = "childProject2",
           version = "0.9",
           projectDependencies = setOf(project1),
-          customizePom = """
+          customizePom =
+            """
   licenses {
     license {
       name = 'Hello'
     }
   }
-  """
+  """,
         )
 
       withProjects(project1, project2)
@@ -58,7 +59,7 @@ class PublishingPluginTests {
         it.license shouldBe
           License(
             "The Apache Software License, Version 2.0",
-            "http://www.apache.org/licenses/LICENSE-2.0.txt"
+            "http://www.apache.org/licenses/LICENSE-2.0.txt",
           )
       }
       project2.pom.let {
@@ -79,13 +80,14 @@ class PublishingPluginTests {
           name = "childProject2",
           version = "0.9",
           projectDependencies = setOf(project1),
-          customizePom = """
+          customizePom =
+            """
   licenses {
     license {
       name = 'Hello'
     }
   }
-  """
+  """,
         )
 
       withProjects(project1, project2)
@@ -96,7 +98,7 @@ class PublishingPluginTests {
         it.license shouldBe
           License(
             "The Apache Software License, Version 2.0",
-            "http://www.apache.org/licenses/LICENSE-2.0.txt"
+            "http://www.apache.org/licenses/LICENSE-2.0.txt",
           )
       }
       project2.pom.let {
@@ -163,7 +165,7 @@ class PublishingPluginTests {
           name = "childProject2",
           projectDependencies = setOf(project1),
           libraryGroup = "test123",
-          expectedVersion = "1.0.0"
+          expectedVersion = "1.0.0",
         )
 
       withProjects(project1, project2)
@@ -190,7 +192,7 @@ class PublishingPluginTests {
           name = "childProject2",
           version = "0.9",
           projectDependencies = setOf(project1),
-          externalDependencies = setOf(dagger, daggerAndroid)
+          externalDependencies = setOf(dagger, daggerAndroid),
         )
 
       withProjects(project1, project2)
@@ -213,13 +215,13 @@ class PublishingPluginTests {
         Project(
           name = "childProject1",
           version = "1.0",
-          externalDependencies = setOf(externalAARLibrary)
+          externalDependencies = setOf(externalAARLibrary),
         )
       val project2 =
         Project(
           name = "childProject2",
           version = "1.0",
-          externalDependencies = setOf(externalAARLibrary.copy(version = "2.22"))
+          externalDependencies = setOf(externalAARLibrary.copy(version = "2.22")),
         )
 
       withProjects(project1, project2)
@@ -239,13 +241,20 @@ class PublishingPluginTests {
       it.task(":checkHeadDependencies")?.outcome shouldBe FAILED
     }
 
+  /**
+   * Creates a [GradleRunner] to run the specified [projects].
+   *
+   * If your tests are failing, you can call [GradleRunner.forwardOutput] to enable stdout/stderr
+   * redirection for further debugging. Since this can be excessively verbose and slow down tests,
+   * this behavior is not enabled by default.
+   */
   private fun makeGradleRunner(vararg projects: Project) =
     GradleRunner.create()
       .withProjectDir(testProjectDir.root)
       .withArguments(
         "-PprojectsToPublish=${projects.joinToString(",") { it.name }}",
         "-PreleaseName=m123",
-        "firebasePublish"
+        "firebasePublish",
       )
       .withPluginClasspath()
 }
diff --git a/buildSrc/src/test/kotlin/com/google/firebase/gradle/plugins/UpdatePinnedDependenciesTests.kt b/buildSrc/src/test/kotlin/com/google/firebase/gradle/plugins/UpdatePinnedDependenciesTests.kt
index aede46ddfcc..7cdc76a8253 100644
--- a/buildSrc/src/test/kotlin/com/google/firebase/gradle/plugins/UpdatePinnedDependenciesTests.kt
+++ b/buildSrc/src/test/kotlin/com/google/firebase/gradle/plugins/UpdatePinnedDependenciesTests.kt
@@ -53,14 +53,14 @@ class UpdatePinnedDependenciesTests : FunSpec() {
           name = "firebase-firestore",
           libraryGroup = "test",
           group = "com.google.firebase",
-          version = "1.0.0"
+          version = "1.0.0",
         )
       val testProject =
         Project(
           name = "testProject",
           libraryGroup = "test",
           version = "1.0.0",
-          projectDependencies = setOf(fakeFirestore)
+          projectDependencies = setOf(fakeFirestore),
         )
 
       withProjects(fakeFirestore, testProject)
@@ -79,14 +79,14 @@ class UpdatePinnedDependenciesTests : FunSpec() {
           name = "firebase-firestore",
           libraryGroup = "test",
           group = "com.google.firebase",
-          version = "1.0.0"
+          version = "1.0.0",
         )
       val testProject =
         Project(
           name = "testProject",
           libraryGroup = "test",
           version = "1.0.0",
-          externalDependencies = setOf(fakeFirestore.toArtifact())
+          externalDependencies = setOf(fakeFirestore.toArtifact()),
         )
 
       withProjects(fakeFirestore, testProject)
diff --git a/buildSrc/src/test/kotlin/com/google/firebase/gradle/plugins/publishing.kt b/buildSrc/src/test/kotlin/com/google/firebase/gradle/plugins/publishing.kt
index 0579712bf10..4dcc06ad635 100644
--- a/buildSrc/src/test/kotlin/com/google/firebase/gradle/plugins/publishing.kt
+++ b/buildSrc/src/test/kotlin/com/google/firebase/gradle/plugins/publishing.kt
@@ -33,9 +33,10 @@ data class Project(
   val libraryGroup: String? = null,
   val customizePom: String? = null,
   val publishJavadoc: Boolean = false,
-  val libraryType: LibraryType = LibraryType.ANDROID
+  val libraryType: LibraryType = LibraryType.ANDROID,
 ) {
   val path = ":$name"
+
   fun generateBuildFile(): String {
     return """
             plugins {
@@ -45,7 +46,7 @@ data class Project(
             version = '$version'
             ${if (latestReleasedVersion != null) "ext.latestReleasedVersion = $latestReleasedVersion" else ""}
             firebaseLibrary {
-                ${if (libraryGroup != null) "libraryGroup '$libraryGroup'" else ""}
+                ${if (libraryGroup != null) "libraryGroup = '$libraryGroup'" else ""}
                 ${if (customizePom != null) "customizePom {$customizePom}" else ""}
                 ${"publishJavadoc = $publishJavadoc"}
             }
@@ -66,7 +67,7 @@ data class License(val name: String, val url: String)
 
 enum class Type {
   JAR,
-  AAR
+  AAR,
 }
 
 data class Artifact(
@@ -74,7 +75,7 @@ data class Artifact(
   val artifactId: String,
   val version: String,
   val type: Type = Type.JAR,
-  val scope: String = "runtime"
+  val scope: String = "runtime",
 ) {
   val simpleDepString = "$groupId:$artifactId:$version"
 
@@ -86,9 +87,9 @@ data class Pom(
   val license: License =
     License(
       name = "The Apache Software License, Version 2.0",
-      url = "http://www.apache.org/licenses/LICENSE-2.0.txt"
+      url = "http://www.apache.org/licenses/LICENSE-2.0.txt",
     ),
-  val dependencies: List = listOf()
+  val dependencies: List = listOf(),
 ) {
   companion object {
     fun parse(file: File): Pom {
@@ -223,7 +224,6 @@ fun Project.toArtifact() = Artifact(group, name, version, libraryType.toArtifact
  * ```
  *
  * @param projectLevel whether the dependency should be a project level dependency or external
- *
  * @see toArtifact
  */
 fun Project.toDependency(projectLevel: Boolean = false) =
diff --git a/firebase-appdistribution-api/firebase-appdistribution-api.gradle b/firebase-appdistribution-api/firebase-appdistribution-api.gradle
index 9505c94fe94..97687554f40 100644
--- a/firebase-appdistribution-api/firebase-appdistribution-api.gradle
+++ b/firebase-appdistribution-api/firebase-appdistribution-api.gradle
@@ -18,7 +18,7 @@ plugins {
 }
 
 firebaseLibrary {
-    libraryGroup "appdistribution"
+    libraryGroup = "appdistribution"
     previewMode = "beta"
     releaseNotes {
         name.set("{{appdistro}} API")
diff --git a/firebase-appdistribution-api/ktx/ktx.gradle b/firebase-appdistribution-api/ktx/ktx.gradle
index 794b7b8b41a..5a49152f6cb 100644
--- a/firebase-appdistribution-api/ktx/ktx.gradle
+++ b/firebase-appdistribution-api/ktx/ktx.gradle
@@ -18,7 +18,7 @@ plugins {
 }
 
 firebaseLibrary {
-    libraryGroup "appdistribution"
+    libraryGroup = "appdistribution"
     testLab.enabled = true
     publishJavadoc = false
     releaseNotes { 
diff --git a/firebase-appdistribution/firebase-appdistribution.gradle b/firebase-appdistribution/firebase-appdistribution.gradle
index ec9776438a3..298eb3db079 100644
--- a/firebase-appdistribution/firebase-appdistribution.gradle
+++ b/firebase-appdistribution/firebase-appdistribution.gradle
@@ -18,7 +18,7 @@ plugins {
 }
 
 firebaseLibrary {
-    libraryGroup "appdistribution"
+    libraryGroup = "appdistribution"
     publishJavadoc = false
     previewMode = "beta"
     releaseNotes {
diff --git a/firebase-common/firebase-common.gradle.kts b/firebase-common/firebase-common.gradle.kts
index 2dd11a4db31..071a56e462a 100644
--- a/firebase-common/firebase-common.gradle.kts
+++ b/firebase-common/firebase-common.gradle.kts
@@ -18,7 +18,7 @@ plugins {
 }
 
 firebaseLibrary {
-  libraryGroup("common")
+  libraryGroup = "common"
   testLab.enabled = true
   publishSources = true
   releaseNotes { enabled = false }
diff --git a/firebase-common/ktx/ktx.gradle.kts b/firebase-common/ktx/ktx.gradle.kts
index 2c07a415162..61553f0adeb 100644
--- a/firebase-common/ktx/ktx.gradle.kts
+++ b/firebase-common/ktx/ktx.gradle.kts
@@ -18,7 +18,7 @@ plugins {
 }
 
 firebaseLibrary {
-  libraryGroup("common")
+  libraryGroup = "common"
   publishJavadoc = false
   releaseNotes { enabled.set(false) }
 }
diff --git a/firebase-config/firebase-config.gradle.kts b/firebase-config/firebase-config.gradle.kts
index c2322d4232c..872c320356d 100644
--- a/firebase-config/firebase-config.gradle.kts
+++ b/firebase-config/firebase-config.gradle.kts
@@ -20,7 +20,7 @@ plugins {
 }
 
 firebaseLibrary {
-  libraryGroup("config")
+  libraryGroup = "config"
   testLab.enabled = true
   publishSources = true
   releaseNotes {
diff --git a/firebase-config/ktx/ktx.gradle b/firebase-config/ktx/ktx.gradle
index dadf3933637..917850a33b6 100644
--- a/firebase-config/ktx/ktx.gradle
+++ b/firebase-config/ktx/ktx.gradle
@@ -18,7 +18,7 @@ plugins {
 }
 
 firebaseLibrary {
-    libraryGroup "config"
+    libraryGroup = "config"
     publishJavadoc = false
     releaseNotes { 
         enabled.set(false)
diff --git a/firebase-crashlytics-ndk/firebase-crashlytics-ndk.gradle b/firebase-crashlytics-ndk/firebase-crashlytics-ndk.gradle
index fa15c5c6c4e..5d3bc636a9b 100644
--- a/firebase-crashlytics-ndk/firebase-crashlytics-ndk.gradle
+++ b/firebase-crashlytics-ndk/firebase-crashlytics-ndk.gradle
@@ -18,7 +18,7 @@ plugins {
 }
 
 firebaseLibrary {
-    libraryGroup "crashlytics"
+    libraryGroup = "crashlytics"
     testLab {
         enabled = true
         device 'model=panther,version=33' // Pixel7
diff --git a/firebase-crashlytics/firebase-crashlytics.gradle b/firebase-crashlytics/firebase-crashlytics.gradle
index 28a23e279ba..be48261c760 100644
--- a/firebase-crashlytics/firebase-crashlytics.gradle
+++ b/firebase-crashlytics/firebase-crashlytics.gradle
@@ -19,7 +19,7 @@ plugins {
 }
 
 firebaseLibrary {
-    libraryGroup "crashlytics"
+    libraryGroup = "crashlytics"
     testLab {
         enabled = true
         device 'model=panther,version=33'
diff --git a/firebase-crashlytics/ktx/ktx.gradle b/firebase-crashlytics/ktx/ktx.gradle
index 3a46e4f3f93..51c6ec6e0f3 100644
--- a/firebase-crashlytics/ktx/ktx.gradle
+++ b/firebase-crashlytics/ktx/ktx.gradle
@@ -18,7 +18,7 @@ plugins {
 }
 
 firebaseLibrary {
-  libraryGroup "crashlytics"
+  libraryGroup = "crashlytics"
   testLab.enabled = true
   publishJavadoc = false
   releaseNotes { 
diff --git a/firebase-database/firebase-database.gradle.kts b/firebase-database/firebase-database.gradle.kts
index eae87a2b8f5..85034e86dc9 100644
--- a/firebase-database/firebase-database.gradle.kts
+++ b/firebase-database/firebase-database.gradle.kts
@@ -19,7 +19,7 @@ plugins {
 }
 
 firebaseLibrary {
-  libraryGroup("database")
+  libraryGroup = "database"
   testLab.enabled = true
   publishSources = true
   releaseNotes {
diff --git a/firebase-database/ktx/ktx.gradle.kts b/firebase-database/ktx/ktx.gradle.kts
index b627d57535b..7b07ab62901 100644
--- a/firebase-database/ktx/ktx.gradle.kts
+++ b/firebase-database/ktx/ktx.gradle.kts
@@ -21,7 +21,7 @@ plugins {
 group = "com.google.firebase"
 
 firebaseLibrary {
-  libraryGroup("database")
+  libraryGroup = "database"
   publishJavadoc = false
   releaseNotes { enabled.set(false) }
   publishSources = true
diff --git a/firebase-dataconnect/firebase-dataconnect.gradle.kts b/firebase-dataconnect/firebase-dataconnect.gradle.kts
index 158a165910c..ecc4570de64 100644
--- a/firebase-dataconnect/firebase-dataconnect.gradle.kts
+++ b/firebase-dataconnect/firebase-dataconnect.gradle.kts
@@ -25,7 +25,7 @@ plugins {
 }
 
 firebaseLibrary {
-  libraryGroup("dataconnect")
+  libraryGroup = "dataconnect"
   testLab.enabled = false
   publishSources = true
   publishJavadoc = false
diff --git a/firebase-dataconnect/google-services.json b/firebase-dataconnect/google-services.json
index 45de107a9c6..162aa66b572 100644
--- a/firebase-dataconnect/google-services.json
+++ b/firebase-dataconnect/google-services.json
@@ -21,4 +21,4 @@
     }
   ],
   "configuration_version": "1"
-}
+}
\ No newline at end of file
diff --git a/firebase-dynamic-links/firebase-dynamic-links.gradle b/firebase-dynamic-links/firebase-dynamic-links.gradle
index 401c0d2d6cc..c20009d33e3 100644
--- a/firebase-dynamic-links/firebase-dynamic-links.gradle
+++ b/firebase-dynamic-links/firebase-dynamic-links.gradle
@@ -18,7 +18,7 @@ plugins {
 }
 
 firebaseLibrary {
-    libraryGroup "dynamic-links"
+    libraryGroup = "dynamic-links"
     testLab.enabled = false
     publishSources = true
     releaseNotes {
diff --git a/firebase-dynamic-links/ktx/ktx.gradle b/firebase-dynamic-links/ktx/ktx.gradle
index d286b9cb6a4..72337abd0cd 100644
--- a/firebase-dynamic-links/ktx/ktx.gradle
+++ b/firebase-dynamic-links/ktx/ktx.gradle
@@ -18,7 +18,7 @@ plugins {
 }
 
 firebaseLibrary {
-    libraryGroup "dynamic-links"
+    libraryGroup = "dynamic-links"
     publishJavadoc = false
     releaseNotes { 
         enabled.set(false)
diff --git a/firebase-firestore/firebase-firestore.gradle b/firebase-firestore/firebase-firestore.gradle
index ef3e339145d..3888894f456 100644
--- a/firebase-firestore/firebase-firestore.gradle
+++ b/firebase-firestore/firebase-firestore.gradle
@@ -20,7 +20,7 @@ plugins {
 }
 
 firebaseLibrary {
-    libraryGroup "firestore"
+    libraryGroup = "firestore"
     publishSources = true
     testLab {
         enabled = true
diff --git a/firebase-firestore/ktx/ktx.gradle b/firebase-firestore/ktx/ktx.gradle
index 7129a16e4ef..bfe56022e50 100644
--- a/firebase-firestore/ktx/ktx.gradle
+++ b/firebase-firestore/ktx/ktx.gradle
@@ -20,7 +20,7 @@ plugins {
 group = "com.google.firebase"
 
 firebaseLibrary {
-    libraryGroup "firestore"
+    libraryGroup = "firestore"
     publishSources = true
     publishJavadoc = false
     releaseNotes { 
diff --git a/firebase-functions/firebase-functions.gradle.kts b/firebase-functions/firebase-functions.gradle.kts
index 8ec30bcc28b..aa283adbfd8 100644
--- a/firebase-functions/firebase-functions.gradle.kts
+++ b/firebase-functions/firebase-functions.gradle.kts
@@ -23,7 +23,7 @@ plugins {
 }
 
 firebaseLibrary {
-  libraryGroup("functions")
+  libraryGroup = "functions"
   testLab.enabled = true
   publishSources = true
   releaseNotes {
diff --git a/firebase-functions/ktx/ktx.gradle.kts b/firebase-functions/ktx/ktx.gradle.kts
index b66fc76a946..9a3f5cff4f3 100644
--- a/firebase-functions/ktx/ktx.gradle.kts
+++ b/firebase-functions/ktx/ktx.gradle.kts
@@ -18,7 +18,7 @@ plugins {
 }
 
 firebaseLibrary {
-  libraryGroup("functions")
+  libraryGroup = "functions"
   publishJavadoc = false
   releaseNotes { enabled.set(false) }
   publishSources = true
diff --git a/firebase-inappmessaging-display/firebase-inappmessaging-display.gradle b/firebase-inappmessaging-display/firebase-inappmessaging-display.gradle
index 5c9ae57e8a5..7f466137ea2 100644
--- a/firebase-inappmessaging-display/firebase-inappmessaging-display.gradle
+++ b/firebase-inappmessaging-display/firebase-inappmessaging-display.gradle
@@ -19,7 +19,7 @@ plugins {
 }
 
 firebaseLibrary {
-    libraryGroup "inappmessaging"
+    libraryGroup = "inappmessaging"
     testLab.enabled = true
     releaseNotes {
         name.set("{{inappmessaging}} Display")
diff --git a/firebase-inappmessaging-display/ktx/ktx.gradle b/firebase-inappmessaging-display/ktx/ktx.gradle
index 12693bbce56..e82774d7b1b 100644
--- a/firebase-inappmessaging-display/ktx/ktx.gradle
+++ b/firebase-inappmessaging-display/ktx/ktx.gradle
@@ -18,7 +18,7 @@ plugins {
 }
 
 firebaseLibrary {
-    libraryGroup "inappmessaging"
+    libraryGroup = "inappmessaging"
     publishJavadoc = false
     releaseNotes { 
         enabled.set(false)
diff --git a/firebase-inappmessaging/firebase-inappmessaging.gradle b/firebase-inappmessaging/firebase-inappmessaging.gradle
index 2516a215ec4..627bcce4829 100644
--- a/firebase-inappmessaging/firebase-inappmessaging.gradle
+++ b/firebase-inappmessaging/firebase-inappmessaging.gradle
@@ -20,7 +20,7 @@ plugins {
 }
 
 firebaseLibrary {
-    libraryGroup "inappmessaging"
+    libraryGroup = "inappmessaging"
     testLab.enabled = true
     releaseNotes {
         name.set("{{inappmessaging}}")
diff --git a/firebase-inappmessaging/ktx/ktx.gradle b/firebase-inappmessaging/ktx/ktx.gradle
index 0d40ad758cf..234d81d5f2b 100644
--- a/firebase-inappmessaging/ktx/ktx.gradle
+++ b/firebase-inappmessaging/ktx/ktx.gradle
@@ -18,7 +18,7 @@ plugins {
 }
 
 firebaseLibrary {
-    libraryGroup "inappmessaging"
+    libraryGroup = "inappmessaging"
     publishJavadoc = false
     releaseNotes { 
         enabled.set(false)
diff --git a/firebase-installations/firebase-installations.gradle b/firebase-installations/firebase-installations.gradle
index 5dee4877a93..b664fc70b22 100644
--- a/firebase-installations/firebase-installations.gradle
+++ b/firebase-installations/firebase-installations.gradle
@@ -19,7 +19,7 @@ plugins {
 }
 
 firebaseLibrary {
-    libraryGroup "installations"
+    libraryGroup = "installations"
     releaseNotes {
         name.set("{{firebase_installations}}")
         versionName.set("installations")
diff --git a/firebase-installations/ktx/ktx.gradle b/firebase-installations/ktx/ktx.gradle
index c9c24d42af6..a11b0254c91 100644
--- a/firebase-installations/ktx/ktx.gradle
+++ b/firebase-installations/ktx/ktx.gradle
@@ -18,7 +18,7 @@ plugins {
 }
 
 firebaseLibrary {
-    libraryGroup "installations"
+    libraryGroup = "installations"
     publishJavadoc = false
     releaseNotes { 
         enabled.set(false)
diff --git a/firebase-messaging-directboot/firebase-messaging-directboot.gradle b/firebase-messaging-directboot/firebase-messaging-directboot.gradle
index ab1e92c6dd7..1c028fc34b9 100644
--- a/firebase-messaging-directboot/firebase-messaging-directboot.gradle
+++ b/firebase-messaging-directboot/firebase-messaging-directboot.gradle
@@ -19,7 +19,7 @@ plugins {
 firebaseLibrary {
     testLab.enabled = false
     publishJavadoc = false
-    libraryGroup "messaging"
+    libraryGroup = "messaging"
     releaseNotes {
         name.set("Cloud Messaging Direct Boot")
         versionName.set("messaging-directboot")
diff --git a/firebase-messaging/firebase-messaging.gradle b/firebase-messaging/firebase-messaging.gradle
index 349ff0f5bbd..79f65f7e995 100644
--- a/firebase-messaging/firebase-messaging.gradle
+++ b/firebase-messaging/firebase-messaging.gradle
@@ -53,7 +53,7 @@ protobuf {
 
 
 firebaseLibrary {
-    libraryGroup "messaging"
+    libraryGroup = "messaging"
     testLab.enabled = false
     releaseNotes {
         name.set("{{messaging_longer}}")
diff --git a/firebase-messaging/ktx/ktx.gradle b/firebase-messaging/ktx/ktx.gradle
index 8b506e8483f..71c6e4fbb60 100644
--- a/firebase-messaging/ktx/ktx.gradle
+++ b/firebase-messaging/ktx/ktx.gradle
@@ -18,7 +18,7 @@ plugins {
 }
 
 firebaseLibrary {
-    libraryGroup "messaging"
+    libraryGroup = "messaging"
     publishJavadoc = false
     releaseNotes { 
         enabled.set(false)
diff --git a/firebase-ml-modeldownloader/firebase-ml-modeldownloader.gradle b/firebase-ml-modeldownloader/firebase-ml-modeldownloader.gradle
index b026a004dc8..2a7451f0893 100644
--- a/firebase-ml-modeldownloader/firebase-ml-modeldownloader.gradle
+++ b/firebase-ml-modeldownloader/firebase-ml-modeldownloader.gradle
@@ -21,7 +21,7 @@ plugins {
 }
 
 firebaseLibrary {
-    libraryGroup "ml-modeldownloader"
+    libraryGroup = "ml-modeldownloader"
     testLab.enabled = true
     publishJavadoc = true
     releaseNotes {
diff --git a/firebase-ml-modeldownloader/ktx/ktx.gradle b/firebase-ml-modeldownloader/ktx/ktx.gradle
index 845a23a446f..1fa236cad92 100644
--- a/firebase-ml-modeldownloader/ktx/ktx.gradle
+++ b/firebase-ml-modeldownloader/ktx/ktx.gradle
@@ -18,7 +18,7 @@ plugins {
 }
 
 firebaseLibrary {
-    libraryGroup "ml-modeldownloader"
+    libraryGroup = "ml-modeldownloader"
     publishJavadoc = false
     releaseNotes { 
         enabled.set(false)
diff --git a/firebase-perf/firebase-perf.gradle b/firebase-perf/firebase-perf.gradle
index c359a2d2041..ed92d34d4a1 100644
--- a/firebase-perf/firebase-perf.gradle
+++ b/firebase-perf/firebase-perf.gradle
@@ -22,7 +22,7 @@ plugins {
 }
 
 firebaseLibrary {
-    libraryGroup "perf"
+    libraryGroup = "perf"
     publishJavadoc = true
     // Disabling Test Lab as there are no instrumentation tests for the SDK currently.
     // When we add instrumentation tests in the future, this needs to be enabled.
diff --git a/firebase-perf/ktx/ktx.gradle b/firebase-perf/ktx/ktx.gradle
index 5c4985bf147..446ad5cbfe7 100644
--- a/firebase-perf/ktx/ktx.gradle
+++ b/firebase-perf/ktx/ktx.gradle
@@ -18,7 +18,7 @@ plugins {
 }
 
 firebaseLibrary {
-    libraryGroup "perf"
+    libraryGroup = "perf"
     publishJavadoc = false
     releaseNotes { 
         enabled.set(false)
diff --git a/firebase-sessions/firebase-sessions.gradle.kts b/firebase-sessions/firebase-sessions.gradle.kts
index 7455bd68fb6..f14def02101 100644
--- a/firebase-sessions/firebase-sessions.gradle.kts
+++ b/firebase-sessions/firebase-sessions.gradle.kts
@@ -23,7 +23,7 @@ plugins {
 }
 
 firebaseLibrary {
-  libraryGroup("crashlytics")
+  libraryGroup = "crashlytics"
 
   testLab.enabled = true
   publishSources = true
diff --git a/firebase-storage/firebase-storage.gradle b/firebase-storage/firebase-storage.gradle
index ed69bea26d3..b0e9eef4c86 100644
--- a/firebase-storage/firebase-storage.gradle
+++ b/firebase-storage/firebase-storage.gradle
@@ -20,7 +20,7 @@ plugins {
 }
 
 firebaseLibrary {
-    libraryGroup "storage"
+    libraryGroup = "storage"
     testLab.enabled = true
     publishJavadoc = true
     publishSources = true
diff --git a/firebase-storage/ktx/ktx.gradle b/firebase-storage/ktx/ktx.gradle
index bf6cda8adea..c61083c95b9 100644
--- a/firebase-storage/ktx/ktx.gradle
+++ b/firebase-storage/ktx/ktx.gradle
@@ -20,7 +20,7 @@ plugins {
 group = "com.google.firebase"
 
 firebaseLibrary {
-    libraryGroup "storage"
+    libraryGroup = "storage"
     publishJavadoc = false
     releaseNotes { 
         enabled.set(false)
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index cf078e2c9ed..1a263ab12c8 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -20,7 +20,7 @@ protobufjavautil = "3.25.5"
 kotest = "5.9.0" # Do not use 5.9.1 because it reverts the fix for https://github.com/kotest/kotest/issues/3981
 quickcheck = "0.6"
 serialization = "1.5.1"
-spotless = "7.0.0.BETA1"
+spotless = "7.0.0.BETA3"
 androidx-test-core="1.5.0"
 androidx-test-junit="1.1.5"
 androidx-test-truth = "1.5.0"
diff --git a/transport/transport-backend-cct/transport-backend-cct.gradle b/transport/transport-backend-cct/transport-backend-cct.gradle
index eb5d54ab073..2baae70620d 100644
--- a/transport/transport-backend-cct/transport-backend-cct.gradle
+++ b/transport/transport-backend-cct/transport-backend-cct.gradle
@@ -18,7 +18,7 @@ plugins {
 }
 
 firebaseLibrary{
-    libraryGroup("transport")
+    libraryGroup = "transport"
     publishJavadoc = false
     releaseNotes { 
         enabled.set(false)
diff --git a/transport/transport-runtime/transport-runtime.gradle b/transport/transport-runtime/transport-runtime.gradle
index cf8e223a611..eeb18a0513d 100644
--- a/transport/transport-runtime/transport-runtime.gradle
+++ b/transport/transport-runtime/transport-runtime.gradle
@@ -50,7 +50,7 @@ protobuf {
 }
 
 firebaseLibrary {
-    libraryGroup("transport")
+    libraryGroup = "transport"
     publishJavadoc = false
     releaseNotes { 
         enabled.set(false)