Skip to content

Commit 796052c

Browse files
committed
Add release script to admin directory
1 parent 8333e91 commit 796052c

File tree

1 file changed

+130
-0
lines changed

1 file changed

+130
-0
lines changed

admin/release.py

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
"""
2+
Release the next version of VWS Python Mock.
3+
"""
4+
5+
import datetime
6+
import os
7+
import subprocess
8+
from pathlib import Path
9+
10+
from dulwich.porcelain import add, commit, push, tag_list
11+
from dulwich.repo import Repo
12+
from github import Github, Repository, UnknownObjectException
13+
14+
15+
def get_version() -> str:
16+
"""
17+
Return the next version of VWS Python Mock.
18+
This is today’s date in the format ``YYYY.MM.DD.MICRO``.
19+
``MICRO`` refers to the number of releases created on this date,
20+
starting from ``0``.
21+
"""
22+
utc_now = datetime.datetime.utcnow()
23+
date_format = '%Y.%m.%d'
24+
date_str = utc_now.strftime(date_format)
25+
local_repository = Repo('.')
26+
tag_labels = tag_list(repo=local_repository)
27+
tag_labels = [item.decode() for item in tag_labels]
28+
today_tag_labels = [
29+
item for item in tag_labels if item.startswith(date_str)
30+
]
31+
micro = int(len(today_tag_labels))
32+
return '{date}.{micro}'.format(date=date_str, micro=micro)
33+
34+
35+
def update_changelog(version: str) -> None:
36+
"""
37+
Add a version title to the changelog.
38+
"""
39+
changelog = Path('CHANGELOG.rst')
40+
changelog_contents = changelog.read_text()
41+
new_changelog_contents = changelog_contents.replace(
42+
'Next\n----',
43+
'Next\n----\n\n{version}\n------------'.format(version=version),
44+
)
45+
changelog.write_text(new_changelog_contents)
46+
47+
48+
def create_github_release(
49+
repository: Repository,
50+
version: str,
51+
) -> None:
52+
"""
53+
Create a tag and release on GitHub.
54+
"""
55+
changelog_url = (
56+
'https://vws-python-mock.readthedocs.io/en/latest/changelog.html'
57+
)
58+
repository.create_git_tag_and_release(
59+
tag=version,
60+
tag_message='Release ' + version,
61+
release_name='Release ' + version,
62+
release_message='See ' + changelog_url,
63+
type='commit',
64+
object=repository.get_commits()[0].sha,
65+
)
66+
67+
68+
def commit_and_push(version: str, repository: Repository) -> None:
69+
"""
70+
Commit and push all changes.
71+
"""
72+
local_repository = Repo('.')
73+
paths = ['CHANGELOG.rst']
74+
_, ignored = add(paths=paths)
75+
assert not ignored
76+
message = b'Update for release ' + version.encode('utf-8')
77+
commit(message=message)
78+
branch_name = 'master'
79+
push(
80+
repo=local_repository,
81+
remote_location=repository.ssh_url,
82+
refspecs=branch_name.encode('utf-8'),
83+
)
84+
85+
86+
def get_repo(github_token: str, github_owner: str) -> Repository:
87+
"""
88+
Get a GitHub repository.
89+
"""
90+
github_client = Github(github_token)
91+
try:
92+
github_user_or_org = github_client.get_organization(github_owner)
93+
except UnknownObjectException:
94+
github_user_or_org = github_client.get_user(github_owner)
95+
96+
return github_user_or_org.get_repo('vws-python-mock')
97+
98+
99+
def build() -> None:
100+
"""
101+
Build source and binary distributions.
102+
"""
103+
for args in (
104+
['git', 'fetch'],
105+
['rm', '-rf', 'build'],
106+
['python', 'setup.py', 'sdist', 'bdist_wheel'],
107+
['twine', 'upload', '-r', 'pypi', 'dist/*'],
108+
):
109+
subprocess.run(args=args, check=True)
110+
111+
112+
def main() -> None:
113+
"""
114+
Perform a release.
115+
"""
116+
github_token = os.environ['GITHUB_TOKEN']
117+
github_owner = os.environ['GITHUB_OWNER']
118+
repository = get_repo(github_token=github_token, github_owner=github_owner)
119+
version_str = get_version()
120+
update_changelog(version=version_str)
121+
commit_and_push(version=version_str, repository=repository)
122+
create_github_release(
123+
repository=repository,
124+
version=version_str,
125+
)
126+
build()
127+
128+
129+
if __name__ == '__main__':
130+
main()

0 commit comments

Comments
 (0)