Skip to content

Commit 0404e00

Browse files
Update Netlify Build Script
Update the netlify build script to use the artifacts API from the site. Signed-off-by: Hassan Abouelela <[email protected]>
1 parent fe4def7 commit 0404e00

File tree

2 files changed

+45
-104
lines changed

2 files changed

+45
-104
lines changed

static-builds/README.md

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,29 @@ Alternatively, you can use the [Dockerfile](/Dockerfile) and extract the build.
2727
Both output their builds to a `build/` directory.
2828

2929
### Deploying To Netlify
30-
To deploy to netlify, link your site GitHub repository to a netlify site, and use the following settings:
30+
To deploy to netlify, link your site GitHub repository to a netlify site, and use the settings below.
31+
The netlify build script uses the site API to fetch and download the artifact, using a GitHub app that
32+
can access the repo. The app must have the `actions` and `artifacts` scopes enabled.
3133

34+
### Netlify Settings
3235
Build Command:
33-
`python -m pip install httpx==0.19.0 && python static-builds/netlify_build.py`
36+
`python -m pip install httpx==0.23.0 && python static-builds/netlify_build.py`
3437

3538
Publish Directory:
3639
`build`
3740

38-
Environment Variables:
39-
- PYTHON_VERSION: 3.8
41+
**Environment Variables**
42+
43+
| Name | Value | Description |
44+
|----------------|--------------------------------|-------------------------------------------------------------------------------------------|
45+
| PYTHON_VERSION | 3.8 | The python version. Supported options are defined by netlify [here][netlify build image]. |
46+
| API_URL | https://pythondiscord.com/ | The link to the API, which will be used to fetch the build artifacts. |
47+
| ACTION_NAME | Build & Publish Static Preview | The name of the workflow which will be used to find the artifact. |
48+
| ARTIFACT_NAME | static-build | The name of the artifact to download. |
49+
50+
51+
[netlify build image]: https://github.com/netlify/build-image/tree/focal
52+
4053

4154

4255
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
4558

4659

4760
> Warning: If you are modifying the [build script](./netlify_build.py), make sure it is compatible with Python 3.8.
48-
49-
Note: The build script uses [nightly.link](https://github.com/oprypin/nightly.link)
50-
to fetch the artifact with no authentication.

static-builds/netlify_build.py

Lines changed: 28 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -4,106 +4,42 @@
44

55
# This script performs all the actions required to build and deploy our project on netlify
66
# It depends on the following packages, which are set in the netlify UI:
7-
# httpx == 0.19.0
7+
# httpx == 0.23.0
88

9+
import json
910
import os
10-
import time
11-
import typing
1211
import zipfile
1312
from pathlib import Path
1413
from urllib import parse
1514

1615
import httpx
1716

18-
API_URL = "https://api.github.com"
19-
NIGHTLY_URL = "https://nightly.link"
20-
OWNER, REPO = parse.urlparse(os.getenv("REPOSITORY_URL")).path.lstrip("/").split("/")[0:2]
21-
22-
23-
def get_build_artifact() -> typing.Tuple[int, str]:
24-
"""
25-
Search for a build artifact, and return the result.
26-
27-
The return is a tuple of the check suite ID, and the URL to the artifacts.
28-
"""
29-
print("Fetching build URL.")
30-
31-
if os.getenv("PULL_REQUEST").lower() == "true":
32-
print(f"Fetching data for PR #{os.getenv('REVIEW_ID')}")
33-
34-
pull_url = f"{API_URL}/repos/{OWNER}/{REPO}/pulls/{os.getenv('REVIEW_ID')}"
35-
pull_request = httpx.get(pull_url)
36-
pull_request.raise_for_status()
37-
38-
commit_sha = pull_request.json()["head"]["sha"]
39-
40-
workflows_params = parse.urlencode({
41-
"event": "pull_request",
42-
"per_page": 100
43-
})
44-
45-
else:
46-
commit_sha = os.getenv("COMMIT_REF")
47-
48-
workflows_params = parse.urlencode({
49-
"event": "push",
50-
"per_page": 100
51-
})
52-
53-
print(f"Fetching action data for commit {commit_sha}")
54-
55-
workflows = httpx.get(f"{API_URL}/repos/{OWNER}/{REPO}/actions/runs?{workflows_params}")
56-
workflows.raise_for_status()
57-
58-
for run in workflows.json()["workflow_runs"]:
59-
if run["name"] == "Build & Publish Static Preview" and commit_sha == run["head_sha"]:
60-
print(f"Found action for this commit: {run['id']}\n{run['html_url']}")
61-
break
62-
else:
63-
raise Exception("Could not find the workflow run for this event.")
64-
65-
polls = 0
66-
while polls <= 20:
67-
if run["status"] != "completed":
68-
print("Action isn't ready, sleeping for 10 seconds.")
69-
polls += 1
70-
time.sleep(10)
71-
72-
elif run["conclusion"] != "success":
73-
print("Aborting build due to a failure in a previous CI step.")
74-
exit(0)
75-
76-
else:
77-
print(f"Found artifact URL:\n{run['artifacts_url']}")
78-
return run["check_suite_id"], run["artifacts_url"]
79-
80-
_run = httpx.get(run["url"])
81-
_run.raise_for_status()
82-
run = _run.json()
83-
84-
raise Exception("Polled for the artifact workflow, but it was not ready in time.")
85-
86-
87-
def download_artifact(suite_id: int, url: str) -> None:
88-
"""Download a build artifact from `url`, and unzip the content."""
89-
print("Fetching artifact data.")
90-
91-
artifacts = httpx.get(url)
92-
artifacts.raise_for_status()
93-
artifacts = artifacts.json()
94-
95-
if artifacts["total_count"] == "0":
96-
raise Exception(f"No artifacts were found for this build, aborting.\n{url}")
97-
98-
for artifact in artifacts["artifacts"]:
99-
if artifact["name"] == "static-build":
100-
print("Found artifact with build.")
101-
break
102-
else:
103-
raise Exception("Could not find an artifact with the expected name.")
104-
105-
artifact_url = f"{NIGHTLY_URL}/{OWNER}/{REPO}/suites/{suite_id}/artifacts/{artifact['id']}"
106-
zipped_content = httpx.get(artifact_url)
17+
if __name__ == "__main__":
18+
owner, repo = parse.urlparse(os.getenv("REPOSITORY_URL")).path.lstrip("/").split("/")[0:2]
19+
20+
download_url = "/".join([
21+
os.getenv("API_URL").rstrip("/"),
22+
"api/github/artifact",
23+
owner,
24+
repo,
25+
os.getenv("COMMIT_REF"),
26+
parse.quote(os.getenv("ACTION_NAME")),
27+
os.getenv("ARTIFACT_NAME"),
28+
])
29+
print(f"Fetching download URL from {download_url}")
30+
response = httpx.get(download_url, follow_redirects=True)
31+
32+
if response.status_code != 200:
33+
try:
34+
print(response.json())
35+
except json.JSONDecodeError:
36+
pass
37+
38+
response.raise_for_status()
39+
40+
url = response.json()["url"]
41+
print(f"Downloading build from {url}")
42+
zipped_content = httpx.get(url, follow_redirects=True)
10743
zipped_content.raise_for_status()
10844

10945
zip_file = Path("temp.zip")
@@ -115,8 +51,3 @@ def download_artifact(suite_id: int, url: str) -> None:
11551
zip_file.unlink(missing_ok=True)
11652

11753
print("Wrote artifact content to target directory.")
118-
119-
120-
if __name__ == "__main__":
121-
print("Build started")
122-
download_artifact(*get_build_artifact())

0 commit comments

Comments
 (0)