Files
Artemis-Plugins/scripts/build_cua_driver.py
T

122 lines
4.1 KiB
Python

"""Build a self-contained Windows plugin from a hash-pinned Cua release."""
import argparse
import hashlib
import json
import os
import re
import subprocess
import urllib.request
import zipfile
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
SOURCE = ROOT / "plugins/cua-driver"
UPSTREAM_VERSION = "0.36.0"
COMMIT = "6d6c734c127025fb39ad5d585a10382808b39dc1"
DIGEST = "f8c47024b626f4e0e70f8428d2998df39e4879110c5722a29d5fd03e367353ad"
URL = "https://github.com/trycua/cua/releases/download/cua-driver-rs-v0.36.0/cua-driver-rs-0.36.0-windows-x86_64-binary.zip"
def main():
parser = argparse.ArgumentParser(__doc__)
parser.add_argument("upstream_zip", type=Path)
parser.add_argument("--go", default="go")
parser.add_argument("--output", type=Path, default=ROOT / "artifacts")
args = parser.parse_args()
version = json.loads((SOURCE / "plugin.json").read_text("utf-8"))["version"]
if version.split("+", 1)[0] != UPSTREAM_VERSION:
raise ValueError("Plugin version must match the pinned Cua Driver version")
match = re.search(
r'const adapterVersion = "([^"]+)"', (SOURCE / "main.go").read_text("utf-8")
)
if not match or match[1] != version:
raise ValueError("Adapter MCP version must match plugin.json")
if hashlib.sha256(args.upstream_zip.read_bytes()).hexdigest() != DIGEST:
raise ValueError("Cua release archive hash mismatch")
output = args.output.resolve()
output.mkdir(parents=True, exist_ok=True)
adapter = output / "artemis-cua-adapter.exe"
env = {
**os.environ,
"CGO_ENABLED": "0",
"GOOS": "windows",
"GOARCH": "amd64",
"GOTOOLCHAIN": "local",
}
for command in (
[args.go, "test", "./..."],
[
args.go,
"build",
"-trimpath",
"-buildvcs=false",
"-ldflags=-s -w",
"-o",
str(adapter),
".",
],
):
subprocess.run(command, cwd=SOURCE, env=env, check=True, timeout=180)
license_file = SOURCE / "LICENSE.upstream"
if not license_file.exists():
with urllib.request.urlopen(
f"https://raw.githubusercontent.com/trycua/cua/{COMMIT}/LICENSE.md",
timeout=30,
) as response:
license_file.write_bytes(response.read())
target = output / f"cua-driver-{version}-windows-amd64.zip"
with (
zipfile.ZipFile(target, "w", zipfile.ZIP_DEFLATED) as dest,
zipfile.ZipFile(args.upstream_zip) as upstream,
):
for name in (
"plugin.json",
"SKILL.md",
"LICENSE.upstream",
"RELEASE.md",
"VERIFICATION.md",
):
dest.write(SOURCE / name, name)
for source in sorted(SOURCE.glob("*.go")):
dest.write(source, f"source/{source.name}")
for name in ("go.mod", "tools.json"):
dest.write(SOURCE / name, f"source/{name}")
dest.write(adapter, "bin/artemis-cua-adapter.exe")
for name in upstream.namelist():
# Only the release's executable runtime; no global installer/hooks.
if Path(name).name in {
"cua-driver.exe",
"cua-driver-uia.exe",
"cua-cursor-theme.exe",
"cua_driver_sdk.dll",
}:
dest.writestr(f"bin/{Path(name).name}", upstream.read(name))
dest.writestr(
"provenance.json",
json.dumps(
{
"source_commit": COMMIT,
"upstream_version": UPSTREAM_VERSION,
"plugin_version": version,
"adapter_revision": 3,
"prerelease": True,
"url": URL,
"sha256": DIGEST,
},
indent=2,
),
)
print(
json.dumps(
{
"archive": str(target),
"sha256": hashlib.sha256(target.read_bytes()).hexdigest(),
}
)
)
if __name__ == "__main__":
main()