diff options
| -rw-r--r-- | static-builds/README.md | 24 | ||||
| -rw-r--r-- | static-builds/netlify_build.py | 125 | 
2 files changed, 45 insertions, 104 deletions
| diff --git a/static-builds/README.md b/static-builds/README.md index 9b86ed08..a3c7962b 100644 --- a/static-builds/README.md +++ b/static-builds/README.md @@ -27,16 +27,29 @@ Alternatively, you can use the [Dockerfile](/Dockerfile) and extract the build.  Both output their builds to a `build/` directory.  ### Deploying To Netlify -To deploy to netlify, link your site GitHub repository to a netlify site, and use the following settings: +To deploy to netlify, link your site GitHub repository to a netlify site, and use the settings below. +The netlify build script uses the site API to fetch and download the artifact, using a GitHub app that +can access the repo. The app must have the `actions` and `artifacts` scopes enabled. +### Netlify Settings  Build Command: -`python -m pip install httpx==0.19.0 && python static-builds/netlify_build.py` +`python -m pip install httpx==0.23.0 && python static-builds/netlify_build.py`  Publish Directory:  `build` -Environment Variables: -- PYTHON_VERSION: 3.8 +**Environment Variables** + +| Name           | Value                          | Description                                                                               | +|----------------|--------------------------------|-------------------------------------------------------------------------------------------| +| PYTHON_VERSION | 3.8                            | The python version. Supported options are defined by netlify [here][netlify build image]. | +| API_URL        | https://pythondiscord.com/     | The link to the API, which will be used to fetch the build artifacts.                     | +| ACTION_NAME    | Build & Publish Static Preview | The name of the workflow which will be used to find the artifact.                         | +| ARTIFACT_NAME  | static-build                   | The name of the artifact to download.                                                     | + + +[netlify build image]: https://github.com/netlify/build-image/tree/focal +  Note that at this time, if you are deploying to netlify yourself, you won't have access to the @@ -45,6 +58,3 @@ You can either update the pack to one which will work on your domain, or you'll  > Warning: If you are modifying the [build script](./netlify_build.py), make sure it is compatible with Python 3.8. - -Note: The build script uses [nightly.link](https://github.com/oprypin/nightly.link) -to fetch the artifact with no authentication. diff --git a/static-builds/netlify_build.py b/static-builds/netlify_build.py index 4e1e6106..13cd0279 100644 --- a/static-builds/netlify_build.py +++ b/static-builds/netlify_build.py @@ -4,106 +4,42 @@  # This script performs all the actions required to build and deploy our project on netlify  # It depends on the following packages, which are set in the netlify UI: -# httpx == 0.19.0 +# httpx == 0.23.0 +import json  import os -import time -import typing  import zipfile  from pathlib import Path  from urllib import parse  import httpx -API_URL = "https://api.github.com" -NIGHTLY_URL = "https://nightly.link" -OWNER, REPO = parse.urlparse(os.getenv("REPOSITORY_URL")).path.lstrip("/").split("/")[0:2] - - -def get_build_artifact() -> typing.Tuple[int, str]: -    """ -    Search for a build artifact, and return the result. - -    The return is a tuple of the check suite ID, and the URL to the artifacts. -    """ -    print("Fetching build URL.") - -    if os.getenv("PULL_REQUEST").lower() == "true": -        print(f"Fetching data for PR #{os.getenv('REVIEW_ID')}") - -        pull_url = f"{API_URL}/repos/{OWNER}/{REPO}/pulls/{os.getenv('REVIEW_ID')}" -        pull_request = httpx.get(pull_url) -        pull_request.raise_for_status() - -        commit_sha = pull_request.json()["head"]["sha"] - -        workflows_params = parse.urlencode({ -            "event": "pull_request", -            "per_page": 100 -        }) - -    else: -        commit_sha = os.getenv("COMMIT_REF") - -        workflows_params = parse.urlencode({ -            "event": "push", -            "per_page": 100 -        }) - -    print(f"Fetching action data for commit {commit_sha}") - -    workflows = httpx.get(f"{API_URL}/repos/{OWNER}/{REPO}/actions/runs?{workflows_params}") -    workflows.raise_for_status() - -    for run in workflows.json()["workflow_runs"]: -        if run["name"] == "Build & Publish Static Preview" and commit_sha == run["head_sha"]: -            print(f"Found action for this commit: {run['id']}\n{run['html_url']}") -            break -    else: -        raise Exception("Could not find the workflow run for this event.") - -    polls = 0 -    while polls <= 20: -        if run["status"] != "completed": -            print("Action isn't ready, sleeping for 10 seconds.") -            polls += 1 -            time.sleep(10) - -        elif run["conclusion"] != "success": -            print("Aborting build due to a failure in a previous CI step.") -            exit(0) - -        else: -            print(f"Found artifact URL:\n{run['artifacts_url']}") -            return run["check_suite_id"], run["artifacts_url"] - -        _run = httpx.get(run["url"]) -        _run.raise_for_status() -        run = _run.json() - -    raise Exception("Polled for the artifact workflow, but it was not ready in time.") - - -def download_artifact(suite_id: int, url: str) -> None: -    """Download a build artifact from `url`, and unzip the content.""" -    print("Fetching artifact data.") - -    artifacts = httpx.get(url) -    artifacts.raise_for_status() -    artifacts = artifacts.json() - -    if artifacts["total_count"] == "0": -        raise Exception(f"No artifacts were found for this build, aborting.\n{url}") - -    for artifact in artifacts["artifacts"]: -        if artifact["name"] == "static-build": -            print("Found artifact with build.") -            break -    else: -        raise Exception("Could not find an artifact with the expected name.") - -    artifact_url = f"{NIGHTLY_URL}/{OWNER}/{REPO}/suites/{suite_id}/artifacts/{artifact['id']}" -    zipped_content = httpx.get(artifact_url) +if __name__ == "__main__": +    owner, repo = parse.urlparse(os.getenv("REPOSITORY_URL")).path.lstrip("/").split("/")[0:2] + +    download_url = "/".join([ +        os.getenv("API_URL").rstrip("/"), +        "api/github/artifact", +        owner, +        repo, +        os.getenv("COMMIT_REF"), +        parse.quote(os.getenv("ACTION_NAME")), +        os.getenv("ARTIFACT_NAME"), +    ]) +    print(f"Fetching download URL from {download_url}") +    response = httpx.get(download_url, follow_redirects=True) + +    if response.status_code != 200: +        try: +            print(response.json()) +        except json.JSONDecodeError: +            pass + +        response.raise_for_status() + +    url = response.json()["url"] +    print(f"Downloading build from {url}") +    zipped_content = httpx.get(url, follow_redirects=True)      zipped_content.raise_for_status()      zip_file = Path("temp.zip") @@ -115,8 +51,3 @@ def download_artifact(suite_id: int, url: str) -> None:      zip_file.unlink(missing_ok=True)      print("Wrote artifact content to target directory.") - - -if __name__ == "__main__": -    print("Build started") -    download_artifact(*get_build_artifact()) | 
