diff --git a/.github/workflows/build-release-artifacts.yml b/.github/workflows/build-release-artifacts.yml
index 049f1acdd50..2c0e050e947 100644
--- a/.github/workflows/build-release-artifacts.yml
+++ b/.github/workflows/build-release-artifacts.yml
@@ -24,7 +24,7 @@ jobs:
- name: Perform gradle build
run: |
- ./gradlew firebasePublish -PpublishConfigFilePath=release.cfg -PpublishMode=RELEASE
+ ./gradlew firebasePublish
- name: Generate release notes
run: |
diff --git a/.github/workflows/check-head-dependencies.yml b/.github/workflows/check-head-dependencies.yml
index d451b78d4ce..9dac59365df 100644
--- a/.github/workflows/check-head-dependencies.yml
+++ b/.github/workflows/check-head-dependencies.yml
@@ -14,4 +14,4 @@ jobs:
- name: Perform gradle build
run: |
- ./gradlew checkHeadDependencies -PpublishConfigFilePath=release.cfg -PpublishMode=RELEASE
+ ./gradlew checkHeadDependencies
diff --git a/.github/workflows/create_releases.yml b/.github/workflows/create_releases.yml
index 48ca77079e0..0f37c425066 100644
--- a/.github/workflows/create_releases.yml
+++ b/.github/workflows/create_releases.yml
@@ -39,7 +39,7 @@ jobs:
with:
base: 'releases/${{ inputs.name }}'
branch: 'releases/${{ inputs.name }}.release'
- add-paths: release.cfg,release_report.md
+ add-paths: release.json,release_report.md
title: '${{ inputs.name}} release'
body: 'Auto-generated PR for release ${{ inputs.name}}'
commit-message: 'Create release config for ${{ inputs.name }}'
diff --git a/.github/workflows/semver-check.yml b/.github/workflows/semver-check.yml
index c2729df2106..aad6bff759d 100644
--- a/.github/workflows/semver-check.yml
+++ b/.github/workflows/semver-check.yml
@@ -14,4 +14,4 @@ jobs:
- name: Perform gradle build
run: |
- ./gradlew semverCheckForRelease -PpublishConfigFilePath=release.cfg -PpublishMode=RELEASE
+ ./gradlew semverCheckForRelease
diff --git a/.github/workflows/validate-dependencies.yml b/.github/workflows/validate-dependencies.yml
index 73bacb1d08b..5c7a19643b0 100644
--- a/.github/workflows/validate-dependencies.yml
+++ b/.github/workflows/validate-dependencies.yml
@@ -14,4 +14,4 @@ jobs:
- name: Perform gradle build
run: |
- ./gradlew validatePomForRelease -PpublishConfigFilePath=release.cfg -PpublishMode=RELEASE
+ ./gradlew validatePomForRelease
diff --git a/build.gradle b/build.gradle
index e3fe0c5a3fc..2ce0dc4d7a7 100644
--- a/build.gradle
+++ b/build.gradle
@@ -12,9 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import com.google.firebase.gradle.plugins.license.LicenseResolverPlugin
-import com.google.firebase.gradle.MultiProjectReleasePlugin
-
buildscript {
// TODO: remove once all sdks have migrated to version catalog
ext.kotlinVersion = libs.versions.kotlin.get()
@@ -58,11 +55,10 @@ ext {
protobufJavaUtilVersion = libs.versions.protobufjavautil.get()
}
-apply plugin: com.google.firebase.gradle.plugins.publish.PublishingPlugin
apply plugin: com.google.firebase.gradle.plugins.ci.ContinuousIntegrationPlugin
apply plugin: com.google.firebase.gradle.plugins.ci.SmokeTestsPlugin
-apply plugin: MultiProjectReleasePlugin
+apply plugin: com.google.firebase.gradle.plugins.PublishingPlugin
firebaseContinuousIntegration {
ignorePaths = [
diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts
index 73d6169bd6f..4348d604566 100644
--- a/buildSrc/build.gradle.kts
+++ b/buildSrc/build.gradle.kts
@@ -15,6 +15,7 @@
plugins {
id("com.ncorti.ktfmt.gradle") version "0.11.0"
id("com.github.sherter.google-java-format") version "0.9"
+ kotlin("plugin.serialization") version "1.7.10"
`kotlin-dsl`
}
@@ -67,6 +68,7 @@ dependencies {
implementation("org.eclipse.jgit:org.eclipse.jgit:6.3.0.202209071007-r")
+ implementation(libs.kotlinx.serialization.json)
implementation("com.google.code.gson:gson:2.8.9")
implementation("com.android.tools.build:gradle:7.2.2")
implementation("com.android.tools.build:builder-test-api:7.2.2")
@@ -90,7 +92,7 @@ gradlePlugin {
}
register("publishingPlugin") {
id = "PublishingPlugin"
- implementationClass = "com.google.firebase.gradle.plugins.publish.PublishingPlugin"
+ implementationClass = "com.google.firebase.gradle.plugins.PublishingPlugin"
}
register("firebaseLibraryPlugin") {
id = "firebase-library"
diff --git a/buildSrc/src/main/java/com/google/firebase/gradle/MultiProjectReleasePlugin.java b/buildSrc/src/main/java/com/google/firebase/gradle/MultiProjectReleasePlugin.java
deleted file mode 100644
index f8bb4fc2f52..00000000000
--- a/buildSrc/src/main/java/com/google/firebase/gradle/MultiProjectReleasePlugin.java
+++ /dev/null
@@ -1,128 +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;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.firebase.gradle.bomgenerator.BomGeneratorTask;
-import com.google.firebase.gradle.plugins.FirebaseLibraryExtension;
-import com.google.firebase.gradle.plugins.publish.PublishingPlugin;
-import java.util.Set;
-import java.util.stream.Collectors;
-import org.gradle.api.GradleException;
-import org.gradle.api.Plugin;
-import org.gradle.api.Project;
-import org.gradle.api.Task;
-import org.gradle.api.tasks.Copy;
-import org.gradle.api.tasks.TaskProvider;
-import org.gradle.api.tasks.bundling.Zip;
-
-/**
- * Orchestrates the release process by automating validations, documentation and prebuilts
- * generation.
- *
- *
- * - Pre-release validations:
- *
- * - Build maven artifacts.
- *
- * - Documentation:
- *
- * - Generates javadoc for all SDKs being released.
- *
- * - Artifact generation:
- *
- * - Releases artifacts into a maven repo in build/m2repository.
- *
- Bundles all artifacts into a distributable .zip file.
- *
- *
- */
-public class MultiProjectReleasePlugin implements Plugin {
-
- // TODO() - Will be removed once migrated to Kotlin
- private static String findStringProperty(Project p, String property) {
- Object value = p.findProperty(property);
- return value != null ? value.toString() : null;
- }
-
- @Override
- public void apply(Project project) {
- project.apply(ImmutableMap.of("plugin", PublishingPlugin.class));
-
- project
- .getTasks()
- .create(
- "buildBomZip",
- Zip.class,
- task -> {
- task.dependsOn(project.getTasks().create("generateBom", BomGeneratorTask.class));
- task.from("bom");
- task.getArchiveFileName().set("bom.zip");
- task.getDestinationDirectory().set(project.getRootDir());
- });
-
- TaskProvider generatorTask =
- project
- .getTasks()
- .register(
- "makeReleaseConfigFiles",
- ReleaseGenerator.class,
- task -> {
- task.getCurrentRelease()
- .convention(findStringProperty(project, "currentRelease"));
- task.getPastRelease().convention(findStringProperty(project, "pastRelease"));
- task.getPrintReleaseConfig()
- .convention(findStringProperty(project, "printOutput"));
- task.getReleaseConfigFile()
- .convention(project.getLayout().getBuildDirectory().file("release.cfg"));
- task.getReleaseReportFile()
- .convention(
- project.getLayout().getBuildDirectory().file("release_report.md"));
- });
-
- project
- .getTasks()
- .register(
- "generateReleaseConfig",
- Copy.class,
- task -> {
- task.from(generatorTask);
- task.into(project.getRootDir());
- });
-
- project
- .getGradle()
- .projectsEvaluated(
- gradle -> {
- Set librariesToPublish =
- (Set)
- project.getExtensions().getExtraProperties().get("projectsToPublish");
-
- Set projectsToPublish =
- librariesToPublish.stream().map(lib -> lib.project).collect(Collectors.toSet());
-
- Task validateProjectsToPublish =
- project.task(
- "validateProjectsToPublish",
- task ->
- task.doLast(
- t -> {
- if (projectsToPublish.isEmpty()) {
- throw new GradleException(
- "Required projectsToPublish parameter missing.");
- }
- }));
- project.getTasks().findByName("firebasePublish").dependsOn(validateProjectsToPublish);
- });
- }
-}
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 edbbb1e2b34..fa2fd8ec691 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
@@ -20,43 +20,45 @@ import org.gradle.api.provider.ListProperty
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.TaskAction
+/**
+ * Validates that all project level dependencies are in the release.
+ *
+ * Any releasing library that has a project level dependency on another library invokes the release
+ * of said dependent libary. This is checked via the [artifactId]
+ * [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
+ */
abstract class CheckHeadDependencies : DefaultTask() {
@get:Input abstract val projectsToPublish: ListProperty
- @get:Input abstract val allFirebaseProjects: ListProperty
-
@TaskAction
fun run() {
- val projectsReleasing: Set = projectsToPublish.get().map { it.artifactId.get() }.toSet()
+ val projectsReleasing = computeProjectsReleasing()
+
val errors =
projectsToPublish
.get()
- .associate {
- it.artifactId.get() to
- it
- .projectDependenciesByName()
- .intersect(allFirebaseProjects.get())
- .subtract(projectsReleasing)
- .subtract(DEPENDENCIES_TO_IGNORE)
- }
+ .associate { it.artifactId.get() to it.projectLevelDepsAsArtifactIds() - projectsReleasing }
.filterValues { it.isNotEmpty() }
.map { "${it.key} requires: ${it.value.joinToString(", ") }" }
if (errors.isNotEmpty()) {
throw GradleException(
- "Project-level dependency errors found. Please update the release config.\n${
- errors.joinToString(
- "\n"
- )
- }"
+ "Project-level dependency errors found. Please update the release config.\n" +
+ "${errors.joinToString("\n")}"
)
}
}
- private fun FirebaseLibraryExtension.projectDependenciesByName() =
+ private fun FirebaseLibraryExtension.projectLevelDepsAsArtifactIds() =
resolveProjectLevelDependencies().map { it.artifactId.get() }
+ private fun computeProjectsReleasing() =
+ projectsToPublish.get().map { it.artifactId.get() } + DEPENDENCIES_TO_IGNORE
+
companion object {
- val DEPENDENCIES_TO_IGNORE: List = listOf("protolite-well-known-types")
+ val DEPENDENCIES_TO_IGNORE = listOf("protolite-well-known-types")
}
}
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 49602dd1618..a48b993ec81 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
@@ -134,6 +134,8 @@ abstract class DackkaPlugin : Plugin {
kotlinDoc.configure {
dependsOn(generateDocumentation, firesiteTransform, copyDocsToCommonDirectory)
+
+ outputs.dir(copyDocsToCommonDirectory.map { it.destinationDir })
}
}
}
diff --git a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/GmavenHelper.kt b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/GmavenHelper.kt
index 64e23ca898f..2f2618cb898 100644
--- a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/GmavenHelper.kt
+++ b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/GmavenHelper.kt
@@ -20,6 +20,7 @@ import javax.xml.parsers.DocumentBuilder
import javax.xml.parsers.DocumentBuilderFactory
import org.w3c.dom.Document
+/** TODO(b/279466888) - Make GmavenHelper testable */
class GmavenHelper(val groupId: String, val artifactId: String) {
val GMAVEN_ROOT = "https://dl.google.com/dl/android/maven2"
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 11333b75b76..1d96054999f 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
@@ -15,6 +15,7 @@
package com.google.firebase.gradle.plugins
import java.io.File
+import org.gradle.api.DefaultTask
import org.gradle.api.Project
import org.gradle.api.artifacts.Dependency
import org.gradle.api.attributes.Attribute
@@ -24,6 +25,7 @@ import org.gradle.kotlin.dsl.apply
import org.gradle.workers.WorkAction
import org.gradle.workers.WorkParameters
import org.gradle.workers.WorkQueue
+import org.jetbrains.kotlin.gradle.utils.provider
/**
* Creates a file at the buildDir for the given [Project].
@@ -45,6 +47,25 @@ fun Project.fileFromBuildDir(path: String) = file("$buildDir/$path")
*/
fun Provider.childFile(path: String) = map { File("${it.path}/$path") }
+/**
+ * Returns a new [File] under the given sub directory.
+ *
+ * Syntax sugar for:
+ * ```
+ * File("$path/$childPath")
+ * ```
+ */
+fun File.childFile(childPath: String) = File("$path/$childPath")
+
+/**
+ * Provides a temporary file for use during the task.
+ *
+ * Creates a file under the [temporaryDir][DefaultTask.getTemporaryDir] of the task, and should be
+ * preferred to defining an explicit [File]. This will allow Gradle to make better optimizations on
+ * our part, and helps us avoid edge-case scenarios like conflicting file names.
+ */
+fun DefaultTask.tempFile(path: String) = provider { temporaryDir.childFile(path) }
+
/**
* Returns a list of children files, or an empty list if this [File] doesn't exist or doesn't have
* any children.
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 5b695df4a31..cad62080bf7 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
@@ -18,6 +18,7 @@ import org.gradle.api.Task
import org.gradle.api.artifacts.Configuration
import org.gradle.api.file.FileCollection
import org.gradle.api.provider.Provider
+import org.gradle.kotlin.dsl.findByType
import org.gradle.kotlin.dsl.getByType
/** Checks if the project has any of the common Android specific plugins. */
@@ -74,6 +75,17 @@ val Project.dackkaConfig: Configuration
val Project.firebaseLibrary: FirebaseLibraryExtension
get() = extensions.getByType()
+/**
+ * The [FirebaseLibraryExtension] for this [Project], or null if not found.
+ *
+ * Syntax sugar for:
+ * ```kotlin
+ * extensions.findByType()
+ * ```
+ */
+val Project.firebaseLibraryOrNull: FirebaseLibraryExtension?
+ get() = extensions.findByType()
+
/**
* Hacky-check to see if the module is a ktx variant.
*
@@ -84,6 +96,21 @@ val Project.firebaseLibrary: FirebaseLibraryExtension
val Project.isKTXLibary: Boolean
get() = firebaseLibrary.artifactId.get().endsWith("-ktx")
+/**
+ * Provides a project property as the specified type, or null otherwise.
+ *
+ * Utilizing a safe cast, an attempt is made to cast the project property (if found) to the receiver
+ * type. Should this cast fail, the resulting value will be null.
+ *
+ * Keep in mind that is provided lazily via a [Provider], so evalutation does not occur until the
+ * value is needed.
+ *
+ * @param property the name of the property to look for
+ */
+inline fun Project.provideProperty(property: String) = provider {
+ findProperty(property) as? T
+}
+
/** Fetches the jars of dependencies associated with this configuration through an artifact view. */
val Configuration.jars: FileCollection
get() =
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
new file mode 100644
index 00000000000..7299c7e7487
--- /dev/null
+++ b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/PublishingPlugin.kt
@@ -0,0 +1,399 @@
+// Copyright 2023 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.bomgenerator.BomGeneratorTask
+import com.google.firebase.gradle.plugins.PublishingPlugin.Companion.BUILD_BOM_ZIP_TASK
+import com.google.firebase.gradle.plugins.PublishingPlugin.Companion.BUILD_KOTLINDOC_ZIP_TASK
+import com.google.firebase.gradle.plugins.PublishingPlugin.Companion.BUILD_MAVEN_ZIP_TASK
+import com.google.firebase.gradle.plugins.PublishingPlugin.Companion.FIREBASE_PUBLISH_TASK
+import com.google.firebase.gradle.plugins.PublishingPlugin.Companion.GENERATE_BOM_TASK
+import com.google.firebase.gradle.plugins.PublishingPlugin.Companion.GENERATE_KOTLINDOC_FOR_RELEASE_TASK
+import com.google.firebase.gradle.plugins.PublishingPlugin.Companion.PUBLISH_RELEASING_LIBS_TO_BUILD_TASK
+import com.google.firebase.gradle.plugins.semver.ApiDiffer
+import org.gradle.api.GradleException
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+import org.gradle.api.publish.maven.tasks.PublishToMavenRepository
+import org.gradle.api.tasks.bundling.Zip
+import org.gradle.kotlin.dsl.named
+import org.gradle.kotlin.dsl.register
+
+/**
+ * Plugin for providing tasks to release [FirebaseLibrary][FirebaseLibraryPlugin] projects.
+ *
+ * Projects to release are computed via [computeReleasingLibraries]. A multitude of tasks are then
+ * registered at the root project.
+ *
+ * The following pertain specifically to a release:
+ * - [CHECK_HEAD_DEPS_TASK][registerCheckHeadDependenciesTask]
+ * - [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]
+ * - [BUILD_KOTLINDOC_ZIP_TASK] -> Creates a zip file of the contents of
+ * [GENERATE_KOTLINDOC_FOR_RELEASE_TASK] [registerGenerateKotlindocForReleaseTask]
+ * - [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]
+ * - [RELEASE_GENEATOR_TASK][registerGenerateReleaseConfigFilesTask]
+ * - [PUBLISH_RELEASING_LIBS_TO_LOCAL_TASK][registerPublishReleasingLibrariesToMavenLocalTask]
+ * - [SEMVER_CHECK_TASK][registerSemverCheckForReleaseTask]
+ * - [PUBLISH_ALL_TO_BUILD_TASK][registerPublishAllToBuildDir]
+ */
+abstract class PublishingPlugin : Plugin {
+ override fun apply(project: Project) {
+ project.gradle.projectsEvaluated {
+ val allFirebaseLibraries = project.subprojects.mapNotNull { it.firebaseLibraryOrNull }
+ val releasingFirebaseLibraries = computeReleasingLibraries(project, allFirebaseLibraries)
+ val releasingProjects = releasingFirebaseLibraries.map { it.project }
+
+ val generateBom = registerGenerateBomTask(project)
+ val validatePomForRelease = registerValidatePomForReleaseTask(project, releasingProjects)
+ val checkHeadDependencies =
+ registerCheckHeadDependenciesTask(project, releasingFirebaseLibraries)
+ val validateProjectsToPublish =
+ registerValidateProjectsToPublishTask(project, releasingProjects)
+ val publishReleasingLibrariesToBuildDir =
+ registerPublishReleasingLibrariesToBuildDirTask(project, releasingProjects)
+ val generateKotlindocsForRelease =
+ registerGenerateKotlindocForReleaseTask(project, releasingFirebaseLibraries)
+
+ registerGenerateReleaseConfigFilesTask(project)
+ registerPublishReleasingLibrariesToMavenLocalTask(project, releasingProjects)
+ registerSemverCheckForReleaseTask(project, releasingProjects)
+ registerPublishAllToBuildDir(project, allFirebaseLibraries)
+
+ val buildMavenZip =
+ project.tasks.register(BUILD_MAVEN_ZIP_TASK) {
+ from(publishReleasingLibrariesToBuildDir)
+ archiveFileName.set("m2repository.zip")
+ destinationDirectory.set(project.layout.buildDirectory)
+ }
+
+ val buildKotlindocZip =
+ project.tasks.register(BUILD_KOTLINDOC_ZIP_TASK) {
+ from(generateKotlindocsForRelease)
+ archiveFileName.set("kotlindoc.zip")
+ destinationDirectory.set(project.layout.buildDirectory)
+ }
+
+ project.tasks.register(BUILD_BOM_ZIP_TASK) {
+ from(generateBom)
+ archiveFileName.set("bom.zip")
+ destinationDirectory.set(project.layout.projectDirectory)
+ }
+
+ project.tasks.register(FIREBASE_PUBLISH_TASK) {
+ dependsOn(
+ validateProjectsToPublish,
+ checkHeadDependencies,
+ // validatePomForRelease, TODO(b/279466888) - Make GmavenHelper testable
+ buildMavenZip,
+ buildKotlindocZip
+ )
+
+ doLast {
+ logger.lifecycle(
+ "Publishing the following libraries:\n{}",
+ releasingProjects.map { it.path }.joinToString("\n")
+ )
+ }
+ }
+ }
+ }
+
+ /**
+ * Figures out what libraries are intended to release.
+ *
+ * Libraries can be provided either via the `projectsToPublish` property, or a [ReleaseConfig]
+ * file.
+ *
+ * The `projectsToPublish` property takes priority over the [ReleaseConfig]. It expects a comma
+ * separated list of the publishing project(s) `artifactId`. It also takes into account
+ * [librariesToRelease][FirebaseLibraryExtension.getLibrariesToRelease] -> so there's no need to
+ * specify multiple of the same co-releasing libs.
+ *
+ * The [ReleaseConfig] is a pre-defined set of data for a release. It expects a valid [file]
+ * [ReleaseConfig.fromFile], which provides a list of libraries via their [path]
+ * [FirebaseLibraryExtension.getPath]. Additionally, it does __NOT__ take into account
+ * co-releasing libraries-> meaning libraries that should be releasing alongside one another will
+ * need to be individually specified in the [ReleaseConfig], otherwise it will likely cause an
+ * error during the release process.
+ *
+ * Example usage of `projectsToPublish`:
+ * ```
+ * ./gradlew firebasePublish -PprojectsToPublish="firebase-firestore,firebase-common"
+ * ```
+ *
+ * See [ReleaseConfig.toFile] for example usage of [ReleaseConfig].
+ *
+ * If both `projectsToPublish` and [ReleaseConfig] are empty, or do not exist- this method will
+ * return an empty list.
+ */
+ private fun computeReleasingLibraries(
+ project: Project,
+ allFirebaseLibraries: List
+ ): List {
+ val releasingLibrariesFromProperty = releasingLibsFromProperty(project)
+ if (releasingLibrariesFromProperty != null) {
+ return allFirebaseLibraries
+ .filter { it.artifactId.get() in releasingLibrariesFromProperty }
+ .flatMap { it.librariesToRelease }
+ .distinctBy { it.artifactId.get() }
+ }
+
+ val releasingLibrariesFromReleseConfig = releasingLibsFromReleaseConfig(project)
+ if (releasingLibrariesFromReleseConfig != null) {
+ return allFirebaseLibraries.filter { it.path in releasingLibrariesFromReleseConfig }
+ }
+
+ return emptyList()
+ }
+
+ private fun releasingLibsFromProperty(project: Project) =
+ project.provideProperty("projectsToPublish").orNull?.split(",")
+
+ private fun releasingLibsFromReleaseConfig(project: Project) =
+ project.layout.projectDirectory
+ .file(RELEASE_CONFIG_FILE)
+ .asFile
+ .takeIf { it.exists() }
+ ?.let { ReleaseConfig.fromFile(it).libraries }
+
+ /**
+ * Registers the [GENERATE_BOM_TASK] task.
+ *
+ * Generates a BOM for a release, although it relies on gmaven to be updated- so it should be
+ * invoked manually later on in the release process.
+ *
+ * @see BomGeneratorTask
+ */
+ private fun registerGenerateBomTask(project: Project) =
+ project.tasks.register(GENERATE_BOM_TASK)
+
+ /**
+ * Registers the [VALIDATE_POM_TASK] task.
+ *
+ * A collection of [PomValidator] for each releasing project.
+ *
+ * Ensures that pom dependencies are not accidently downgraded.
+ */
+ private fun registerValidatePomForReleaseTask(
+ project: Project,
+ releasingProjects: List
+ ) =
+ project.tasks.register(VALIDATE_POM_TASK) {
+ for (releasingProject in releasingProjects) {
+ val pomValidatorTask = releasingProject.tasks.named("isPomDependencyValid")
+
+ dependsOn(pomValidatorTask)
+ }
+ }
+
+ /**
+ * Registers the [CHECK_HEAD_DEPS_TASK] task.
+ *
+ * Ensures that project level dependencies are included in the release.
+ *
+ * @see [CheckHeadDependencies]
+ */
+ private fun registerCheckHeadDependenciesTask(
+ project: Project,
+ releasingLibraries: List
+ ) =
+ project.tasks.register(CHECK_HEAD_DEPS_TASK) {
+ projectsToPublish.set(releasingLibraries)
+ }
+
+ /**
+ * Registers the [VALIDATE_PROJECTS_TO_PUBLISH_TASK] task.
+ *
+ * Ensures that there are releasing projects provided, to avoid potential false positive
+ * edge-cases.
+ *
+ * @throws GradleException if no releasing projects are found.
+ */
+ private fun registerValidateProjectsToPublishTask(
+ project: Project,
+ releasingProjects: List
+ ) =
+ project.tasks.register(VALIDATE_PROJECTS_TO_PUBLISH_TASK) {
+ if (releasingProjects.isEmpty()) {
+ throw GradleException(
+ "No projects to release. " +
+ "Ensure you've specified the projectsToPublish parameter, " +
+ "or have a valid $RELEASE_CONFIG_FILE file at the root directory."
+ )
+ }
+ }
+
+ /**
+ * Registers the [PUBLISH_RELEASING_LIBS_TO_BUILD_TASK] task.
+ *
+ * A collection of [publishMavenAarPublicationToBuildDirRepository][PublishToMavenRepository] for
+ * each releasing project.
+ *
+ * The artifacts are provided in a repository under the [buildDir][Project.getBuildDir] of the
+ * provided [project].
+ *
+ * This task outputs the final repository directory.
+ */
+ private fun registerPublishReleasingLibrariesToBuildDirTask(
+ project: Project,
+ releasingProjects: List
+ ) =
+ project.tasks.register(PUBLISH_RELEASING_LIBS_TO_BUILD_TASK) {
+ for (releasingProject in releasingProjects) {
+ val publishTask =
+ releasingProject.tasks.named(
+ "publishMavenAarPublicationToBuildDirRepository"
+ )
+
+ dependsOn(publishTask)
+ outputs.file(publishTask.map { it.repository.url })
+ }
+ }
+
+ /**
+ * Registers the [GENERATE_KOTLINDOC_FOR_RELEASE_TASK] task.
+ *
+ * A collection of [kotlindoc][DackkaPlugin] for each releasing library.
+ *
+ * Outputs a directory containing all the documentation generated for releasing projects.
+ */
+ private fun registerGenerateKotlindocForReleaseTask(
+ project: Project,
+ releasingLibraries: List
+ ) =
+ project.tasks.register(GENERATE_KOTLINDOC_FOR_RELEASE_TASK) {
+ for (releasingLibrary in releasingLibraries) {
+ val kotlindocTask = releasingLibrary.project.tasks.named("kotlindoc")
+
+ dependsOn(kotlindocTask)
+
+ if (releasingLibrary.publishJavadoc) {
+ outputs.dir(kotlindocTask.map { it.outputs.files }).optional()
+ }
+ }
+ }
+
+ /**
+ * Registers the [RELEASE_GENEATOR_TASK] task.
+ *
+ * Creates a config file that keeps track of what libraries are releasing. To learn more about the
+ * file's format see [ReleaseConfig].
+ *
+ * @see [ReleaseGenerator]
+ */
+ private fun registerGenerateReleaseConfigFilesTask(project: Project) =
+ project.tasks.register(RELEASE_GENEATOR_TASK) {
+ currentRelease.convention(project.provideProperty("currentRelease"))
+ pastRelease.convention(project.provideProperty("pastRelease"))
+ printReleaseConfig.convention(project.provideProperty("printOutput"))
+
+ releaseConfigFile.convention(project.layout.projectDirectory.file(RELEASE_CONFIG_FILE))
+ releaseReportFile.convention(project.layout.buildDirectory.file(RELEASE_REPORT_FILE))
+ }
+
+ /**
+ * Registers the [PUBLISH_RELEASING_LIBS_TO_LOCAL_TASK] task.
+ *
+ * A collection of [publishMavenAarPublicationToMavenLocal][PublishToMavenRepository] for each
+ * releasing project.
+ *
+ * Allows users to do local testing of releasing libraries, pulling the artifacts via the maven
+ * local repository.
+ */
+ private fun registerPublishReleasingLibrariesToMavenLocalTask(
+ project: Project,
+ releasingProjects: List
+ ) =
+ project.tasks.register(PUBLISH_RELEASING_LIBS_TO_LOCAL_TASK) {
+ for (releasingProject in releasingProjects) {
+ val publishTask = releasingProject.tasks.named("publishMavenAarPublicationToMavenLocal")
+
+ dependsOn(publishTask)
+ }
+ }
+
+ /**
+ * Registers the [SEMVER_CHECK_TASK] task.
+ *
+ * A collection of [ApiDiffer] for each releasing project.
+ *
+ * Ensures that the version of a releasing project aligns with the API. That is, if the API shows
+ * signs of a major or minor bump- the version is bumped as expected.
+ */
+ private fun registerSemverCheckForReleaseTask(
+ project: Project,
+ releasingProjects: List
+ ) =
+ project.tasks.register(SEMVER_CHECK_TASK) {
+ for (releasingProject in releasingProjects) {
+ val semverCheckTask = releasingProject.tasks.named("semverCheck")
+
+ dependsOn(semverCheckTask)
+ }
+ }
+
+ /**
+ * Registers the [PUBLISH_ALL_TO_BUILD_TASK] task.
+ *
+ * A collection of [publishMavenAarPublicationToBuildDirRepository][PublishToMavenRepository] for
+ * __ALL__ firebase library projects.
+ *
+ * The artifacts are provided in a repository under the [buildDir][Project.getBuildDir] of the
+ * provided [project].
+ */
+ private fun registerPublishAllToBuildDir(
+ project: Project,
+ allFirebaseLibraries: List
+ ) =
+ project.tasks.register(PUBLISH_ALL_TO_BUILD_TASK) {
+ for (firebaseLibrary in allFirebaseLibraries) {
+ val publishTask =
+ firebaseLibrary.project.tasks.named("publishMavenAarPublicationToBuildDirRepository")
+
+ dependsOn(publishTask)
+ }
+ }
+
+ companion object {
+ const val RELEASE_CONFIG_FILE = "release.json"
+ const val RELEASE_REPORT_FILE = "release_report.md"
+
+ const val GENERATE_BOM_TASK = "generateBom"
+ const val VALIDATE_PROJECTS_TO_PUBLISH_TASK = "validateProjectsToPublish"
+ const val SEMVER_CHECK_TASK = "semverCheckForRelease"
+ const val RELEASE_GENEATOR_TASK = "generateReleaseConfig"
+ const val VALIDATE_POM_TASK = "validatePomForRelease"
+ const val PUBLISH_RELEASING_LIBS_TO_BUILD_TASK = "publishReleasingLibrariesToBuildDir"
+ const val PUBLISH_RELEASING_LIBS_TO_LOCAL_TASK = "publishReleasingLibrariesToMavenLocal"
+ const val GENERATE_KOTLINDOC_FOR_RELEASE_TASK = "generateKotlindocForRelease"
+ const val CHECK_HEAD_DEPS_TASK = "checkHeadDependencies"
+ const val BUILD_MAVEN_ZIP_TASK = "buildMavenZip"
+ const val BUILD_KOTLINDOC_ZIP_TASK = "buildKotlindocZip"
+ const val BUILD_BOM_ZIP_TASK = "buildBomZip"
+ const val FIREBASE_PUBLISH_TASK = "firebasePublish"
+ const val PUBLISH_ALL_TO_BUILD_TASK = "publishAllToBuildDir"
+
+ const val BUILD_DIR_REPOSITORY_DIR = "m2repository"
+ }
+}
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
new file mode 100644
index 00000000000..e452b2398c6
--- /dev/null
+++ b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/ReleaseConfig.kt
@@ -0,0 +1,69 @@
+// Copyright 2023 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 java.io.File
+import kotlinx.serialization.Serializable
+import kotlinx.serialization.decodeFromString
+import kotlinx.serialization.encodeToString
+import kotlinx.serialization.json.Json
+
+/**
+ * Container for providing data about a release.
+ *
+ * Allows a type safe representation of data generated for an official 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) {
+
+ /**
+ * Writes a [ReleaseConfig] into a [File] as JSON.
+ *
+ * An example of the output can be seen below:
+ * ```
+ * {
+ * "name": "m130",
+ * "libraries": [
+ * ":firebase-appdistribution",
+ * ":firebase-config",
+ * ]
+ * }
+ * ```
+ *
+ * @see fromFile
+ */
+ fun toFile(file: File) = file.also { it.writeText(formatter.encodeToString(this)) }
+
+ companion object {
+ val formatter = Json { prettyPrint = true }
+
+ /**
+ * Parses a [ReleaseConfig] from the contents of a given [File].
+ *
+ * Allows one to reuse an already generated [ReleaseConfig] that was saved to disc.
+ *
+ * @param file the [File] to parse
+ * @see toFile
+ */
+ fun fromFile(file: File): ReleaseConfig = formatter.decodeFromString(file.readText())
+ }
+}
diff --git a/buildSrc/src/main/java/com/google/firebase/gradle/ReleaseGenerator.kt b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/ReleaseGenerator.kt
similarity index 83%
rename from buildSrc/src/main/java/com/google/firebase/gradle/ReleaseGenerator.kt
rename to buildSrc/src/main/java/com/google/firebase/gradle/plugins/ReleaseGenerator.kt
index 36c9e6bb885..7834c0bff5f 100644
--- a/buildSrc/src/main/java/com/google/firebase/gradle/ReleaseGenerator.kt
+++ b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/ReleaseGenerator.kt
@@ -11,10 +11,9 @@
// 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
+package com.google.firebase.gradle.plugins
import com.google.common.collect.ImmutableList
-import com.google.firebase.gradle.plugins.FirebaseLibraryExtension
import java.io.File
import org.eclipse.jgit.api.Git
import org.eclipse.jgit.api.ListBranchCommand
@@ -27,12 +26,11 @@ import org.gradle.api.Project
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.provider.Property
import org.gradle.api.tasks.Input
+import org.gradle.api.tasks.Optional
import org.gradle.api.tasks.OutputFile
import org.gradle.api.tasks.TaskAction
import org.gradle.kotlin.dsl.findByType
-data class FirebaseLibrary(val moduleNames: List, val directories: List)
-
data class CommitDiff(
val commitId: String,
val author: String,
@@ -57,7 +55,7 @@ abstract class ReleaseGenerator : DefaultTask() {
@get:Input abstract val pastRelease: Property
- @get:Input abstract val printReleaseConfig: Property
+ @get:Optional @get:Input abstract val printReleaseConfig: Property
@get:OutputFile abstract val releaseConfigFile: RegularFileProperty
@@ -79,12 +77,12 @@ abstract class ReleaseGenerator : DefaultTask() {
libsToRelease.map { it.path }.toSet()
val changes = getChangesForLibraries(repo, branchRef, headRef, libsToRelease)
- writeReleaseConfig(
- releaseConfigFile.get().asFile,
- ReleaseConfig(currentRelease.get(), libsToRelease.map { it.path }.toSet())
- )
+
+ val releaseConfig = ReleaseConfig(currentRelease.get(), libsToRelease.map { it.path })
+ releaseConfig.toFile(releaseConfigFile.get().asFile)
+
val releaseReport = generateReleaseReport(changes, changedLibsWithNoChangelog)
- if (printReleaseConfig.get().toBoolean()) {
+ if (printReleaseConfig.orNull.toBoolean()) {
project.logger.info(releaseReport)
}
writeReleaseReport(releaseReportFile.get().asFile, releaseReport)
@@ -202,30 +200,5 @@ abstract class ReleaseGenerator : DefaultTask() {
private fun writeReleaseReport(file: File, report: String) = file.writeText(report)
- private fun writeReleaseConfig(file: File, config: ReleaseConfig) =
- file.writeText(config.toFile())
-
private fun getRelativeDir(project: Project) = project.path.substring(1).replace(':', '/')
}
-
-data class ReleaseConfig(val releaseName: String, val libs: Set) {
- companion object {
- fun fromFile(file: File): ReleaseConfig {
- val contents = file.readLines()
- val libs = contents.filter { it.startsWith(":") }.toSet()
- val releaseName = contents.first { it.startsWith("name") }.substringAfter("=").trim()
- return ReleaseConfig(releaseName, libs)
- }
- }
-
- fun toFile() =
- """
- |[release]
- |name = $releaseName
- |mode = RELEASE
-
- |[modules]
- |${libs.sorted().joinToString("\n")}
- """
- .trimMargin()
-}
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 7855c987504..3556c1b62b9 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
@@ -15,6 +15,7 @@
package com.google.firebase.gradle.plugins.ci;
import com.google.firebase.gradle.plugins.FirebaseLibraryExtension;
+import com.google.firebase.gradle.plugins.PublishingPlugin;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
@@ -69,8 +70,7 @@ public void apply(Project project) {
});
// Reuse the publish task for building the libraries.
- Task publishAllTask = project.getTasks().getByPath("publishAllToBuildDir");
- assembleAllTask.dependsOn(publishAllTask);
+ assembleAllTask.dependsOn(PublishingPlugin.PUBLISH_ALL_TO_BUILD_TASK);
// Generate a JSON file listing the artifacts after everything is complete.
assembleAllTask.doLast(
diff --git a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/publish/PublishingPlugin.java b/buildSrc/src/main/java/com/google/firebase/gradle/plugins/publish/PublishingPlugin.java
deleted file mode 100644
index 2cc038bfd20..00000000000
--- a/buildSrc/src/main/java/com/google/firebase/gradle/plugins/publish/PublishingPlugin.java
+++ /dev/null
@@ -1,270 +0,0 @@
-// Copyright 2020 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.publish;
-
-import com.google.firebase.gradle.plugins.CheckHeadDependencies;
-import com.google.firebase.gradle.plugins.FirebaseLibraryExtension;
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.List;
-import java.util.Set;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-import org.gradle.api.Plugin;
-import org.gradle.api.Project;
-import org.gradle.api.Task;
-import org.gradle.api.tasks.bundling.Zip;
-
-/**
- * Enables releasing of the SDKs.
- *
- * The plugin supports multiple workflows.
- *
- *
Build all SDK snapshots
- *
- *
- * ./gradlew publishAllToLocal # publishes to maven local repo
- * ./gradlew publishAllToBuildDir # publishes to build/m2repository
- *
- *
- * Prepare a release
- *
- *
- * ./gradlew -PpublishConfigFilePath=release.cfg
- * -PpublishMode=(RELEASE|SNAPSHOT) \
- * firebasePublish
- *
- *
- *
- * ./gradlew -PprojectsToPublish="firebase-inappmessaging,firebase-inappmessaging-display"\
- * -PpublishMode=(RELEASE|SNAPSHOT) \
- * firebasePublish
- *
- *
- *
- * - {@code publishConfigFilePath} is the path to the configuration file from which to read the
- * list of projects to release. The file format should be consistent with Python's
- * configparser, and the list of projects should be in a section called "modules". If both
- * this, and {@code projectsToPublish} are specified, this property takes precedence.
- *
- * Example config file content:
- *
- * [release]
- * name = M126
- * ...
- * [modules]
- * firebase-database
- * firebase-common
- * firebase-firestore
- *
- * - {@code projectsToPublish} is a list of projects to release separated by {@code
- * projectsToPublishSeparator}(default: ","), these projects will have their versions depend
- * on the {@code publishMode} parameter.
- *
- {@code publishMode} can one of two values: {@code SNAPSHOT} results in version to be {@code
- * "${project.version}-SNAPSHOT"}. {@code RELEASE} results in versions to be whatever is
- * specified in the SDKs gradle.properties. Additionally when {@code RELEASE} is specified,
- * the release validates the pom to make sure no SDKs point to unreleased SDKs.
- *
- {@code projectsToPublishSeparator}: separates project names in the {@code
- * projectsToPublish} parameter. Default is: ",".
- *
The artifacts will be built to build/m2repository.zip
- *
Prepare release(to maven local)
- *
Same as above but publishes artifacts to maven local.
- *
- * ./gradlew -PprojectsToPublish="firebase-inappmessaging,firebase-inappmessaging-display"\
- * -PpublishMode=(RELEASE|SNAPSHOT) \
- * publishProjectsToMavenLocal
- *
- */
-public class PublishingPlugin implements Plugin {
-
- public PublishingPlugin() {}
-
- private static String getPropertyOr(Project p, String property, String defaultValue) {
- Object value = p.findProperty(property);
- if (value != null) {
- return value.toString();
- }
- return defaultValue;
- }
-
- private static String getPublishTask(FirebaseLibraryExtension p, String repoName) {
- return p.getPath() + ":publishMavenAarPublicationTo" + repoName;
- }
-
- @Override
- public void apply(Project project) {
- String projectNamesToPublish = getPropertyOr(project, "projectsToPublish", "");
- String projectsToPublishSeparator = getPropertyOr(project, "projectsToPublishSeparator", ",");
- String publishConfigFilePath = getPropertyOr(project, "publishConfigFilePath", "");
-
- Task publishAllToLocal = project.task("publishAllToLocal");
- Task publishAllToBuildDir = project.task("publishAllToBuildDir");
- Task firebasePublish = project.task("firebasePublish");
-
- project
- .getGradle()
- .projectsEvaluated(
- gradle -> {
- List projectsNames;
- if (!publishConfigFilePath.isEmpty()) {
- projectsNames = readReleaseConfigFile(publishConfigFilePath);
- } else {
- projectsNames =
- List.of(projectNamesToPublish.split(projectsToPublishSeparator, -1));
- }
-
- Set allFirebaseProjects =
- project.getSubprojects().stream()
- .map(sub -> sub.getExtensions().findByType(FirebaseLibraryExtension.class))
- .filter(ext -> ext != null)
- .map(ext -> ext.artifactId.get())
- .collect(Collectors.toSet());
-
- Set projectsToPublish =
- projectsNames.stream()
- .filter(name -> !name.isEmpty())
- .map(
- name ->
- project
- .project(name)
- .getExtensions()
- .findByType(FirebaseLibraryExtension.class))
- .filter(ext -> ext != null)
- .flatMap(lib -> lib.getLibrariesToRelease().stream())
- .collect(Collectors.toSet());
-
- project
- .getExtensions()
- .getExtraProperties()
- .set("projectsToPublish", projectsToPublish);
-
- project
- .getTasks()
- .register(
- "semverCheckForRelease",
- t -> {
- for (FirebaseLibraryExtension toPublish : projectsToPublish) {
- t.dependsOn(toPublish.getPath() + ":semverCheck");
- }
- });
- project
- .getTasks()
- .create(
- "validatePomForRelease",
- t -> {
- for (FirebaseLibraryExtension toPublish : projectsToPublish) {
- t.dependsOn(toPublish.getPath() + ":isPomDependencyValid");
- }
- });
- project.subprojects(
- sub -> {
- if (sub.getExtensions().findByType(FirebaseLibraryExtension.class) == null)
- return;
- publishAllToLocal.dependsOn(
- sub.getPath() + ":publishMavenAarPublicationToMavenLocal");
- publishAllToBuildDir.dependsOn(
- sub.getPath() + ":publishMavenAarPublicationToBuildDirRepository");
- });
- project
- .getTasks()
- .create(
- "checkHeadDependencies",
- CheckHeadDependencies.class,
- t -> {
- t.getProjectsToPublish().set(projectsToPublish);
- t.getAllFirebaseProjects().set(allFirebaseProjects);
- firebasePublish.dependsOn(t);
- });
-
- project
- .getTasks()
- .register(
- "publishProjectsToMavenLocal",
- t -> {
- for (FirebaseLibraryExtension toPublish : projectsToPublish) {
- t.dependsOn(getPublishTask(toPublish, "MavenLocal"));
- }
- });
-
- Task publishProjectsToBuildDir =
- project
- .getTasks()
- .create(
- "publishProjectsToBuildDir",
- t -> {
- for (FirebaseLibraryExtension toPublish : projectsToPublish) {
- t.dependsOn(getPublishTask(toPublish, "BuildDirRepository"));
- t.dependsOn(toPublish.getPath() + ":kotlindoc");
- }
- });
- Zip buildMavenZip =
- project
- .getTasks()
- .create(
- "buildMavenZip",
- Zip.class,
- zip -> {
- zip.dependsOn(publishProjectsToBuildDir);
- zip.getArchiveFileName().set("m2repository.zip");
- zip.getDestinationDirectory().set(project.getBuildDir());
- zip.from(project.getBuildDir() + "/m2repository");
- });
- Zip buildKotlindocZip =
- project
- .getTasks()
- .create(
- "buildKotlindocZip",
- Zip.class,
- zip -> {
- zip.dependsOn(publishProjectsToBuildDir);
- zip.getArchiveFileName().set("kotlindoc.zip");
- zip.getDestinationDirectory().set(project.getBuildDir());
- zip.from(project.getBuildDir() + "/firebase-kotlindoc");
- });
- Task info =
- project
- .getTasks()
- .create(
- "publishPrintInfo",
- t ->
- publishAllToLocal.doLast(
- it ->
- project
- .getLogger()
- .lifecycle(
- "Publishing the following libraries:\n{}",
- projectsToPublish.stream()
- .map(FirebaseLibraryExtension::getPath)
- .collect(Collectors.joining("\n")))));
- buildMavenZip.mustRunAfter(info);
- buildKotlindocZip.mustRunAfter(info);
- firebasePublish.dependsOn(info, buildMavenZip, buildKotlindocZip);
- });
- }
-
- private List readReleaseConfigFile(String publishConfigurationFilePath) {
- try (Stream stream = Files.lines(Path.of(publishConfigurationFilePath))) {
- return stream
- .dropWhile((line) -> !line.equals("[modules]"))
- // We need to skip the "[modules]" line since it's not dropped
- .skip(1)
- .collect(Collectors.toList());
- } catch (IOException e) {
- throw new IllegalArgumentException(
- "Error reading configuration file " + publishConfigurationFilePath, e);
- }
- }
-}
diff --git a/docs/make_release_notes.py b/docs/make_release_notes.py
index 4c32465cf01..62aa486a2a0 100644
--- a/docs/make_release_notes.py
+++ b/docs/make_release_notes.py
@@ -23,7 +23,7 @@
import string
from dataclasses import dataclass, field
-
+# TODO(b/279610345) - Replace this with a Gradle task
@dataclass
class Changelog:
path: str
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 873c6c3f7ed..41969acbf46 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -33,6 +33,7 @@ findbugs-jsr305 = { module = "com.google.code.findbugs:jsr305", version = "3.0.2
javax-inject = { module = "javax.inject:javax.inject", version = "1" }
kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kotlin" }
kotlin-coroutines-tasks = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-play-services", version.ref = "coroutines" }
+kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version = "1.5.0" }
kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "coroutines" }
okhttp = { module = "com.squareup.okhttp3:okhttp", version = "3.12.13" }
org-json = { module = "org.json:json", version = "20210307" }