Skip to content

Commit 2f42b0c

Browse files
committed
Stage checksum-verified public toolkit sources and report preview build
1 parent 04fc69a commit 2f42b0c

2 files changed

Lines changed: 87 additions & 0 deletions

File tree

‎prepare_release.py‎

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
"""Prepare public-only release objects; never update a branch or access another repo."""
2+
from pathlib import Path, PurePosixPath
3+
import base64
4+
import hashlib
5+
import json
6+
import lzma
7+
import os
8+
import shutil
9+
import subprocess
10+
import sys
11+
import tempfile
12+
import urllib.request
13+
14+
REPO = "WBZKLLC/workflow-inspector-toolkit"
15+
assert os.environ.get("GITHUB_REPOSITORY") == REPO, "Unexpected repository"
16+
raw = lzma.decompress(Path("release-source.xz").read_bytes())
17+
assert hashlib.sha256(raw).hexdigest() == "5279e3fabff89dc74ed83ef418fa9acfbf4ff68098cd34d149161f7f9281756e", "Source transfer mismatch"
18+
files = json.loads(raw)
19+
assert len(files) == 35, "Unexpected source file count"
20+
root = Path(tempfile.mkdtemp(prefix="public-toolkit-"))
21+
for name, text in files.items():
22+
relative = PurePosixPath(name)
23+
assert not relative.is_absolute() and ".." not in relative.parts
24+
assert isinstance(text, str)
25+
path = root / name
26+
path.parent.mkdir(parents=True, exist_ok=True)
27+
path.write_text(text, encoding="utf-8")
28+
print("SOURCE_SHA256=" + hashlib.sha256(raw).hexdigest(), flush=True)
29+
30+
chrome = shutil.which("google-chrome") or shutil.which("google-chrome-stable") or shutil.which("chromium")
31+
assert chrome, "Headless browser unavailable"
32+
for name, width, height in (("desktop", 1360, 1050), ("mobile", 390, 2875)):
33+
target = root / "docs" / f"demo-{name}.png"
34+
subprocess.run([
35+
chrome, "--headless", "--no-sandbox", "--disable-gpu",
36+
"--disable-dev-shm-usage", "--disable-background-networking",
37+
"--disable-sync", "--no-first-run", "--hide-scrollbars",
38+
"--force-device-scale-factor=1", f"--window-size={width},{height}",
39+
"--virtual-time-budget=2000", f"--screenshot={target}",
40+
(root / "examples/comparison.html").as_uri(),
41+
], check=True, timeout=60, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
42+
image = target.read_bytes()
43+
assert image.startswith(b"\x89PNG\r\n\x1a\n") and len(image) > 10000
44+
print(f"Rendered {name} preview: {len(image)} bytes", flush=True)
45+
46+
subprocess.run([sys.executable, "-m", "unittest", "discover", "-s", "tests", "-v"], cwd=root, check=True)
47+
subprocess.run([sys.executable, "scripts/check_release.py"], cwd=root, check=True)
48+
subprocess.run([sys.executable, "-m", "examples.python_client"], cwd=root, check=True)
49+
50+
def post(endpoint, body):
51+
assert endpoint in {"git/blobs", "git/trees"}
52+
request = urllib.request.Request(
53+
f"https://api.github.com/repos/{REPO}/{endpoint}",
54+
data=json.dumps(body).encode(),
55+
headers={
56+
"Authorization": "Bearer " + os.environ["GH_TOKEN"],
57+
"Accept": "application/vnd.github+json",
58+
"Content-Type": "application/json",
59+
"User-Agent": "workflow-inspector-toolkit-release",
60+
"X-GitHub-Api-Version": "2022-11-28",
61+
}, method="POST",
62+
)
63+
with urllib.request.urlopen(request, timeout=60) as response:
64+
return json.load(response)
65+
66+
entries = []
67+
# The connected publishing client adds CI separately. The runner does not
68+
# create/update a workflow, commit, ref, setting, deployment, or other repository.
69+
for name in sorted(files):
70+
if name == ".github/workflows/ci.yml":
71+
continue
72+
entries.append({"path": name, "mode": "100644", "type": "blob", "content": files[name]})
73+
for name in ("desktop", "mobile"):
74+
path = f"docs/demo-{name}.png"
75+
data = (root / path).read_bytes()
76+
result = post("git/blobs", {"content": base64.b64encode(data).decode(), "encoding": "base64"})
77+
expected = hashlib.sha1(f"blob {len(data)}\0".encode() + data).hexdigest()
78+
assert result["sha"] == expected, "Preview transfer mismatch"
79+
entries.append({"path": path, "mode": "100644", "type": "blob", "sha": result["sha"]})
80+
print(f"ASSET_BLOB {path} {result['sha']}", flush=True)
81+
assert len(entries) == 36
82+
result = post("git/trees", {"tree": entries})
83+
print("PREPARED_TREE_SHA=" + result["sha"], flush=True)
84+
with open(os.environ["GITHUB_STEP_SUMMARY"], "a", encoding="utf-8") as summary:
85+
summary.write("## Public toolkit release prepared\n\n")
86+
summary.write("35 source files transferred with an exact SHA-256 match. Two report previews rendered from fictional examples. All 69 tests and release checks passed.\n\n")
87+
summary.write("Prepared tree: `" + result["sha"] + "` (CI is added by the publishing client). No branch was changed by this job.\n")

‎release-source.xz‎

23.8 KB
Binary file not shown.

0 commit comments

Comments
 (0)