/
github-milestone-report.main.kts
executable file
·125 lines (101 loc) · 4.62 KB
/
github-milestone-report.main.kts
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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#!/bin/sh
//bin/true; exec kotlinc -script "$0" -- "$@"
/**
* Script to prepare release notes for the upcoming Detekt release
*
* You need kotlin 1.3.70+ installed on your machine
*/
// for the exec line
@file:Suppress("detekt.CommentSpacing")
@file:DependsOn("org.kohsuke:github-api:1.307")
@file:DependsOn("com.github.ajalt:clikt:2.8.0")
import com.github.ajalt.clikt.core.CliktCommand
import com.github.ajalt.clikt.parameters.options.default
import com.github.ajalt.clikt.parameters.options.flag
import com.github.ajalt.clikt.parameters.options.option
import com.github.ajalt.clikt.parameters.types.int
import org.kohsuke.github.GHIssue
import org.kohsuke.github.GHIssueState
import org.kohsuke.github.GHMilestone
import org.kohsuke.github.GHRepository
import org.kohsuke.github.GitHub
import java.io.File
import java.net.URL
import java.time.LocalDate
import java.time.format.DateTimeFormatter
class GithubMilestoneReport : CliktCommand() {
private val user: String by option("-u", help = "Github user or organization. Default: detekt").default("detekt")
private val project: String by option("-p", help = "Github project. Default: detekt").default("detekt")
private val milestone: Int? by option("-m", help = "Milestone number. Default: latest milestone.").int()
private val filterExisting: Boolean by option(
"-f",
help = "Filter issues that are already in the changelog. Default: false."
).flag(default = false)
override fun run() {
// connect to GitHub
val github: GitHub = GitHub.connectAnonymously()
val ghRepository: GHRepository = github.getUser(user).getRepository(project)
val milestones = ghRepository.listMilestones(GHIssueState.OPEN).toMutableList()
milestones.sortBy { it.number }
val milestoneId = milestone ?: milestones.last().number
// get milestone and issue data
val ghMilestone: GHMilestone = ghRepository.getMilestone(milestoneId)
var ghIssues: List<GHIssue> = ghRepository.getIssues(GHIssueState.CLOSED, ghMilestone)
if (filterExisting) {
val changeLogContent = File("./website/docs/introduction/changelog 1.x.x.md").readText()
ghIssues = ghIssues.filter { "[#${it.number}]" !in changeLogContent }
}
val milestoneTitle = ghMilestone.title.trim()
val groups = ghIssues.groupBy { issue ->
val labels = issue.labels.map { it.name }
when {
"notable changes" in labels -> "notable changes"
"dependencies" in labels -> "dependencies"
"housekeeping" in labels -> "housekeeping"
else -> "changes"
}
}
val notableChanges = groups["notable changes"]
val dependencyBumps = groups["dependencies"]
val housekeepingChanges = groups["housekeeping"]
val issuesForUsers = groups["changes"]
// print report
val content = StringBuilder().apply {
append(header(milestoneTitle))
append("\n")
append(section("Notable Changes"))
append("\n")
append(formatIssues(notableChanges))
append("\n")
append(section("Migration"))
append("\n")
append(section("Changelog"))
append("\n")
append(formatIssues(issuesForUsers))
append("\n")
append(section("Dependency Updates"))
append("\n")
append(formatIssues(dependencyBumps))
append("\n")
append(section("Housekeeping & Refactorings"))
append("\n")
append(formatIssues(housekeepingChanges))
append("\n")
append(footer(milestoneTitle, ghMilestone.htmlUrl))
}.toString()
println(content)
// write report to disk
val tempFile: File = File.createTempFile(project, "_$milestoneId.$milestoneTitle")
tempFile.writeText(content)
println("\nContent saved to ${tempFile.path}")
}
// formatting helpers
private fun formatIssues(issues: List<GHIssue>?) =
issues?.joinToString(separator = "\n", postfix = "\n") { entry(it) } ?: ""
private fun entry(issue: GHIssue) = entry(issue.title.trim(), issue.number, issue.htmlUrl)
private fun entry(content: String, issueId: Int, issueUrl: URL) = "- $content - [#$issueId]($issueUrl)"
private fun footer(footer: String, url: URL) = "See all issues at: [$footer]($url)"
private fun header(name: String) = "#### $name - ${DateTimeFormatter.ISO_DATE.format(LocalDate.now())} \n"
private fun section(name: String) = "##### $name\n"
}
GithubMilestoneReport().main(args)