-
Notifications
You must be signed in to change notification settings - Fork 22
/
lts-candidate-stats
executable file
·136 lines (112 loc) · 5.56 KB
/
lts-candidate-stats
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
#!/usr/bin/env groovy
// Intentional wildcard import to allow the script to run on Ubuntu 22.04 groovy and Red Hat 8.8 groovy.
// https://github.com/jenkins-infra/release/pull/468
// https://stackoverflow.com/questions/55169114/unable-to-add-xmlslurper-to-eclipse-groovy-project
import groovy.xml.*;
class Script {
private static final String PREFIX = "https://issues.jenkins.io/sr/jira.issueviews:searchrequest-xml/temp/SearchRequest.xml?tempMax=1000&jqlQuery=";
static Integer main(String[] args) {
if (args.size() != 1) {
System.err.println("Usage lts-candidate-stats <version>")
System.exit 1
}
def version = args[0];
def targetVersion = ['bash', '-c', "echo 'VERSION=\${project.version}' | mvn help:evaluate | sed -n 's/^VERSION=//p'"].execute().text
if (!targetVersion.contains(version)) {
System.err.println("The previous version does not appear to be released yet: " + targetVersion)
System.exit 1
}
def remoteName = ['git', 'for-each-ref', "--format='%(upstream:remotename)'", 'refs/heads/master'].execute().text
['git', 'fetch', 'jenkinsci', 'master:master'].execute().text
println "Latest core version: " + ['git', 'describe', 'master', '--abbrev=0'].execute().text
def categories = [:];
categories['Postponed'] = [];
categories['Rejected'] = fetch(PREFIX + "labels+in+%28${version}-rejected%29").toList()
categories['Fixed'] = fetch(PREFIX + "labels+in+%28${version}-fixed%29").toList()
categories['Candidates'] = fetch("https://issues.jenkins.io/sr/jira.issueviews:searchrequest-xml/12146/SearchRequest-12146.xml?tempMax=1000").toList()
categories['Postponed'] = categories['Candidates'].findAll { c ->
categories['Rejected'].find { it.key == c.key }
}
categories['Rejected'].removeAll(categories['Postponed'])
categories['Candidates'].removeAll(categories['Postponed'])
categories.each { title, issues ->
printListing(title, issues)
}
return
}
static Iterable fetch(String jql) {
def text = new URL(jql).text
return new XmlSlurper().parseText(text).channel.item
}
static void printListing(String title, items) {
if (!items.isEmpty()) {
println "${title}\n${''.padRight(title.length(), '-')}\n"
for (it in items) {
def prio = it.priority.toString()
if (prio.toLowerCase() in ['blocker', 'critical']) {
prio = Ansi.color(prio.padRight(10), Ansi.RED)
} else {
prio = prio.padRight(10)
}
def age = Ansi.color(ageIndicator(it), Ansi.YELLOW)
println "${it.key}\t\t${prio}\t\t${age}"
println "\t${it.summary}"
def labels = it.labels.label.collect { it.toString() }
labels.retainAll(['non-trivial-lts-backporting', 'regression'])
if (!labels.empty){
println "\t${Ansi.color(labels.join(' '), Ansi.RED)}"
}
println "\t${it.link}"
it.issuelinks.issuelinktype.each {
if (it.name.toString() == 'Cause') {
it.outwardlinks.issuelink.each {
def caused = Ansi.color(
"Caused https://issues.jenkins.io/browse/${it.toString()}",
Ansi.RED
)
println "\t\t$caused"
}
}
}
println ""
}
}
}
static String ageIndicator(it) {
def releasedAs = it.customfields.customfield.find { it.customfieldname == "Released As" }.customfieldvalues as String
if (releasedAs?.trim()) {
return releasedAs.replaceAll("[Jj]enkins[ -]", "")
} else {
return it.updated
}
}
// Credit https://gist.github.com/tvinke/db4d21dfdbdae49e6f92dcf1ca6120de
private static class Ansi {
static final String NORMAL = "\u001B[0m"
static final String BOLD = "\u001B[1m"
static final String ITALIC = "\u001B[3m"
static final String UNDERLINE = "\u001B[4m"
static final String BLINK = "\u001B[5m"
static final String RAPID_BLINK = "\u001B[6m"
static final String REVERSE_VIDEO = "\u001B[7m"
static final String INVISIBLE_TEXT = "\u001B[8m"
static final String BLACK = "\u001B[30m"
static final String RED = "\u001B[31m"
static final String GREEN = "\u001B[32m"
static final String YELLOW = "\u001B[33m"
static final String BLUE = "\u001B[34m"
static final String MAGENTA = "\u001B[35m"
static final String CYAN = "\u001B[36m"
static final String WHITE = "\u001B[37m"
static final String DARK_GRAY = "\u001B[1;30m"
static final String LIGHT_RED = "\u001B[1;31m"
static final String LIGHT_GREEN = "\u001B[1;32m"
static final String LIGHT_YELLOW = "\u001B[1;33m"
static final String LIGHT_BLUE = "\u001B[1;34m"
static final String LIGHT_PURPLE = "\u001B[1;35m"
static final String LIGHT_CYAN = "\u001B[1;36m"
static String color(String text, String ansiValue) {
ansiValue + text + NORMAL
}
}
}