diff --git a/.travis.yml b/.travis.yml index abcbfbac5..2d6883f48 100644 --- a/.travis.yml +++ b/.travis.yml @@ -99,8 +99,17 @@ jobs: - stage: deploy python: '3.6' - install: pip install -U setuptools setuptools_scm + install: pip install -U setuptools setuptools_scm tox script: skip + # token to upload github release notes: GH_RELEASE_NOTES_TOKEN + env: + - secure: "OjOeL7/0JUDkV00SsTs732e8vQjHynpbG9FKTNtZZJ+1Zn4Cib+hAlwmlBnvVukML0X60YpcfjnC4quDOIGLPsh5zeXnvJmYtAIIUNQXjWz8NhcGYrhyzuP1rqV22U68RTCdmOq3lMYU/W2acwHP7T49PwJtOiUM5kF120UAQ0Zi5EmkqkIvH8oM5mO9Dlver+/U7Htpz9rhKrHBXQNCMZI6yj2aUyukqB2PN2fjAlDbCF//+FmvYw9NjT4GeFOSkTCf4ER9yfqs7yglRfwiLtOCZ2qKQhWZNsSJDB89rxIRXWavJUjJKeY2EW2/NkomYJDpqJLIF4JeFRw/HhA47CYPeo6BJqyyNV+0CovL1frpWfi9UQw2cMbgFUkUIUk3F6DD59PHNIOX2R/HX56dQsw7WKl3QuHlCOkICXYg8F7Ta684IoKjeTX03/6QNOkURfDBwfGszY0FpbxrjCSWKom6RyZdyidnESaxv9RzjcIRZVh1rp8KMrwS1OrwRSdG0zjlsPr49hWMenN/8fKgcHTV4/r1Tj6mip0dorSRCrgUNIeRBKgmui6FS8642ab5JNKOxMteVPVR2sFuhjOQ0Jy+PmvceYY9ZMWc3+/B/KVh0dZ3hwvLGZep/vxDS2PwCA5/xw31714vT5LxidKo8yECjBynMU/wUTTS695D3NY=" + addons: + apt: + packages: + # required by publish_gh_release_notes + - pandoc + after_deploy: tox -e publish_gh_release_notes deploy: provider: pypi user: nicoddemus diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 8e50486de..d33a9e09b 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -91,7 +91,7 @@ jobs: condition: eq(variables['python.needs_vc'], True) displayName: 'Install VC for py27' - - script: python -m pip install --upgrade pip && python -m pip install tox + - script: python -m pip install tox displayName: 'Install tox' - script: | diff --git a/scripts/publish_gh_release_notes.py b/scripts/publish_gh_release_notes.py new file mode 100644 index 000000000..3ff946b58 --- /dev/null +++ b/scripts/publish_gh_release_notes.py @@ -0,0 +1,96 @@ +# -*- coding: utf-8 -*- +""" +Script used to publish GitHub release notes extracted from CHANGELOG.rst. + +This script is meant to be executed after a successful deployment in Travis. + +Uses the following environment variables: + +* GIT_TAG: the name of the tag of the current commit. +* GH_RELEASE_NOTES_TOKEN: a personal access token with 'repo' permissions. It should be encrypted using: + + $travis encrypt GH_RELEASE_NOTES_TOKEN= -r pytest-dev/pytest + + And the contents pasted in the ``deploy.env.secure`` section in the ``travis.yml`` file. + +The script also requires ``pandoc`` to be previously installed in the system. + +Requires Python3.6+. +""" +import os +import re +import sys +from pathlib import Path + +import github3 +import pypandoc + + +def publish_github_release(slug, token, tag_name, body): + github = github3.login(token=token) + owner, repo = slug.split("/") + repo = github.repository(owner, repo) + return repo.create_release(tag_name=tag_name, body=body) + + +def parse_changelog(tag_name): + p = Path(__file__).parent.parent / "CHANGELOG.rst" + changelog_lines = p.read_text(encoding="UTF-8").splitlines() + + title_regex = re.compile(r"pytest (\d\.\d+\.\d+) \(\d{4}-\d{2}-\d{2}\)") + consuming_version = False + version_lines = [] + for line in changelog_lines: + m = title_regex.match(line) + if m: + # found the version we want: start to consume lines until we find the next version title + if m.group(1) == tag_name: + consuming_version = True + # found a new version title while parsing the version we want: break out + elif consuming_version: + break + if consuming_version: + version_lines.append(line) + + return "\n".join(version_lines) + + +def convert_rst_to_md(text): + return pypandoc.convert_text(text, "md", format="rst") + + +def main(argv): + if len(argv) > 1: + tag_name = argv[1] + else: + tag_name = os.environ.get("TRAVIS_TAG") + if not tag_name: + print("tag_name not given and $TRAVIS_TAG not set", file=sys.stderr) + return 1 + + token = os.environ.get("GH_RELEASE_NOTES_TOKEN") + if not token: + print("GH_RELEASE_NOTES_TOKEN not set", file=sys.stderr) + return 1 + + slug = os.environ.get("TRAVIS_REPO_SLUG") + if not slug: + print("TRAVIS_REPO_SLUG not set", file=sys.stderr) + return 1 + + rst_body = parse_changelog(tag_name) + md_body = convert_rst_to_md(rst_body) + if not publish_github_release(slug, token, tag_name, md_body): + print("Could not publish release notes:", file=sys.stderr) + print(md_body, file=sys.stderr) + return 5 + + print() + print(f"Release notes for {tag_name} published successfully:") + print(f"https://github.com/{slug}/releases/tag/{tag_name}") + print() + return 0 + + +if __name__ == "__main__": + sys.exit(main(sys.argv)) diff --git a/tox.ini b/tox.ini index 0b1be0d33..ab9f581f7 100644 --- a/tox.ini +++ b/tox.ini @@ -136,6 +136,17 @@ deps = wheel commands = python scripts/release.py {posargs} +[testenv:publish_gh_release_notes] +description = create GitHub release after deployment +basepython = python3.6 +usedevelop = True +passenv = GH_RELEASE_NOTES_TOKEN TRAVIS_TAG TRAVIS_REPO_SLUG +deps = + github3.py + pypandoc +commands = python scripts/publish_gh_release_notes.py + + [pytest] minversion = 2.0 addopts = -ra -p pytester --strict-markers