techglass-mint / tools /deploy_vercel.py
EHS-Studio's picture
Add the Vercel deploy script and share the zip builder
58bf71d verified
Raw History Blame Contribute Delete
3.26 kB
#!/usr/bin/env python3
"""Deploy the website (and the download zip) to Vercel as a production deployment.
Only uses the standard library. The token comes from $VERCEL_TOKEN or from
~/Dokumente/tokens/vercel token, and is only ever sent in the Authorization header.
Usage: python3 tools/deploy_vercel.py
"""
import hashlib
import json
import os
import re
import sys
import tempfile
import time
import urllib.error
import urllib.request
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parent))
from deploy_space import ROOT, build_zip # noqa: E402
PROJECT = "techglass-mint"
API = "https://api.vercel.com"
SITE = ["index.html", "icon.svg", "assets"]
def token():
if os.environ.get("VERCEL_TOKEN"):
return os.environ["VERCEL_TOKEN"]
text = (Path.home() / "Dokumente/tokens/vercel token").read_text()
return max(re.findall(r"[A-Za-z0-9_\-]{20,}", text), key=len)
def call(method, path, body=None, headers=None):
h = {"Authorization": f"Bearer {token()}", **(headers or {})}
data = body
if body is not None and not isinstance(body, bytes):
data = json.dumps(body).encode()
h["Content-Type"] = "application/json"
req = urllib.request.Request(API + path, data=data, method=method, headers=h)
try:
with urllib.request.urlopen(req, timeout=180) as r:
text = r.read().decode()
except urllib.error.HTTPError as e:
sys.exit(f"Vercel answered {e.code} for {path}: {e.read().decode()[:400]}")
return json.loads(text) if text.strip() else {}
def upload_files():
entries = []
with tempfile.TemporaryDirectory() as tmp:
zip_path = Path(tmp) / "techglass-mint.zip"
build_zip(zip_path)
items = []
for name in SITE:
src = ROOT / name
for p in ([src] if src.is_file() else sorted(src.rglob("*"))):
if p.is_file():
items.append((p, str(p.relative_to(ROOT))))
items.append((zip_path, "techglass-mint.zip"))
for path, rel in items:
data = path.read_bytes()
sha = hashlib.sha1(data).hexdigest()
call("POST", "/v2/files", data, {"Content-Type": "application/octet-stream",
"x-vercel-digest": sha, "Content-Length": str(len(data))})
entries.append({"file": rel, "sha": sha, "size": len(data)})
return entries
def main():
files = upload_files()
print(f"Uploaded {len(files)} files")
dep = call("POST", "/v13/deployments?skipAutoDetectionConfirmation=1", {
"name": PROJECT,
"files": files,
"target": "production",
"projectSettings": {"framework": None, "buildCommand": None, "installCommand": None,
"outputDirectory": None, "devCommand": None},
})
for _ in range(90):
state = call("GET", f"/v13/deployments/{dep['id']}")
if state.get("readyState") in ("READY", "ERROR", "CANCELED"):
break
time.sleep(2)
print("State:", state.get("readyState"))
print("Deployment:", "https://" + state.get("url", ""))
for alias in state.get("alias", []):
print("Alias:", "https://" + alias)
if __name__ == "__main__":
main()