Skip to content

Commit

Permalink
Merge branch 'master' into rl.report.deprecated
Browse files Browse the repository at this point in the history
  • Loading branch information
rlazo committed Jul 20, 2023
2 parents 4619e3f + 933d191 commit ee09b2d
Show file tree
Hide file tree
Showing 23 changed files with 522 additions and 268 deletions.
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 @@ -109,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 ee09b2d

Please sign in to comment.