"""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 Writes /wai.rb (a Homebrew formula for macOS and Linux) and /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/, the room client, and studio/, WAI Studio), kept side by side as `wai dev` expects them. Both install every binary of the archive but wai-quantum, and depend on wai-quantum's own formula and manifest (wai/wai-quantum-cli/release/formulae.py) instead: the archive carries it for install.sh, while a package manager that installed it twice, once in each package, would have two packages claim one command (Homebrew refuses the second link, and Scoop's two shims overwrite each other). wai/quickstart/test/formulae_test.py holds this to build.sh. """ 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" # The archive's binaries the two install (build.sh packs these and wai-quantum). BINS = ["wai", "wai-relay", "wai-room", "wai-ingest", "wai-remote-host", "wai-pack"] # wai-quantum's own formula, in this tap, and its own manifest, in this bucket. QUANTUM_FORMULA = "transaction-science/tap/wai-quantum" QUANTUM_MANIFEST = "wai-quantum" 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" installs = ", ".join(f'"bin/{b}"' for b in BINS) formula += f''' # The quantum command line is a formula of its own: one copy, whichever is installed first. depends_on "{QUANTUM_FORMULA}" def install # bin/ and share/wai/ side by side: `wai dev` finds the relay, the room service, the room # client and WAI Studio beside its own binary. The archive's bin/wai-quantum is install.sh's; # here it is the dependency's. bin.install {installs} (share/"wai").install "share/wai/web", "share/wai/studio" end ''' formula += ''' 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}}, # The zip's bin\\wai-quantum.exe is left to the dependency's own manifest and shim. "depends": QUANTUM_MANIFEST, "bin": [f"bin\\{b}.exe" for b in BINS], } 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}")