-
Notifications
You must be signed in to change notification settings - Fork 313
/
changelog.py
executable file
·115 lines (84 loc) · 3.81 KB
/
changelog.py
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
#!/usr/bin/env python3
# Licensed to Elasticsearch B.V. under one or more contributor
# license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright
# ownership. Elasticsearch B.V. licenses this file to you under
# the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
import os
import sys
import github3
ORG = "elastic"
REPO = "rally"
def find_milestone(repo, title):
for m in repo.milestones(state="open", sort="due_date"):
if m.title == title:
return m
return None
def print_category(heading, issue_list):
if issue_list:
print("#### %s\n" % heading)
for issue in issue_list:
print_issue(issue)
print("")
def print_issue(issue):
breaking_hint = " (Breaking)" if labelled(issue, label_name="breaking") else ""
print("* [#%s](%s)%s: %s" % (str(issue.number), issue.html_url, breaking_hint, issue.title))
def labelled(issue, label_name):
for label in issue.labels():
if label.name == label_name:
return True
return False
def is_pr(issue):
"""
:param issue: an issue. May also be a PR.
:return: True iff the issue is actually a PR.
"""
return issue.html_url and "pull" in issue.html_url and issue.pull_request().merged
def pr_list(i):
return [item for item in i if is_pr(item)]
def list_subtract(a, b):
return [item for item in a if item not in b]
def prs(gh, milestone, with_labels, without_labels=None):
prs_labelled = pr_list(gh.issues_on(ORG, REPO, milestone=milestone.number, state="closed", labels=with_labels))
filtered_prs = prs_labelled
if without_labels:
for label in without_labels:
prs_not_labelled = pr_list(gh.issues_on(ORG, REPO, milestone=milestone.number, state="closed", labels=label))
filtered_prs = list_subtract(filtered_prs, prs_not_labelled)
return filtered_prs
def main():
if len(sys.argv) != 2:
print("usage: %s milestone" % sys.argv[0], file=sys.stderr)
exit(1)
milestone_name = sys.argv[1]
# requires a personal Github access token with permission `public_repo` (see https://github.com/settings/tokens)
gh = github3.login(token=open("%s/.github/rally_release_changelog.token" % os.getenv("HOME")).readline().strip())
rally_repo = gh.repository(ORG, REPO)
milestone = find_milestone(rally_repo, title=milestone_name)
if not milestone:
print("No open milestone named [%s] found." % milestone_name, file=sys.stderr)
exit(2)
if milestone.open_issues > 0:
print("There are [%d] open issues on milestone [%s]. Aborting..." % (milestone.open_issues, milestone_name), file=sys.stderr)
exit(2)
print("### %s\n" % milestone_name)
print_category("Highlights", prs(gh, milestone, with_labels="highlight"))
print_category(
"Enhancements", prs(gh, milestone, with_labels="enhancement", without_labels=[":Docs", "highlight", ":internal", ":misc"])
)
print_category("Bug Fixes", prs(gh, milestone, with_labels="bug", without_labels=[":Docs", "highlight", ":internal", ":misc"]))
print_category("Doc Changes", prs(gh, milestone, with_labels=":Docs", without_labels=["highlight", ":misc"]))
print_category("Miscellaneous Changes", prs(gh, milestone, with_labels=":misc", without_labels=[":internal"]))
if __name__ == "__main__":
main()