-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
releaseNotes.scala
79 lines (69 loc) · 2.83 KB
/
releaseNotes.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
import scala.io.Source
/**
* A script to create release notes from github pull request page.
* To use first go to https://github.com/typelevel/cats/pulls?q=is%3Apr+milestone%3A_MILESTONE_+is%3Aclosed
* replace _MILESTONE_ with actual milestone like 1.5
* Make sure all PR are labeled properly with one of the
* "Binary Breaking", "Source Breaking", "bug", "enhancement", "documentation", "testing", "build"
* copy the content of the table from each page to a file (see releaseNotesTestFile as an example).
* and run `scala releaseNotes.scala YOUR_FILE_NAME``
*/
object ReleaseNotesFromGitHubText {
def main(args: Array[String]): Unit = {
val cleaned = Source
.fromFile(args(0))
.getLines()
.toList
.filterNot(_.trim.isEmpty)
.filterNot(_.matches("^\\s+\\d+\\s*$")) // remove comments count
.map(_.replaceAll(""" was merged .+""", ""))
.sliding(2)
.zipWithIndex
.filter(_._2 % 2 == 0)
.map(_._1)
val lables = List("Binary Breaking", "Source Breaking", "bug", "enhancement", "documentation", "testing", "build")
val normalReg = ("(.+)\\s+(" + lables.drop(2).mkString("|") + ")$$").r
val numUserReg = """#(\d+)\sby\s(.+)$""".r
val binaryBreakingReg = ("(.+)\\s+(" + lables.head + ").*$$").r
val sourceBreakingReg = ("(.+)\\s+(" + lables(1) + ").*$$").r
val prs = cleaned.map {
case List(binaryBreakingReg(title, label), numUserReg(num, user)) => PR(title, label, num, user)
case List(sourceBreakingReg(title, label), numUserReg(num, user)) => PR(title, label, num, user)
case List(normalReg(title, label), numUserReg(num, user)) => PR(title, label, num, user)
}.toList
def toTitle(lable: String, size: Int): String = {
val singular =
lable match {
case "build" => "build improvement"
case "testing" => "test improvement"
case "bug" => "bug fix"
case "documentation" => "documentation improvement"
case "enhancement" => "API/feature enhancement"
case "Source Breaking" => "source breaking change"
case "Binary Breaking" => "binary breaking change"
}
// poor man's pluralizer
if (size > 1) {
if (singular.endsWith("x")) singular + "es"
else singular + "s"
} else singular
}
val out = prs
.groupBy(_.label)
.toList
.sortBy(p => lables.indexOf(p._1))
.map { case (label, prs) =>
s"""
|### ${prs.size} ${toTitle(label, prs.size)}
|
|${prs.map(_.toMD).mkString("\n|")}
""".stripMargin
}
.mkString("\n")
println(out)
}
case class PR(title: String, label: String, num: String, user: String) {
def toMD: String =
s"* [#$num](https://github.com/typelevel/cats/pull/$num) $title by @$user"
}
}