From f21a422646606b5f5bebfd46d132ba6020e6ba2a Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sat, 31 Dec 2022 10:53:40 +0700 Subject: [PATCH] automatically download and upload circleci wheels --- release.py | 107 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 106 insertions(+), 1 deletion(-) diff --git a/release.py b/release.py index 5046daff1e6c..52cd30a224d7 100644 --- a/release.py +++ b/release.py @@ -95,6 +95,102 @@ def fetch_github_actions_artifacts(token, version): return download_artifacts_github_actions(session, token, run_url) +def wait_for_build_complete_circleci(session, token, pipeline_id): + while True: + response = session.get( + f"https://circleci.com/api/v2/pipeline/{pipeline_id}/workflow", + headers={ + "Circle-Token": token, + }, + ) + response.raise_for_status() + if response.json()["status"] == "success": + break + time.sleep(3) + + +def download_artifacts_circleci(session, urls): + paths = [] + for url in urls: + name = url.split("/")[-1] + response = session.get( + url, + headers={}, + ) + out_path = os.path.join( + os.path.dirname(__file__), + "dist", + os.path.basename(name), + ) + with open(out_path, "wb") as f: + f.write(response.content) + paths.append(out_path) + return paths + + +def fetch_circleci_artifacts(token, version): + session = requests.Session() + + response = session.get( + "https://circleci.com/api/v2/pipeline?org-slug=gh/pyca", + headers={"Circle-Token": token}, + ) + response.raise_for_status() + pipeline_id = None + for item in response.json()["items"]: + if item["project_slug"] == "gh/pyca/cryptography": + if item["vcs"].get("tag", None) == version: + pipeline_id = item["id"] + break + + if pipeline_id is None: + raise ValueError( + "Could not find a pipeline for version {0}".format(version) + ) + + wait_for_build_complete_circleci(session, token, pipeline_id) + urls = fetch_circleci_artifact_urls(session, token, item["id"]) + return download_artifacts_circleci(session, urls) + + +def fetch_circleci_artifact_urls(session, token, pipeline_id): + response = session.get( + f"https://circleci.com/api/v2/pipeline/{pipeline_id}/workflow", + headers={"Circle-Token": token}, + ) + response.raise_for_status() + workflow_id = response.json()["items"][0]["id"] + job_response = session.get( + f"https://circleci.com/api/v2/workflow/{workflow_id}/job", + headers={"Circle-Token": token}, + ) + job_response.raise_for_status() + artifact_urls = [] + for job in job_response.json()["items"]: + urls = fetch_circleci_artifact_url_from_job( + session, token, job["job_number"] + ) + artifact_urls.extend(urls) + + return artifact_urls + + +def fetch_circleci_artifact_url_from_job(session, token, job): + response = session.get( + f"https://circleci.com/api/v2/project/gh/pyca/cryptography/" + f"{job}/artifacts", + headers={"Circle-Token": token}, + ) + response.raise_for_status() + urls = [] + for item in response.json()["items"]: + url = item.get("url", None) + if url is not None: + urls.append(url) + + return urls + + @click.command() @click.argument("version") def release(version): @@ -106,7 +202,12 @@ def release(version): f"https://github.com/settings/tokens/new?" f"description={version}&scopes=repo" ) + print( + "Get a CircleCI token at: " + "https://app.circleci.com/settings/user/tokens" + ) github_token = getpass.getpass("Github person access token: ") + circle_token = getpass.getpass("CircleCI token: ") # Tag and push the tag (this will trigger the wheel builder in Actions) run("git", "tag", "-s", version, "-m", "{0} release".format(version)) @@ -116,9 +217,13 @@ def release(version): github_actions_artifact_paths = fetch_github_actions_artifacts( github_token, version ) + # Download wheels from CircleCI + circle_artifact_paths = fetch_circleci_artifacts(circle_token, version) + + artifact_paths = github_actions_artifact_paths + circle_artifact_paths # Upload wheels and sdist - run("twine", "upload", *github_actions_artifact_paths) + run("twine", "upload", *artifact_paths) if __name__ == "__main__":