Skip to content

Commit

Permalink
Merge branch 'master' into sdk-33
Browse files Browse the repository at this point in the history
  • Loading branch information
utzcoz authored Jul 21, 2023
2 parents 5ee585f + eafda53 commit 97b1b96
Show file tree
Hide file tree
Showing 61 changed files with 1,114 additions and 778 deletions.
9 changes: 2 additions & 7 deletions buildSrc/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,6 @@ ktfmt {
googleStyle()
}

java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}

dependencies {
// Firebase performance plugin, it should be added here because of how gradle dependency
// resolution works, otherwise it breaks Fireperf Test Apps.
Expand All @@ -70,8 +65,8 @@ dependencies {

implementation(libs.kotlinx.serialization.json)
implementation("com.google.code.gson:gson:2.8.9")
implementation("com.android.tools.build:gradle:7.3.1")
implementation("com.android.tools.build:builder-test-api:7.2.2")
implementation("com.android.tools.build:gradle:7.4.2")
implementation("com.android.tools.build:builder-test-api:7.4.2")
implementation("gradle.plugin.com.github.sherter.google-java-format:google-java-format-gradle-plugin:0.9")

testImplementation(libs.bundles.kotest)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ public abstract class BomGeneratorTask extends DefaultTask {
"firebase-ml-model-interpreter",
"firebase-perf-license",
"firebase-plugins",
"firebase-sessions",
"firebase-storage-common",
"firebase-storage-common-license",
"firebase-storage-license",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ import java.io.File
* @see fromString
*/
data class Changelog(val releases: List<ReleaseEntry>) {

override fun toString(): String = releases.joinToString("\n") + "\n"

companion object {
/**
* Regex for finding the version titles in a changelog file.
Expand Down Expand Up @@ -114,7 +117,41 @@ data class ReleaseEntry(
val content: ReleaseContent,
val ktx: ReleaseContent?
) {

override fun toString(): String {
return """
|# ${version ?: "Unreleased"}
|$content
|${ktx?.let { """
|
|## Kotlin
|$it
|""" }.orEmpty()}
"""
.trimMargin()
}

/**
* If there is any content in this release.
*
* Meaning that there is content in either the [base release][content] or [ktx].
*
* @see ReleaseContent.hasContent
*/
fun hasContent() = content.hasContent() || ktx?.hasContent() ?: false

companion object {

/**
* A static instance of a [ReleaseEntry] without any content.
*
* 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.
*/
val Empty = ReleaseEntry(null, ReleaseContent("", emptyList()), null)

/**
* Regex for finding the Kotlin header in a changelog file.
*
Expand Down Expand Up @@ -164,18 +201,12 @@ data class ReleaseEntry(
val ktx = ktxString?.let { ReleaseContent.fromString(it) }
val version = ModuleVersion.fromStringOrNull(versionString)

if (ktx?.hasContent() == false)
throw RuntimeException("KTX header found without any content:\n $string")

return ReleaseEntry(version, content, ktx)
}
}

/**
* If there is any content in this release.
*
* Meaning that there is content in either the [base release][content] or [ktx].
*
* @see ReleaseContent.hasContent
*/
fun hasContent() = content.hasContent() || ktx?.hasContent() ?: false
}

/**
Expand All @@ -186,6 +217,25 @@ data class ReleaseEntry(
* @see fromString
*/
data class ReleaseContent(val subtext: String, val changes: List<Change>) {

override fun toString(): String {
val changes = changes.joinToString("\n")

return when {
subtext.isNotBlank() && changes.isNotBlank() -> "$subtext\n\n$changes"
subtext.isNotBlank() -> subtext
changes.isNotBlank() -> changes
else -> ""
}
}

/**
* If there is any content in this release.
*
* Meaning that there is either [changes] or [subtext] present.
*/
fun hasContent() = changes.isNotEmpty() || subtext.isNotBlank()

companion object {
/**
* Regex for finding the changes in a release.
Expand Down Expand Up @@ -235,7 +285,7 @@ data class ReleaseContent(val subtext: String, val changes: List<Change>) {
* "This release contains a known bug. We will address this in a future bugfix."
* ```
*/
val SUBTEXT_REGEX = Regex("^([^\\*\\s][\\s\\S]+?)(\\n\\n|(?![\\s\\S]))", RegexOption.MULTILINE)
val SUBTEXT_REGEX = Regex("^([^\\*\\s][\\s\\S]+?)(\\n\\n|(?![\\s\\S]))")

/**
* Parses [ReleaseContent] from a [String].
Expand All @@ -254,19 +304,14 @@ data class ReleaseContent(val subtext: String, val changes: List<Change>) {
* @see Change
*/
fun fromString(string: String): ReleaseContent {
val subtext = SUBTEXT_REGEX.find(string)?.value.orEmpty().trim()
val changes = CHANGE_REGEX.findAll(string).map { Change.fromString(it.firstCapturedValue) }
val changes =
CHANGE_REGEX.findAll(string).map { Change.fromString(it.firstCapturedValue) }.toList()
val firstChange = CHANGE_REGEX.find(string)
val subtext = if (firstChange != null) string.substringBefore(firstChange.value) else string

return ReleaseContent(subtext, changes.toList())
return ReleaseContent(subtext.trim(), changes.toList())
}
}

/**
* If there is any content in this release.
*
* Meaning that there is either [changes] or [subtext] present.
*/
fun hasContent() = changes.isNotEmpty() || subtext.isNotBlank()
}

/**
Expand All @@ -277,6 +322,9 @@ data class ReleaseContent(val subtext: String, val changes: List<Change>) {
* @see fromString
*/
data class Change(val type: ChangeType, val message: String) {

override fun toString(): String = "* [$type] $message"

companion object {
/**
* Regex for finding the information about a [Change].
Expand Down Expand Up @@ -331,5 +379,7 @@ enum class ChangeType {
CHANGED,
UNCHANGED,
REMOVED,
DEPRECATED
DEPRECATED;

override fun toString(): String = name.toLowerCase()
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ class FirebaseLibraryPlugin : BaseFirebaseLibraryPlugin() {

project.apply<DackkaPlugin>()
project.apply<GitSubmodulePlugin>()
project.apply<PostReleasePlugin>()
project.tasks.getByName("preBuild").dependsOn("updateGitSubmodules")
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,38 @@ fun Provider<File>.childFile(path: String) = map { File("${it.path}/$path") }
*/
fun File.childFile(childPath: String) = File("$path/$childPath")

/**
* Rewrites the lines of a file.
*
* The lines of the file are first read and then transformed by the provided `block` function. The
* transformed lines are then joined together with a newline character and written back to the file.
*
* If the `terminateWithNewline` parameter is set to `false`, the file will not be terminated with a
* newline character.
*
* @param terminateWithNewline Whether to terminate the file with a newline character. Defaults to
* `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.
*
* ```
* val file = File("my-file.txt")
*
* // Rewrite the lines of the file, replacing all spaces with tabs.
* file.rewriteLines { it.replace(" ", "\t") }
*
* // Rewrite the lines of the file, capitalizing the first letter of each word.
* file.rewriteLines { it.capitalizeWords() }
* ```
*
* @see [readLines]
* @see [writeText]
*/
fun File.rewriteLines(terminateWithNewline: Boolean = true, block: (String) -> String) {
val newLines = readLines().map(block)
writeText(newLines.joinToString("\n").let { if (terminateWithNewline) it + "\n" else it })
}

/**
* Provides a temporary file for use during the task.
*
Expand All @@ -77,6 +109,25 @@ fun DefaultTask.tempFile(path: String) = provider { temporaryDir.childFile(path)
*/
fun File.listFilesOrEmpty() = listFiles().orEmpty()

/**
* Copies this file to the specified directory.
*
* The new file will retain the same [name][File.getName] and [extension][File.extension] as this
* file.
*
* @param target The directory to copy the file to.
* @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
): File = copyTo(target.childFile(name), overwrite, bufferSize)

/**
* Submits a piece of work to be executed asynchronously.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ abstract class MakeReleaseNotesTask : DefaultTask() {
"""
|#### ${metadata.name} Kotlin extensions version $version {: #${metadata.versionName}-ktx_v$versionClassifier}
|
|${unreleased.ktx?.toReleaseNotes() ?: KotlinTransitiveRelease(project.name)}
|${unreleased.ktx?.toReleaseNotes() ?: KTXTransitiveReleaseText(project.name)}
"""
.trimMargin()
.trim()
Expand All @@ -115,32 +115,6 @@ abstract class MakeReleaseNotesTask : DefaultTask() {
releaseNotesFile.asFile.get().writeText(releaseNotes)
}

/**
* Provides default text for releasing KTX libs that are transitively invoked in a release,
* because their parent module is releasing. This only applies to `-ktx` libs, not Kotlin SDKs.
*/
private fun KotlinTransitiveRelease(projectName: String) =
"""
|The Kotlin extensions library transitively includes the updated
|`${ProjectNameToKTXPlaceholder(projectName)}` library. The Kotlin extensions library has no additional
|updates.
"""
.trimMargin()
.trim()

/**
* Maps a project's name to a KTX suitable placeholder.
*
* Some libraries produce artifacts with different coordinates than their project name. This
* method helps to map that gap for [KotlinTransitiveRelease].
*/
private fun ProjectNameToKTXPlaceholder(projectName: String) =
when (projectName) {
"firebase-perf" -> "firebase-performance"
"firebase-appcheck" -> "firebase-appcheck"
else -> projectName
}

/**
* Converts a [ReleaseContent] to a [String] to be used in a release note.
*
Expand Down Expand Up @@ -174,55 +148,6 @@ abstract class MakeReleaseNotesTask : DefaultTask() {
return "* {{${type.name.toLowerCase()}}} $fixedMessage"
}

/**
* Maps the name of a project to its potential [ReleaseNotesMetadata].
*
* @throws StopActionException If a mapping is not found
*/
// TODO() - Should we expose these as firebaselib configuration points; especially for new SDKS?
private fun convertToMetadata(string: String) =
when (string) {
"firebase-abt" -> ReleaseNotesMetadata("{{ab_testing}}", "ab_testing", false)
"firebase-appdistribution" -> ReleaseNotesMetadata("{{appdistro}}", "app-distro", false)
"firebase-appdistribution-api" -> ReleaseNotesMetadata("{{appdistro}} API", "app-distro-api")
"firebase-config" -> ReleaseNotesMetadata("{{remote_config}}", "remote-config")
"firebase-crashlytics" -> ReleaseNotesMetadata("{{crashlytics}}", "crashlytics")
"firebase-crashlytics-ndk" ->
ReleaseNotesMetadata("{{crashlytics}} NDK", "crashlytics-ndk", false)
"firebase-database" -> ReleaseNotesMetadata("{{database}}", "realtime-database")
"firebase-dynamic-links" -> ReleaseNotesMetadata("{{ddls}}", "dynamic-links")
"firebase-firestore" -> ReleaseNotesMetadata("{{firestore}}", "firestore")
"firebase-functions" -> ReleaseNotesMetadata("{{functions_client}}", "functions-client")
"firebase-dynamic-module-support" ->
ReleaseNotesMetadata(
"Dynamic feature modules support",
"dynamic-feature-modules-support",
false
)
"firebase-inappmessaging" -> ReleaseNotesMetadata("{{inappmessaging}}", "inappmessaging")
"firebase-inappmessaging-display" ->
ReleaseNotesMetadata("{{inappmessaging}} Display", "inappmessaging-display")
"firebase-installations" ->
ReleaseNotesMetadata("{{firebase_installations}}", "installations")
"firebase-messaging" -> ReleaseNotesMetadata("{{messaging_longer}}", "messaging")
"firebase-messaging-directboot" ->
ReleaseNotesMetadata("Cloud Messaging Direct Boot", "messaging-directboot", false)
"firebase-ml-modeldownloader" ->
ReleaseNotesMetadata("{{firebase_ml}}", "firebaseml-modeldownloader")
"firebase-perf" -> ReleaseNotesMetadata("{{perfmon}}", "performance")
"firebase-storage" -> ReleaseNotesMetadata("{{firebase_storage_full}}", "storage")
"firebase-appcheck" -> ReleaseNotesMetadata("{{app_check}}", "appcheck")
"firebase-appcheck-debug" ->
ReleaseNotesMetadata("{{app_check}} Debug", "appcheck-debug", false)
"firebase-appcheck-debug-testing" ->
ReleaseNotesMetadata("{{app_check}} Debug Testing", "appcheck-debug-testing", false)
"firebase-appcheck-playintegrity" ->
ReleaseNotesMetadata("{{app_check}} Play integrity", "appcheck-playintegrity", false)
"firebase-appcheck-safetynet" ->
ReleaseNotesMetadata("{{app_check}} SafetyNet", "appcheck-safetynet", false)
else -> throw StopActionException("No metadata mapping found for project: $string")
}

companion object {
/**
* Regex for GitHub issue links in change messages.
Expand Down Expand Up @@ -268,20 +193,3 @@ abstract class MakeReleaseNotesTask : DefaultTask() {
)
}
}

/**
* Provides extra metadata needed to create release notes for a given project.
*
* This data is needed for g3 internal mappings, and does not really have any implications for
* public repo actions.
*
* @property name The variable name for a project in a release note
* @property vesionName The variable name given to the versions of a project
* @property hasKTX The module has a KTX submodule (not to be confused with having KTX files)
* @see MakeReleaseNotesTask
*/
data class ReleaseNotesMetadata(
val name: String,
val versionName: String,
val hasKTX: Boolean = true
)
Loading

0 comments on commit 97b1b96

Please sign in to comment.