-
Notifications
You must be signed in to change notification settings - Fork 10
/
releaseGen.py
executable file
·185 lines (145 loc) · 6.32 KB
/
releaseGen.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
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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
#-----------------------------------------------------------------------------
# Title : Release notes generation
# ----------------------------------------------------------------------------
# This file is part of the SMURF software platform. It is subject to
# the license terms in the LICENSE.txt file found in the top-level directory
# of this distribution and at:
# https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html.
# No part of the SMURF software platform, including this file, may be
# copied, modified, propagated, or distributed except according to the terms
# contained in the LICENSE.txt file.
# ----------------------------------------------------------------------------
import os
import git # GitPython
from github import Github # PyGithub
from collections import OrderedDict as odict
import re
ghRepo = os.environ.get('REPO_SLUG')
token = os.environ.get('GITHUB_TOKEN')
newTag = os.environ.get('TAG')
if ghRepo is None:
exit("REPO_SLUG not in environment.")
if token is None:
exit("GITHUB_TOKEN not in environment.")
if newTag is None:
exit("TAG not in environment.")
# Check tag to make sure it is a proper release: va.b.c
vpat = re.compile('v\d+\.\d+\.\d+')
if vpat.match(newTag) is None:
exit("Not a release version")
# Git server
gh = Github(token)
remRepo = gh.get_repo(ghRepo)
# Find previous tag
oldTag = git.Git('.').describe('--abbrev=0','--tags',newTag + '^')
# Get logs
loginfo = git.Git('.').log(f"{oldTag}...{newTag}",'--grep','Merge pull request')
# Grouping of recors
records= odict({'Core': odict({'Bug' : [], 'Enhancement':[], 'Interface-change':[], 'Firmware-change':[]}),
'Client': odict({'Bug' : [], 'Enhancement':[], 'Interface-change':[], 'Firmware-change':[]}),
'Other': odict({'Bug' : [], 'Enhancement':[], 'Interface-change':[], 'Firmware-change':[]}),
'Unlabeled': [] })
details = []
entry = {}
# Parse the log entries
for line in loginfo.splitlines():
if line.startswith('Author:'):
entry['Author'] = line[7:].lstrip()
elif line.startswith('Date:'):
entry['Date'] = line[5:].lstrip()
elif 'Merge pull request' in line:
entry['PR'] = line.split()[3].lstrip()
entry['Branch'] = line.split()[5].lstrip()
# Get PR info from github
req = remRepo.get_pull(int(entry['PR'][1:]))
entry['Title'] = req.title
entry['body'] = req.body
entry['changes'] = req.additions + req.deletions
entry['Pull'] = entry['PR'] + f" ({req.additions} additions, {req.deletions} deletions, {req.changed_files} files changed)"
# Detect JIRA entry
if entry['Branch'].startswith('slaclab/ES'):
url = 'https://jira.slac.stanford.edu/issues/{}'.format(entry['Branch'].split('/')[1])
entry['Jira'] = url
else:
entry['Jira'] = None
entry['Labels'] = None
for lbl in req.get_labels():
if entry['Labels'] is None:
entry['Labels'] = lbl.name.lower()
else:
entry['Labels'] += ', ' + lbl.name.lower()
# Attempt to locate any issues mentioned in the body and comments
entry['Issues'] = None
## Generate a list with the bodies of the PR and all its comments
bodies = [entry['body']]
for c in req.get_issue_comments():
bodies.append(c.body)
## Look for the pattern '#\d+' in all the bodies, and add then to the
## entry['Issues'] list, avoiding duplications
for body in bodies:
iList = re.compile(r'(#\d+)').findall(body)
if iList is not None:
for issue in iList:
if entry['Issues'] is None:
entry['Issues'] = issue
elif not issue in entry['Issues']:
entry['Issues'] += ', ' + issue
# Add both to details list and sectioned summary list
found = False
if entry['Labels'] is not None:
# if the PR does not have a 'core' nor a 'client' label, add it to the 'Other' section
if not any(x in entry['Labels'] for x in ['core', 'client']):
for label in ['Bug','Enhancement', 'Interface-change', 'Firmware-change']:
if label.lower() in entry['Labels']:
records['Other'][label].append(entry)
found = True
else:
for section in ['Client','Core']:
for label in ['Bug','Enhancement', 'Interface-change', 'Firmware-change']:
if section.lower() in entry['Labels'] and label.lower() in entry['Labels']:
records[section][label].append(entry)
found = True
if not found:
records['Unlabeled'].append(entry)
details.append(entry)
entry = {}
# Generate summary text
md = f'# Pull Requests Since {oldTag}\n'
# Summary list is sectioned
for section in ['Client','Core', 'Other']:
subSec = ""
for label in ['Firmware-change', 'Interface-change', 'Bug','Enhancement']:
subLab = ""
entries = sorted(records[section][label], key=lambda v : v['changes'], reverse=True)
for entry in entries:
subLab += f" 1. {entry['PR']} - {entry['Title']}\n"
if len(subLab) > 0:
subSec += f"### {label}\n" + subLab
if len(subSec) > 0:
md += f"## {section}\n"
md += subSec
if len(records['Unlabeled']) > 0:
md += f"## Unlabeled\n"
for entry in records['Unlabeled']:
md += f" 1. {entry['PR']} - {entry['Title']}\n"
# Detailed list
det = '# Pull Request Details\n'
# Sort records
#details = sorted(details, key=lambda v : v['changes'], reverse=True)
# Generate detailed PR notes
for entry in details:
det += f"### {entry['Title']}"
det += '\n|||\n|---:|:---|\n'
for i in ['Author','Date','Pull','Branch','Issues','Jira','Labels']:
if entry[i] is not None:
det += f'|**{i}:**|{entry[i]}|\n'
det += '\n**Notes:**\n'
for line in entry['body'].splitlines():
det += '> ' + line + '\n'
det += '\n-------\n'
det += '\n\n'
# Include details
md += det
# Create release using tag
remRel = remRepo.create_git_release(tag=newTag, name=newTag, message=md, draft=False)
print("end of releaseGen.py")