@@ -33,9 +33,12 @@ import kotlinx.serialization.json.jsonArray
33
33
import kotlinx.serialization.json.jsonObject
34
34
import kotlinx.serialization.json.jsonPrimitive
35
35
import org.gradle.internal.Pair
36
+ import org.slf4j.Logger
37
+ import org.slf4j.LoggerFactory
36
38
37
39
@SuppressWarnings(" NewApi" )
38
40
class UnitTestReport (private val apiToken : String ) {
41
+ private val LOG : Logger = LoggerFactory .getLogger(" firebase-test-report" )
39
42
private val client: HttpClient =
40
43
HttpClient .newBuilder().connectTimeout(Duration .ofSeconds(10 )).build()
41
44
@@ -73,7 +76,7 @@ class UnitTestReport(private val apiToken: String) {
73
76
}
74
77
75
78
private fun outputReport (commits : List <ReportCommit >) {
76
- val reports: MutableList <TestReport > = ArrayList ()
79
+ val reports: MutableList <TestReport > = mutableListOf ()
77
80
for (commit in commits) {
78
81
reports.addAll(parseTestReports(commit.sha))
79
82
}
@@ -109,7 +112,7 @@ class UnitTestReport(private val apiToken: String) {
109
112
val commits = reports.map(TestReport ::commit).distinct()
110
113
var sdks = reports.map(TestReport ::name).distinct().sorted()
111
114
val lookup = reports.associateBy({ report -> Pair .of(report.name, report.commit) })
112
- val successPercentage: MutableMap <String , Int > = HashMap ()
115
+ val successPercentage: MutableMap <String , Int > = hashMapOf ()
113
116
var passingSdks = 0
114
117
// Get success percentage
115
118
for (sdk in sdks) {
@@ -140,7 +143,7 @@ class UnitTestReport(private val apiToken: String) {
140
143
}
141
144
val output = StringBuilder (" | |" )
142
145
for (commit in commits) {
143
- val rc = commitLookup.get( commit)
146
+ val rc = commitLookup[ commit]
144
147
output.append(" " )
145
148
if (rc != null && rc.pr != - 1 ) {
146
149
output.append(" [#${rc.pr} ](https://github.com/firebase/firebase-android-sdk/pull/${rc.pr} )" )
@@ -154,7 +157,7 @@ class UnitTestReport(private val apiToken: String) {
154
157
output.append(" :---: |" .repeat(commits.size))
155
158
output.append(" :--- |" )
156
159
for (sdk in sdks) {
157
- output.append(" \n | " ).append( sdk).append( " |" )
160
+ output.append(" \n | $ sdk |" )
158
161
for (commit in commits) {
159
162
if (lookup.containsKey(Pair .of(sdk, commit))) {
160
163
val report: TestReport = lookup[Pair .of(sdk, commit)]!!
@@ -174,38 +177,38 @@ class UnitTestReport(private val apiToken: String) {
174
177
if (successChance == 100 ) {
175
178
output.append(" ✅ 100%" )
176
179
} else {
177
- output.append(" ⛔ " ).append( successChance).append( " %" )
180
+ output.append(" ⛔ $ successChance %" )
178
181
}
179
182
output.append(" |" )
180
183
}
181
184
output.append(" \n " )
182
185
if (passingSdks > 0 ) {
183
- output.append(" \n *+" ).append( passingSdks).append( " passing SDKs* \n " )
186
+ output.append(" \n *+$ passingSdks passing SDKs" )
184
187
}
185
188
return output.toString()
186
189
}
187
190
188
191
private fun parseTestReports (commit : String ): List <TestReport > {
189
- val runs = request(" actions/runs?head_sha=" + commit)
192
+ val runs = request(" actions/runs?head_sha=$ commit" )
190
193
for (el in runs[" workflow_runs" ] as JsonArray ) {
191
194
val run = el as JsonObject
192
195
val name = run[" name" ]!! .jsonPrimitive.content
193
196
if (name == " CI Tests" ) {
194
197
return parseCITests(run[" id" ]!! .jsonPrimitive.content, commit)
195
198
}
196
199
}
197
- return listOf ()
200
+ return emptyList ()
198
201
}
199
202
200
203
private fun parseCITests (id : String , commit : String ): List <TestReport > {
201
- val reports: MutableList <TestReport > = ArrayList ()
202
- val jobs = request(" actions/runs/" + id + " /jobs" )
204
+ val reports: MutableList <TestReport > = mutableListOf ()
205
+ val jobs = request(" actions/runs/$id /jobs" )
203
206
for (el in jobs[" jobs" ] as JsonArray ) {
204
207
val job = el as JsonObject
205
- val jid = job[" name" ]!! .jsonPrimitive.content
206
- if (jid .startsWith(" Unit Tests (:" )) {
208
+ val jobName = job[" name" ]!! .jsonPrimitive.content
209
+ if (jobName .startsWith(" Unit Tests (:" )) {
207
210
reports.add(parseJob(TestReport .Type .UNIT_TEST , job, commit))
208
- } else if (jid .startsWith(" Instrumentation Tests (:" )) {
211
+ } else if (jobName .startsWith(" Instrumentation Tests (:" )) {
209
212
reports.add(parseJob(TestReport .Type .INSTRUMENTATION_TEST , job, commit))
210
213
}
211
214
}
@@ -217,17 +220,19 @@ class UnitTestReport(private val apiToken: String) {
217
220
job[" name" ]!!
218
221
.jsonPrimitive
219
222
.content
220
- .split(" \\ (:" .toRegex() )
223
+ .split(" (:" )
221
224
.dropLastWhile { it.isEmpty() }
222
225
.toTypedArray()[1 ]
223
226
name = name.substring(0 , name.length - 1 ) // Remove trailing ")"
224
- var status = TestReport . Status . OTHER
227
+ val status =
225
228
if (job[" status" ]!! .jsonPrimitive.content == " completed" ) {
226
229
if (job[" conclusion" ]!! .jsonPrimitive.content == " success" ) {
227
- status = TestReport .Status .SUCCESS
230
+ TestReport .Status .SUCCESS
228
231
} else {
229
- status = TestReport .Status .FAILURE
232
+ TestReport .Status .FAILURE
230
233
}
234
+ } else {
235
+ TestReport .Status .OTHER
231
236
}
232
237
val url = job[" html_url" ]!! .jsonPrimitive.content
233
238
return TestReport (name, type, status, commit, url)
@@ -236,8 +241,7 @@ class UnitTestReport(private val apiToken: String) {
236
241
private fun generateGraphQLQuery (commitCount : Int ): JsonObject {
237
242
return JsonObject (
238
243
mapOf (
239
- Pair (
240
- " query" ,
244
+ " query" to
241
245
JsonPrimitive (
242
246
"""
243
247
query {
@@ -265,7 +269,6 @@ class UnitTestReport(private val apiToken: String) {
265
269
"""
266
270
),
267
271
)
268
- )
269
272
)
270
273
}
271
274
@@ -281,14 +284,14 @@ class UnitTestReport(private val apiToken: String) {
281
284
* Abstracts away paginated calling. Naively joins pages together by merging root level arrays.
282
285
*/
283
286
private fun <T > request (uri : URI , clazz : Class <T >, payload : JsonObject ? = null): T {
284
- val builder = HttpRequest .newBuilder()
285
- if (payload == null ) {
286
- builder.GET ()
287
- } else {
288
- builder.POST (HttpRequest .BodyPublishers .ofString(payload.toString()))
289
- }
290
287
val request =
291
- builder
288
+ HttpRequest .newBuilder().apply {
289
+ if (payload == null ) {
290
+ GET ()
291
+ } else {
292
+ POST (HttpRequest .BodyPublishers .ofString(payload.toString()))
293
+ }
294
+ }
292
295
.uri(uri)
293
296
.header(" Authorization" , " Bearer $apiToken " )
294
297
.header(" X-GitHub-Api-Version" , " 2022-11-28" )
@@ -297,31 +300,31 @@ class UnitTestReport(private val apiToken: String) {
297
300
val response = client.send(request, HttpResponse .BodyHandlers .ofString())
298
301
val body = response.body()
299
302
if (response.statusCode() >= 300 ) {
300
- System .err. println (response)
301
- System .err. println (body)
303
+ LOG .error (response.toString() )
304
+ LOG .error (body)
302
305
}
303
306
val json =
304
307
when (clazz) {
305
308
JsonObject ::class .java -> Json .decodeFromString<JsonObject >(body)
306
309
JsonArray ::class .java -> Json .decodeFromString<JsonArray >(body)
307
- else -> throw IllegalArgumentException ()
310
+ else -> throw IllegalArgumentException (" Unsupported deserialization type of $clazz " )
308
311
}
309
312
if (json is JsonObject ) {
310
313
// Retrieve and merge objects from other pages, if present
311
314
return response
312
315
.headers()
313
316
.firstValue(" Link" )
314
317
.map { link: String ->
315
- val parts = link.split(" ," .toRegex() ).dropLastWhile { it.isEmpty() }
318
+ val parts = link.split(" ," ).dropLastWhile { it.isEmpty() }
316
319
for (part in parts) {
317
320
if (part.endsWith(" rel=\" next\" " )) {
318
321
// <foo>; rel="next" -> foo
319
322
val url =
320
323
part
321
- .split(" >;" .toRegex() )
324
+ .split(" >;" )
322
325
.dropLastWhile { it.isEmpty() }
323
326
.toTypedArray()[0 ]
324
- .split(" <" .toRegex() )
327
+ .split(" <" )
325
328
.dropLastWhile { it.isEmpty() }
326
329
.toTypedArray()[1 ]
327
330
val p = request<JsonObject >(URI .create(url), JsonObject ::class .java)
0 commit comments