1# -*- coding: utf-8 -*-
2"""
3Script used to publish GitHub release notes extracted from CHANGELOG.rst.
4
5This script is meant to be executed after a successful deployment in Travis.
6
7Uses the following environment variables:
8
9* GIT_TAG: the name of the tag of the current commit.
10* GH_RELEASE_NOTES_TOKEN: a personal access token with 'repo' permissions. It should be encrypted using:
11
12    $travis encrypt GH_RELEASE_NOTES_TOKEN=<token> -r pytest-dev/pytest
13
14  And the contents pasted in the ``deploy.env.secure`` section in the ``travis.yml`` file.
15
16The script also requires ``pandoc`` to be previously installed in the system.
17
18Requires Python3.6+.
19"""
20import os
21import re
22import sys
23from pathlib import Path
24
25import github3
26import pypandoc
27
28
29def publish_github_release(slug, token, tag_name, body):
30    github = github3.login(token=token)
31    owner, repo = slug.split("/")
32    repo = github.repository(owner, repo)
33    return repo.create_release(tag_name=tag_name, body=body)
34
35
36def parse_changelog(tag_name):
37    p = Path(__file__).parent.parent / "CHANGELOG.rst"
38    changelog_lines = p.read_text(encoding="UTF-8").splitlines()
39
40    title_regex = re.compile(r"pytest (\d\.\d+\.\d+) \(\d{4}-\d{2}-\d{2}\)")
41    consuming_version = False
42    version_lines = []
43    for line in changelog_lines:
44        m = title_regex.match(line)
45        if m:
46            # found the version we want: start to consume lines until we find the next version title
47            if m.group(1) == tag_name:
48                consuming_version = True
49            # found a new version title while parsing the version we want: break out
50            elif consuming_version:
51                break
52        if consuming_version:
53            version_lines.append(line)
54
55    return "\n".join(version_lines)
56
57
58def convert_rst_to_md(text):
59    return pypandoc.convert_text(text, "md", format="rst")
60
61
62def main(argv):
63    if len(argv) > 1:
64        tag_name = argv[1]
65    else:
66        tag_name = os.environ.get("TRAVIS_TAG")
67        if not tag_name:
68            print("tag_name not given and $TRAVIS_TAG not set", file=sys.stderr)
69            return 1
70
71    token = os.environ.get("GH_RELEASE_NOTES_TOKEN")
72    if not token:
73        print("GH_RELEASE_NOTES_TOKEN not set", file=sys.stderr)
74        return 1
75
76    slug = os.environ.get("TRAVIS_REPO_SLUG")
77    if not slug:
78        print("TRAVIS_REPO_SLUG not set", file=sys.stderr)
79        return 1
80
81    rst_body = parse_changelog(tag_name)
82    md_body = convert_rst_to_md(rst_body)
83    if not publish_github_release(slug, token, tag_name, md_body):
84        print("Could not publish release notes:", file=sys.stderr)
85        print(md_body, file=sys.stderr)
86        return 5
87
88    print()
89    print(f"Release notes for {tag_name} published successfully:")
90    print(f"https://github.com/{slug}/releases/tag/{tag_name}")
91    print()
92    return 0
93
94
95if __name__ == "__main__":
96    sys.exit(main(sys.argv))
97