@@ -15,6 +15,9 @@ package com.google.firebase.gradle.plugins
15
15
16
16
import com.google.common.collect.ImmutableList
17
17
import java.io.File
18
+ import kotlinx.serialization.Serializable
19
+ import kotlinx.serialization.encodeToString
20
+ import kotlinx.serialization.json.Json
18
21
import org.eclipse.jgit.api.Git
19
22
import org.eclipse.jgit.api.ListBranchCommand
20
23
import org.eclipse.jgit.api.errors.GitAPIException
@@ -31,25 +34,85 @@ import org.gradle.api.tasks.OutputFile
31
34
import org.gradle.api.tasks.TaskAction
32
35
import org.gradle.kotlin.dsl.findByType
33
36
37
+ /* *
38
+ * Contains output data from the Release Generator, published as release_report.json
39
+ *
40
+ * @property changesByLibraryName contains libs which have opted into the release, and their changes
41
+ * @property changedLibrariesWithNoChangelog contains libs not opted into the release, despite
42
+ * having changes
43
+ */
44
+ @Serializable
45
+ data class ReleaseReport (
46
+ val changesByLibraryName : Map <String , List <CommitDiff >>,
47
+ val changedLibrariesWithNoChangelog : Set <String >
48
+ ) {
49
+ companion object {
50
+ val formatter = Json { prettyPrint = true }
51
+ }
52
+
53
+ fun toFile (file : File ) = file.also { it.writeText(formatter.encodeToString(this )) }
54
+
55
+ override fun toString () =
56
+ """
57
+ |# Release Report
58
+ |${
59
+ changesByLibraryName.entries.joinToString(" \n " ) {
60
+ """
61
+ |## ${it.key}
62
+
63
+ |${it.value.joinToString(" \n " ) { it.toString() }}
64
+ """ .trimMargin()
65
+ }
66
+ }
67
+ |
68
+ |## SDKs with changes, but no changelogs
69
+ |${changedLibrariesWithNoChangelog.joinToString(" \n " )}
70
+ """
71
+ .trimMargin()
72
+ }
73
+
74
+ @Serializable
34
75
data class CommitDiff (
35
76
val commitId : String ,
77
+ val prId : String ,
36
78
val author : String ,
37
79
val message : String ,
80
+ val commitLink : String ,
81
+ val prLink : String ,
38
82
) {
39
- constructor (
40
- revCommit: RevCommit
41
- ) : this (revCommit.id.name, revCommit.authorIdent.name, revCommit.fullMessage) {}
83
+ companion object {
84
+ // This is a meant to capture the PR number from PR Titles
85
+ // ex: "Fix a problem (#1234)" -> "1234"
86
+ private val PR_ID_EXTRACTOR = Regex (" .*\\ (#(\\ d+)\\ ).*" )
87
+
88
+ public fun fromRevCommit (commit : RevCommit ): CommitDiff {
89
+ val commitId = commit.id.name
90
+ val prId =
91
+ PR_ID_EXTRACTOR .find(commit.fullMessage.split(" \n " ).first())?.groupValues?.get(1 ) ? : " "
92
+ return CommitDiff (
93
+ commitId,
94
+ prId,
95
+ commit.authorIdent.name,
96
+ commit.fullMessage,
97
+ " https://github.com/firebase/firebase-android-sdk/commit/$commitId " ,
98
+ " https://github.com/firebase/firebase-android-sdk/pull/$prId "
99
+ )
100
+ }
101
+ }
42
102
43
103
override fun toString (): String =
44
104
"""
45
105
|* ${message.split(" \n " ).first()}
46
- | https://github.com/firebase/firebase-android-sdk/ commit/ ${commitId} [${ author} ]
106
+ | [pr]( $prLink ) [ commit]( $commitLink ) [$author ]
47
107
48
108
"""
49
109
.trimMargin()
50
110
}
51
111
52
112
abstract class ReleaseGenerator : DefaultTask () {
113
+ companion object {
114
+ private val RELEASE_CHANGE_FILTER = " NO_RELEASE_CHANGE"
115
+ }
53
116
54
117
@get:Input abstract val currentRelease: Property <String >
55
118
@@ -59,7 +122,9 @@ abstract class ReleaseGenerator : DefaultTask() {
59
122
60
123
@get:OutputFile abstract val releaseConfigFile: RegularFileProperty
61
124
62
- @get:OutputFile abstract val releaseReportFile: RegularFileProperty
125
+ @get:OutputFile abstract val releaseReportMdFile: RegularFileProperty
126
+
127
+ @get:OutputFile abstract val releaseReportJsonFile: RegularFileProperty
63
128
64
129
@TaskAction
65
130
@Throws(Exception ::class )
@@ -81,34 +146,14 @@ abstract class ReleaseGenerator : DefaultTask() {
81
146
val releaseConfig = ReleaseConfig (currentRelease.get(), libsToRelease.map { it.path })
82
147
releaseConfig.toFile(releaseConfigFile.get().asFile)
83
148
84
- val releaseReport = generateReleaseReport (changes, changedLibsWithNoChangelog)
149
+ val releaseReport = ReleaseReport (changes, changedLibsWithNoChangelog)
85
150
if (printReleaseConfig.orNull.toBoolean()) {
86
- project.logger.info(releaseReport)
151
+ project.logger.info(releaseReport.toString() )
87
152
}
88
- writeReleaseReport(releaseReportFile.get().asFile, releaseReport)
153
+ releaseReportMdFile.get().asFile.writeText(releaseReport.toString())
154
+ releaseReportJsonFile.get().asFile.let { releaseReport.toFile(it) }
89
155
}
90
156
91
- private fun generateReleaseReport (
92
- changes : Map <String , List <CommitDiff >>,
93
- changedLibrariesWithNoChangelog : Set <String >
94
- ) =
95
- """
96
- |# Release Report
97
- |${
98
- changes.entries.joinToString(" \n " ) {
99
- """
100
- |## ${it.key}
101
-
102
- |${it.value.joinToString(" \n " ) { it.toString() }}
103
- """ .trimMargin()
104
- }
105
- }
106
- |
107
- |## SDKs with changes, but no changelogs
108
- |${changedLibrariesWithNoChangelog.joinToString(" \n " )}
109
- """
110
- .trimMargin()
111
-
112
157
private fun getChangesForLibraries (
113
158
repo : Git ,
114
159
branchRef : ObjectId ,
@@ -179,7 +224,7 @@ abstract class ReleaseGenerator : DefaultTask() {
179
224
.addRange(previousReleaseRef, currentReleaseRef)
180
225
.setMaxCount(10 )
181
226
.call()
182
- .filter { ! it.fullMessage.contains(" NO_RELEASE_CHANGE " ) }
227
+ .filter { ! it.fullMessage.contains(RELEASE_CHANGE_FILTER ) }
183
228
.isNotEmpty()
184
229
185
230
private fun getDirChanges (
@@ -188,11 +233,13 @@ abstract class ReleaseGenerator : DefaultTask() {
188
233
currentReleaseRef : ObjectId ,
189
234
directory : String
190
235
) =
191
- repo.log().addPath(directory).addRange(previousReleaseRef, currentReleaseRef).call().map {
192
- CommitDiff (it)
193
- }
194
-
195
- private fun writeReleaseReport (file : File , report : String ) = file.writeText(report)
236
+ repo
237
+ .log()
238
+ .addPath(directory)
239
+ .addRange(previousReleaseRef, currentReleaseRef)
240
+ .call()
241
+ .filter { ! it.fullMessage.contains(RELEASE_CHANGE_FILTER ) }
242
+ .map { CommitDiff .fromRevCommit(it) }
196
243
197
244
private fun getRelativeDir (project : Project ) = project.path.substring(1 ).replace(' :' , ' /' )
198
245
}
0 commit comments