-
Notifications
You must be signed in to change notification settings - Fork 2
/
maintain-flagfit-expiration-issue.main.kts
148 lines (136 loc) · 5.09 KB
/
maintain-flagfit-expiration-issue.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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
@file:Repository("https://repo.maven.apache.org/maven2")
@file:DependsOn("org.json:json:20200518")
@file:DependsOn("org.kohsuke:github-api:1.315")
import org.json.JSONObject
import org.kohsuke.github.GHIssueState
import org.kohsuke.github.GitHub
import org.kohsuke.github.HttpException
import java.io.File
import java.util.regex.Pattern
class FlagExpirationIssueMaintainer(
private val githubToken: String,
private val repoName: String,
private val headSha: String,
) {
fun maintain(
sarifFilePath: String,
labelName: String = "",
fallbackAssigneeWhenOwnerNotPresent: String,
) {
val gitHub = GitHub.connectUsingOAuth(githubToken)
val repo = gitHub.getRepository(repoName)
val targetRuleIdList = listOf(FLAGFIT_DEADLINE_SOON, FLAGFIT_DEADLINE_EXPIRED)
val file = File(sarifFilePath)
val content = file.readText()
val jsonData = JSONObject(content)
val runs = jsonData
.getJSONArray("runs")
val results = runs.getJSONObject(0).getJSONArray("results")
val limitIssue = 50
val existingIssues =
repo.queryIssues()
.apply { if (labelName.isNotEmpty()) label(labelName) }
.state(GHIssueState.OPEN)
.pageSize(limitIssue)
.list()
.take(limitIssue)
.toMutableList()
if (existingIssues.size >= limitIssue) {
val messageLimitIssue = if (labelName.isNotEmpty()) {
"Found more than $limitIssue Issues with $labelName set, " +
"please make sure it is less than ${limitIssue}!"
} else {
"Found more than $limitIssue Issues set, " +
"please make sure it is less than ${limitIssue}!"
}
throw IllegalStateException(messageLimitIssue)
}
for (i in 0 until results.length()) {
val result = results.getJSONObject(i)
val ruleId = result.getString("ruleId")
if (ruleId in targetRuleIdList) {
val message = result.getJSONObject("message").getString("markdown")
val keyPatternRegex = "`key: (.*?)`"
val ownerPatternRegex = "`owner: (.*?)`"
val key = matchText(text = message, patternRegex = keyPatternRegex)
val owner = matchText(text = message, patternRegex = ownerPatternRegex)
val issueTitle = "Expiration status of the $key flag"
val warningMessage = """
|$message
|
|<!--
|DO NOT CHANGE
|This metadata is used for issue management.
|
|`ruleId: $ruleId`
|`key: $key`
|`owner: $owner`
|-->
""".trimMargin()
val locations = result.getJSONArray("locations").getJSONObject(0)
val physicalLocation = locations.getJSONObject("physicalLocation")
val artifactLocation = physicalLocation.getJSONObject("artifactLocation")
val baseUrl = repo.htmlUrl
val uri = artifactLocation.getString("uri")
val contextRegion = physicalLocation.getJSONObject("contextRegion")
val artifactUri = "${baseUrl}/blob/${headSha}/${uri}" +
"#L${contextRegion.getInt("startLine")}-L${
contextRegion.getInt("endLine")
}"
val existingIssue = existingIssues.firstOrNull { issue ->
val body = issue.body
key == matchText(text = body, patternRegex = keyPatternRegex)
}
if (existingIssue == null) {
val issue = try {
repo.createIssue(issueTitle)
.body(warningMessage)
.assignee(owner)
.apply { if (labelName.isNotEmpty()) label(labelName) }
.create()
} catch (e: HttpException) {
repo.createIssue(issueTitle)
.body(warningMessage)
.assignee(fallbackAssigneeWhenOwnerNotPresent)
.apply { if (labelName.isNotEmpty()) label(labelName) }
.create()
}
issue.comment(artifactUri)
existingIssues.add(issue)
} else {
val ruleIdPatternRegex = "`ruleId: (.*?)`"
if (ruleId != matchText(
text = existingIssue.body,
patternRegex = ruleIdPatternRegex
)) {
existingIssue.comments.forEach {
if (ruleId == matchText(text = it.body, patternRegex = ruleIdPatternRegex)) {
it.delete()
}
}
val warningComment = "## Warning\n$warningMessage"
existingIssue.comment(warningComment)
}
}
}
}
}
private fun matchText(text: String, patternRegex: String): String {
val pattern = Pattern.compile(patternRegex)
val matcher = pattern.matcher(text)
return if (matcher.find()) matcher.group(1) else ""
}
companion object {
const val FLAGFIT_DEADLINE_SOON = "FlagfitDeadlineSoon"
const val FLAGFIT_DEADLINE_EXPIRED = "FlagfitDeadlineExpired"
}
}
FlagExpirationIssueMaintainer(
githubToken = System.getenv("GITHUB_TOKEN"),
repoName = System.getenv("GITHUB_REPOSITORY"),
headSha = System.getenv("HEAD_SHA")
).maintain(
sarifFilePath = "./lint-results.sarif",
labelName = "featureflag-expiration",
fallbackAssigneeWhenOwnerNotPresent = "{Alternative assignor's GitHub UserId}"
)