com.gabrielittner.github.diff.services.MarkdownCommentBuilder.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of github-diff Show documentation
Show all versions of github-diff Show documentation
Diff apks and post results to Github
package com.gabrielittner.github.diff.services
import com.gabrielittner.github.diff.CommentBuilder
import com.jakewharton.byteunits.BinaryByteUnit
import kotlin.math.abs
class MarkdownCommentBuilder(apkName: String) : CommentBuilder {
private val builder = StringBuilder("### $apkName")
private val initialLength = builder.length
private val columns = mutableListOf().also {
it.addColumn("", "Commit", "Apk size", "Methods", "Fields")
}
override fun appendPermissionAddedNote(baseLabel: String, added: Int) {
builder.appendImportantDiff("permissions", "added", added)
}
override fun appendPermissionRemovedNote(baseLabel: String, removed: Int) {
builder.appendImportantDiff("permissions", "removed", removed)
}
override fun appendRequiredFeaturesAddedNote(baseLabel: String, added: Int) {
builder.appendImportantDiff("required features", "added", added)
}
override fun appendRequiredFeaturesRemovedNote(baseLabel: String, removed: Int) {
builder.appendImportantDiff("required features", "removed", removed)
}
override fun appendApkSizeIncreasedNote(baseLabel: String, change: Int, percentage: Double) {
builder.appendHighlight(baseLabel, "apk size", change, percentage, ::binaryFormat)
}
override fun appendApkSizeDecreasedNote(baseLabel: String, change: Int, percentage: Double) {
builder.appendHighlight(baseLabel, "apk size", change, percentage, ::binaryFormat)
}
override fun appendMethodCountIncreasedNote(baseLabel: String, change: Int, percentage: Double) {
builder.appendHighlight(baseLabel, "method count", change, percentage, ::simpleFormat)
}
override fun appendMethodCountDecreasedNote(baseLabel: String, change: Int, percentage: Double) {
builder.appendHighlight(baseLabel, "method count", change, percentage, ::simpleFormat)
}
override fun appendManifestDiffUrl(baseLabel: String, url: String) {
builder.append("\n\n")
builder.append("$baseLabel manifest diff".linkify(url))
}
override fun appendCurrentStats(url: String, commit: String, size: Int, methods: Int, fields: Int) {
columns.addColumn("current".linkify(url), commit, size, methods, fields)
}
override fun appendOldStats(
label: String,
labelUrl: String,
commit: String,
size: Int,
methods: Int,
fields: Int
) {
columns.addColumn(label.linkify(labelUrl), commit, size, methods, fields)
}
override fun appendOldStatsDiff(
sizeChange: Int,
sizePercentage: Double,
sizeDiffUrl: String?,
methodsChange: Int,
methodsPercentage: Double,
methodsDiffUrl: String?,
fieldsChange: Int,
fieldsPercentage: Double,
fieldDiffUrl: String?
) {
columns.addColumn(
"",
"",
relativeFormat(sizeChange, sizePercentage, ::binaryFormat).linkify(sizeDiffUrl),
relativeFormat(methodsChange, methodsPercentage, ::simpleFormat).linkify(methodsDiffUrl),
relativeFormat(fieldsChange, fieldsPercentage, ::simpleFormat).linkify(fieldDiffUrl)
)
}
override fun build(): String {
val finalBuilder = StringBuilder(builder.toString())
if (finalBuilder.length == initialLength) {
finalBuilder.append("\nNo changes of note")
}
finalBuilder.append("\n\n")
for (row in 0..5) {
finalBuilder.append("\n|")
columns.forEach {
finalBuilder.append(" ")
finalBuilder.append(it.getRow(row))
finalBuilder.append(" |")
}
}
return finalBuilder.toString()
}
private fun StringBuilder.appendImportantDiff(label: String, direction: String, change: Int) {
append("\n:bangbang: $direction $change $label")
}
private fun StringBuilder.appendHighlight(type: String, label: String, sizeDiff: Int, percentage: Double, diffFormat: (Int) -> String) {
append("\n")
if (sizeDiff > 0) {
append(":warning:️ Compared to $type the $label increased by ")
} else {
append(":white_check_mark: Compared to $type the $label decreased by ")
}
append(diffFormat(sizeDiff))
append(percentageFormat(percentage))
}
private fun MutableList.addColumn(label: String, commit: String?, size: Int, methods: Int, fields: Int) {
addColumn(label, commit ?: "n/a", binaryFormat(size), simpleFormat(methods), simpleFormat(fields))
}
private fun MutableList.addColumn(label: String, commit: String, size: String, methods: String, fields: String) {
add(Column(label, commit, size, methods, fields))
}
private fun simpleFormat(count: Int) = String.format("%,d", abs(count))
private fun binaryFormat(size: Int) = BinaryByteUnit.format(abs(size).toLong(), "#.##")!!
private fun relativeFormat(diff: Int, percentage: Double, diffFormat: (Int) -> String): String {
val prefix = when {
diff < 0 -> "-"
diff > 0 -> "+"
else -> ""
}
val formatted = "$prefix${diffFormat(diff)}${percentageFormat(percentage)}"
if (abs(percentage) >= 5.0) {
return "**$formatted**"
}
return formatted
}
private fun percentageFormat(percentage: Double): String {
return if (abs(percentage) < 0.1) {
""
} else {
String.format(" (%+.1f%%)", percentage)
}
}
private fun String.linkify(url: String?): String {
return if (url != null) {
"[$this]($url)"
} else {
this
}
}
private data class Column(
val title: String,
val commit: String,
val apkSize: String,
val methods: String,
val fields: String
) {
fun getRow(row: Int): String {
return when (row) {
0 -> title
1 -> "---"
2 -> commit
3 -> apkSize
4 -> methods
5 -> fields
else -> throw IllegalArgumentException("Unsupported row $row")
}
}
}
}