summaryrefslogtreecommitdiff
path: root/tasks/notify.py
blob: eff891a5bb614f4db2074e15896f33b77ff8ac97 (plain)
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()