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
|
# -*- coding: utf-8 -*-
"""Handles creating a release PR"""
import base64
import json
import os
import tempfile
import textwrap
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from pathlib import Path
from typing import Tuple
import httplib2
from apiclient import discovery
from git import Remote, Repo
from oauth2client import client, file, tools
from packaging.version import Version
ROOT_SRC_DIR = Path(__file__).parents[1]
def main() -> None:
repo = Repo(str(ROOT_SRC_DIR))
update_upstream(repo)
prev_version, release_version = get_last_release_versions(repo)
send_mail_message(
subject=f"tox release {release_version}",
content=get_message_body(release_version, prev_version),
)
print("All done! ✨ 🍰 ✨")
def get_message_body(release_version: Version, prev_version: Version) -> str:
is_major_release = release_version.release[0:2] != prev_version.release[0:2]
if is_major_release:
return textwrap.dedent(
f"""
The tox team is proud to announce the {release_version} feature release!
tox aims to automate and standardize testing in Python. It is part of a larger vision of easing the packaging, testing and release process of Python software.
Details about the changes can be found in the CHANGELOG: https://pypi.org/project/tox/{release_version}/#changelog
For complete documentation, please visit: http://tox.readthedocs.io/en/{release_version}/changelog.html
As usual, you can upgrade from pypi via:
pip install --upgrade tox
or - if you also want to get pre release versions:
pip install -upgrade --pre tox
We thank all present and past contributors to tox. Have a look at https://github.com/tox-dev/tox/blob/master/CONTRIBUTORS to see who contributed.
Happy toxing,
the tox-dev team
""" # noqa
)
else:
return textwrap.dedent(
f"""
The tox team is proud to announce the {release_version} bug fix release!
tox aims to automate and standardize testing in Python. It is part of a larger vision of easing the packaging, testing and release process of Python software.
For details about the fix(es),please check the CHANGELOG: https://pypi.org/project/tox/{release_version}/#changelog
We thank all present and past contributors to tox. Have a look at https://github.com/tox-dev/tox/blob/master/CONTRIBUTORS to see who contributed.
Happy toxing,
the tox-dev team
""" # noqa
)
def get_upstream(repo: Repo) -> Remote:
for remote in repo.remotes:
for url in remote.urls:
if url.endswith("tox-dev/tox.git"):
return remote
raise RuntimeError("could not find tox-dev/tox.git remote")
def get_last_release_versions(repo: Repo) -> Tuple[Version, Version]:
print("get latest release version")
commit_to_tag = {tag.commit.hexsha: tag for tag in repo.tags}
_, release_tag = sorted(
[(tag.commit.committed_datetime, tag) for tag in repo.tags], reverse=True
)[0]
for commit in release_tag.commit.iter_parents():
if commit.hexsha in commit_to_tag:
prev_release_tag = commit_to_tag[commit.hexsha]
prev_version = Version(prev_release_tag.name)
if not any(
(
prev_version.is_devrelease,
prev_version.is_prerelease,
prev_version.is_postrelease,
)
):
break
else:
raise RuntimeError("no previous release")
release_version = Version(release_tag.name)
print(f"\trelease {release_version} with previous {prev_version}")
return prev_version, release_version
def update_upstream(repo: Repo) -> None:
print("fetch latest remote")
upstream = get_upstream(repo)
upstream.fetch()
def send_mail_message(subject, content):
this_dir = Path(__file__).parent
store = file.Storage("credentials.json")
credentials = store.get()
if not credentials or credentials.invalid:
client_secret_json = json.loads((this_dir / "client_secret.json").read_text())
client_secret_json["installed"]["client_secret"] = os.environ["TOX_DEV_GOOGLE_SECRET"]
with tempfile.NamedTemporaryFile(mode="w+t") as temp_filename:
json.dump(client_secret_json, temp_filename)
temp_filename.flush()
flow = client.flow_from_clientsecrets(
filename=temp_filename.name, scope="https://www.googleapis.com/auth/gmail.send"
)
credentials = tools.run_flow(flow, store)
service = discovery.build("gmail", "v1", http=credentials.authorize(httplib2.Http()))
message = MIMEMultipart("alternative")
message["Subject"] = subject
message["From"] = "toxdevorg@gmail.com"
recipients = ["testing-in-python@lists.idyll.org", "tox-dev@python.org"]
message["To"] = ", ".join(recipients)
message.attach(MIMEText(content, "plain"))
raw_message_no_attachment = base64.urlsafe_b64encode(message.as_bytes())
raw_message_no_attachment = raw_message_no_attachment.decode()
body = {"raw": raw_message_no_attachment}
message_sent = service.users().messages().send(userId="me", body=body).execute()
message_id = message_sent["id"]
print(f"\tMessage sent with id: {message_id}")
if __name__ == "__main__":
main()
|