mirror of
https://github.com/openai/codex.git
synced 2026-09-11 20:36:49 +00:00
## What changed - Build, sign, and notarize `codex-voice-host` and its native runtime for Apple Silicon and Intel macOS release packages, granting the helper audio-input access. - Include voice resources in primary package archives and DMGs, with a root-level `codex` symlink to `bin/codex` so the runtime can be located. - Seal runtime receipts with post-signing hashes, require matching release versions and source builds, and bundle dependency notices, licenses, and source metadata. - Keep voice resources out of Python wheels to preserve their older macOS compatibility; the native voice build targets macOS 14. ## Testing Add packaging tests for alpha, beta, and stable versions, signed-byte preservation, license hashes, receipt validation, tamper detection, and exclusion of unlisted files. Extend release verification to check voice architectures, signatures, build identity, package hashes, and DMG contents. GitOrigin-RevId: 9f9415a8b2532d655a9a8740bcdf64066ddb7472
57 lines
2.2 KiB
Python
57 lines
2.2 KiB
Python
"""Stage verified macOS voice libraries and seal their post-signing release receipt."""
|
|
|
|
import argparse
|
|
import json
|
|
from pathlib import Path
|
|
import shutil
|
|
|
|
from package_runtime import runtime_files
|
|
from runtime import digest
|
|
|
|
|
|
def stage(source: Path, destination: Path, target: str) -> None:
|
|
if target not in {"aarch64-apple-darwin", "x86_64-apple-darwin"}:
|
|
raise ValueError("public voice runtime requires a macOS target")
|
|
source = source.resolve(strict=True)
|
|
files = runtime_files(source, target)
|
|
destination.mkdir()
|
|
try:
|
|
for relative, expected in files.items():
|
|
copied = destination / relative
|
|
copied.parent.mkdir(parents=True, exist_ok=True)
|
|
shutil.copy2(source / relative, copied)
|
|
if digest(copied) != expected:
|
|
raise ValueError("runtime changed while staging release inputs")
|
|
except BaseException:
|
|
shutil.rmtree(destination)
|
|
raise
|
|
|
|
|
|
def seal(root: Path, target: str) -> None:
|
|
root = root.resolve(strict=True)
|
|
manifest_path = root / "runtime.json"
|
|
manifest = json.loads(manifest_path.read_text(encoding="utf-8"))
|
|
if manifest.get("developmentOnly") is not True or manifest.get("target") != target:
|
|
raise ValueError("expected an unsealed development receipt for this target")
|
|
for record in manifest["libraries"]:
|
|
record["sha256"] = digest(root / record["path"])
|
|
manifest["developmentOnly"] = False
|
|
manifest["distribution"] = "publicRelease"
|
|
manifest_path.write_text(json.dumps(manifest, indent=2) + "\n", encoding="utf-8")
|
|
runtime_files(root, target, public_release=True)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument("operation", choices=("stage", "seal"))
|
|
parser.add_argument("--target", required=True)
|
|
parser.add_argument("--source", type=Path)
|
|
parser.add_argument("--output", type=Path, required=True)
|
|
args = parser.parse_args()
|
|
if args.operation == "stage":
|
|
if args.source is None:
|
|
parser.error("stage requires --source")
|
|
stage(args.source, args.output, args.target)
|
|
else:
|
|
seal(args.output, args.target)
|