WAI toolchain decision 11: joule-moq-relay builds wai-relay, joule-moq-room wai-room, and joule-moq-ingest wai-ingest. wai dev finds them by those names (WAI_RELAY_BIN, WAI_ROOM_BIN), and the quickstart archive, the release workflow, the examples' workflow, the browser tests, the interop scripts, the example host script, the Scoop manifest and the crates' READMEs and example configurations name them so. Wire and record identifiers that carry a crate's name (joule-moq-relay/session-summary/2, joule-moq-ingest/session/1, the relay's MOQT implementation string) and the log variables (JOULE_MOQ_*_LOG) are unchanged. Co-Authored-By: Claude Opus 5.5 <[email protected]>
101 lines
3.5 KiB
Python
101 lines
3.5 KiB
Python
"""The package managers' entries for a release of the WAI command line, from the SHA-256 files
|
|
attached to it:
|
|
|
|
python3 wai/quickstart/formulae.py <version> <tag> <forge-api> <owner/repo> <public-url> <out-dir>
|
|
|
|
Writes <out-dir>/wai.rb (a Homebrew formula for macOS and Linux) and <out-dir>/wai.json (a
|
|
Scoop manifest for Windows). A platform whose archive is not attached is left out, and stderr
|
|
says so; with none at all, it fails. Each archive holds bin/ and share/wai/web/, kept side by
|
|
side as `wai dev` expects them.
|
|
"""
|
|
|
|
import json
|
|
import os
|
|
import pathlib
|
|
import sys
|
|
import urllib.request
|
|
|
|
version, tag, api, repo, public, out = sys.argv[1:7]
|
|
token = os.environ.get("FORGE_TOKEN", "")
|
|
headers = {"User-Agent": "wai-release"}
|
|
if token:
|
|
headers["Authorization"] = f"token {token}"
|
|
web = api.rsplit("/api/v1", 1)[0]
|
|
|
|
|
|
def get(url):
|
|
with urllib.request.urlopen(urllib.request.Request(url, headers=headers), timeout=60) as r:
|
|
return r.read()
|
|
|
|
|
|
release = json.loads(get(f"{api}/repos/{repo}/releases/tags/{tag}"))
|
|
assets = {a["name"]: a for a in release.get("assets", [])}
|
|
|
|
|
|
def digest(archive):
|
|
if archive not in assets or archive + ".sha256" not in assets:
|
|
print(f"note: {archive} is not attached; left out", file=sys.stderr)
|
|
return None
|
|
return get(f"{web}/{repo}/releases/download/{tag}/{archive}.sha256").decode().split()[0]
|
|
|
|
|
|
def url(archive):
|
|
return f"{public}/releases/download/{tag}/{archive}"
|
|
|
|
|
|
DESC = "WAI, an open media standard: its command line, and a local relay and room service"
|
|
HOME = "https://wai.transaction.science/docs/quickstart/"
|
|
targets = {
|
|
("macos", "arm"): "aarch64-apple-darwin",
|
|
("macos", "intel"): "x86_64-apple-darwin",
|
|
("linux", "arm"): "aarch64-unknown-linux-musl",
|
|
("linux", "intel"): "x86_64-unknown-linux-musl",
|
|
}
|
|
blocks = {}
|
|
for (os_name, cpu), triple in targets.items():
|
|
archive = f"wai-{version}-{triple}.tar.gz"
|
|
sha = digest(archive)
|
|
if sha:
|
|
blocks.setdefault(os_name, []).append(f' on_{cpu} do\n url "{url(archive)}"\n sha256 "{sha}"\n end\n')
|
|
win = f"wai-{version}-x86_64-pc-windows-msvc"
|
|
win_sha = digest(win + ".zip")
|
|
if not blocks and not win_sha:
|
|
sys.exit("no archive is attached to the release")
|
|
|
|
formula = f'''class Wai < Formula
|
|
desc "{DESC}"
|
|
homepage "{HOME}"
|
|
version "{version}"
|
|
license "Apache-2.0"
|
|
'''
|
|
for os_name in ("macos", "linux"):
|
|
if os_name in blocks:
|
|
formula += f" on_{os_name} do\n" + "".join(blocks[os_name]) + " end\n"
|
|
formula += '''
|
|
def install
|
|
# bin/ and share/wai/web/ side by side: `wai dev` finds the relay, the room service and the
|
|
# room client beside its own binary.
|
|
bin.install Dir["bin/*"]
|
|
(share/"wai").install "share/wai/web"
|
|
end
|
|
|
|
test do
|
|
assert_match "video-room", shell_output("#{bin}/wai create --list")
|
|
assert_match "delivered-verified", shell_output("#{bin}/wai hello #{testpath}/hello")
|
|
assert_match "verified", shell_output("#{bin}/wai verify #{testpath}/hello")
|
|
end
|
|
end
|
|
'''
|
|
pathlib.Path(out, "wai.rb").write_text(formula)
|
|
|
|
if win_sha:
|
|
manifest = {
|
|
"version": version,
|
|
"description": DESC,
|
|
"homepage": HOME,
|
|
"license": "Apache-2.0",
|
|
"architecture": {"64bit": {"url": url(win + ".zip"), "hash": win_sha, "extract_dir": win}},
|
|
"bin": ["bin\\wai.exe", "bin\\wai-relay.exe", "bin\\wai-room.exe", "bin\\wai-remote-host.exe", "bin\\wai-pack.exe"],
|
|
}
|
|
pathlib.Path(out, "wai.json").write_text(json.dumps(manifest, indent=2) + "\n")
|
|
print(f"wrote the formula{' and the manifest' if win_sha else ''} for wai {version}")
|