From c7dd9de42ff93d94757a339fe3bf39dc42cd86f9 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 20 May 2017 14:37:40 -0700 Subject: Replace release automation with click (#3557) * Replace release automation with click * Fix * fix --- release.py | 149 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 release.py (limited to 'release.py') diff --git a/release.py b/release.py new file mode 100644 index 00000000..7e2c1d81 --- /dev/null +++ b/release.py @@ -0,0 +1,149 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +import getpass +import io +import os +import subprocess +import time + +import click + +from clint.textui.progress import Bar as ProgressBar + +import requests + + +JENKINS_URL = "https://jenkins.cryptography.io/job/cryptography-wheel-builder" + + +def run(*args, **kwargs): + kwargs.setdefault("stderr", subprocess.STDOUT) + subprocess.check_output(list(args), **kwargs) + + +def wait_for_build_completed(session): + # Wait 20 seconds before actually checking if the build is complete, to + # ensure that it had time to really start. + time.sleep(20) + while True: + response = session.get( + "{0}/lastBuild/api/json/".format(JENKINS_URL), + headers={ + "Accept": "application/json", + } + ) + response.raise_for_status() + if not response.json()["building"]: + assert response.json()["result"] == "SUCCESS" + break + time.sleep(0.1) + + +def download_artifacts(session): + response = session.get( + "{0}/lastBuild/api/json/".format(JENKINS_URL), + headers={ + "Accept": "application/json" + } + ) + response.raise_for_status() + assert not response.json()["building"] + assert response.json()["result"] == "SUCCESS" + + paths = [] + + last_build_number = response.json()["number"] + for run in response.json()["runs"]: + if run["number"] != last_build_number: + print( + "Skipping {0} as it is not from the latest build ({1})".format( + run["url"], last_build_number + ) + ) + continue + + response = session.get( + run["url"] + "api/json/", + headers={ + "Accept": "application/json", + } + ) + response.raise_for_status() + for artifact in response.json()["artifacts"]: + response = session.get( + "{0}artifact/{1}".format(run["url"], artifact["relativePath"]), + stream=True + ) + assert response.headers["content-length"] + print("Downloading {0}".format(artifact["fileName"])) + bar = ProgressBar( + expected_size=int(response.headers["content-length"]), + filled_char="=" + ) + content = io.BytesIO() + for data in response.iter_content(chunk_size=8192): + content.write(data) + bar.show(content.tell()) + assert bar.expected_size == content.tell() + bar.done() + out_path = os.path.join( + os.path.dirname(__file__), + "dist", + artifact["fileName"], + ) + with open(out_path, "wb") as f: + f.write(content.getvalue()) + paths.append(out_path) + return paths + + +@click.command() +@click.argument("version") +def release(version): + """ + ``version`` should be a string like '0.4' or '1.0'. + """ + run("git", "tag", "-s", version, "-m", "{0} release".format(version)) + run("git", "push", "--tags") + + run("python", "setup.py", "sdist") + run("python", "setup.py", "sdist", "bdist_wheel", cwd="vectors/") + + run( + "twine", "upload", "-s", "dist/cryptography-{0}*".format(version), + "vectors/dist/cryptography_vectors-{0}*".format(version), shell=True + ) + + session = requests.Session() + + # This tells the CDN to delete the cached response for the URL. We do this + # so that the Jenkins builders will see the new sdist immediately when they + # go to build the wheels. + response = session.request( + "PURGE", "https://pypi.python.org/simple/cryptography/" + ) + response.raise_for_status() + + username = getpass.getpass("Input the GitHub/Jenkins username: ") + token = getpass.getpass("Input the Jenkins token: ") + response = session.post( + "{0}/build".format(JENKINS_URL), + auth=requests.auth.HTTPBasicAuth( + username, token + ), + params={ + "cause": "Building wheels for {0}".format(version) + } + ) + response.raise_for_status() + wait_for_build_completed(session) + paths = download_artifacts(session) + run("twine", "upload", " ".join(paths)) + + +if __name__ == "__main__": + release() -- cgit v1.2.3