Skip to content

Commit 89764c0

Browse files
Merge pull request #873 from adamtheturtle/release-process
Release process Python script
2 parents fcafd4c + 5943ca6 commit 89764c0

File tree

4 files changed

+141
-5
lines changed

4 files changed

+141
-5
lines changed

admin/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
"""
2+
Admin tools.
3+
"""

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()

dev-requirements.txt

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
1-
PyYAML==3.13
2-
Pygments==2.2.0
3-
Sphinx==1.8.1
4-
VWS-Python-Mock==2018.10.02.0
51
autoflake==1.2
62
check-manifest==0.37
73
codecov==2.0.15 # Upload coverage data
84
doc8==0.8.0
95
dodgy==0.1.9 # Look for uploaded secrets
6+
dulwich==0.19.6
107
flake8-commas==2.0.0 # Require silicon valley commas
118
flake8-quotes==1.0.0 # Require single quotes
129
flake8==3.5.0 # Lint
@@ -15,11 +12,17 @@ mypy==0.630 # Type checking
1512
pip_check_reqs==2.0.3
1613
pydocstyle==2.1.1 # Lint docstrings
1714
pyenchant==2.0.0 # Bindings for a spellchecking sytem
15+
pygithub==1.43.2
16+
Pygments==2.2.0
1817
pylint==2.1.1 # Lint
1918
pyroma==2.4 # Packaging best practices checker
2019
pytest-cov==2.6.0 # Measure code coverage
2120
pytest==3.8.2 # Test runners
21+
PyYAML==3.13
22+
Sphinx==1.8.1
2223
sphinxcontrib-spelling==4.2.0
24+
twine==1.12.1
2325
versioneer==0.18
2426
vulture==0.29
27+
VWS-Python-Mock==2018.10.02.0
2528
yapf==0.24.0 # Automatic formatting for Python

setup.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ ignore =
1010
.style.yapf
1111
.travis.yml
1212
admin
13-
admin/release.sh
13+
admin/*
1414
CHANGELOG.rst
1515
CODE_OF_CONDUCT.rst
1616
CONTRIBUTING.rst

0 commit comments

Comments
 (0)