-
Notifications
You must be signed in to change notification settings - Fork 1
/
release.py
executable file
·150 lines (115 loc) · 3.81 KB
/
release.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
#!/usr/bin/env python3
#
# Release script for spade
#
from collections import OrderedDict
# pylint: disable=unused-wildcard-import,wildcard-import
try:
from hostage import *
except ImportError:
print("!! Release library unavailable.")
print("!! Use `pip install hostage` to fix.")
print("!! You will also need an API token in .github.token,")
print("!! a .hubrrc config, or `brew install hub` configured.")
print("!! A $GITHUB_TOKEN env variable will also work.")
exit(1)
#
# Globals
#
notes = File(".last-release-notes")
latestTag = git.Tag.latest(branch = "main")
def formatIssue(issue):
return "- {title} (#{number})\n".format(
number=issue.number,
title=issue.title)
def buildLabeled(labelsToTitles):
"""Given a set of (label, title) tuples, produces an
OrderedDict whose keys are `label`, and whose values are
dictionaries containing 'title' -> `title`, and
'content' -> string. The iteration order of the dictionary
will preserve the ordering of the provided tuples
"""
result = OrderedDict()
for k, v in labelsToTitles:
result[k] = {'title': v, 'content': ''}
return result
def buildDefaultNotes(_):
if not latestTag: return ''
logParams = {
'path': latestTag.name + "..HEAD",
'grep': ["Fix #", "Fixes #", "Closes #"],
'pretty': "format:- %s"}
logParams["invertGrep"] = True
msgs = git.Log(**logParams).output()
contents = ''
lastReleaseDate = latestTag.get_created_date()
if lastReleaseDate.tzinfo:
# pygithub doesn't respect tzinfo, so we have to do it ourselves
lastReleaseDate -= lastReleaseDate.tzinfo.utcoffset(lastReleaseDate)
lastReleaseDate.replace(tzinfo=None)
closedIssues = github.find_issues(state='closed', since=lastReleaseDate)
labeled = buildLabeled([
['feature', "New Features"],
['enhancement', "Enhancements"],
['bug', "Bug Fixes"],
['_default', "Other resolved tickets"],
])
if closedIssues:
for issue in closedIssues:
found = False
for label in labeled.keys():
if label in issue.labels:
labeled[label]['content'] += formatIssue(issue)
found = True
break
if not found:
labeled['_default']['content'] += formatIssue(issue)
for labeledIssueInfo in labeled.values():
if labeledIssueInfo['content']:
contents += "\n**{title}**:\n{content}".format(**labeledIssueInfo)
if msgs: contents += "\n**Notes**:\n" + msgs
return contents.strip()
#
# Verify
#
version = verify(File("project.clj")
.filtersTo(RegexFilter('defproject net.dhleong/spade "(.*)"'))
).valueElse(echoAndDie("No version!?"))
if version.endswith("SNAPSHOT"):
print("May not release SNAPSHOT versions (got %s)" % version)
sys.exit(1)
else:
print("Testing version", version)
versionTag = git.Tag(version)
verify(versionTag.exists())\
.then(echoAndDie("Version `%s` already exists!" % version))
#
# Make sure all the tests pass
#
verify(Execute("lein test")).succeeds(silent=False).orElse(die())
#
# Build the release notes
#
initialNotes = verify(notes.contents()).valueElse(buildDefaultNotes)
notes.delete()
verify(Edit(notes, withContent=initialNotes).didCreate())\
.orElse(echoAndDie("Aborted due to empty message"))
releaseNotes = notes.contents()
#
# Deploy
#
verify(Execute('lein deploy clojars')).succeeds(silent=False)
#
# Upload to github
#
print("Uploading to Github...")
verify(versionTag).create()
verify(versionTag).push("origin")
gitRelease = github.Release(version)
verify(gitRelease).create(body=releaseNotes)
#
# Success! Now, just cleanup and we're done!
#
notes.delete()
print("Done! Published %s" % version)
# flake8: noqa