Files
Mujoco_WASM/deploy/cadworld/prepare_bundle.py
T
chenlin f3a8a38acd
web-platform-ci / Standalone decision service (no cloud credentials) (push) Has been cancelled
web-platform-ci / TypeScript, lint, unit, build (push) Has been cancelled
web-platform-ci / Playwright E2E (push) Has been cancelled
lekiwi-compatibility / cpu-compatibility (push) Has been cancelled
web-platform-ci / Standalone decision service (no cloud credentials) (pull_request) Has been cancelled
web-platform-ci / TypeScript, lint, unit, build (pull_request) Has been cancelled
web-platform-ci / Playwright E2E (pull_request) Has been cancelled
lekiwi-compatibility / cpu-compatibility (pull_request) Has been cancelled
feat: release v1.0.1 CADWorld 网站与 LeKiwi 智能抓放
集成同源 BYOK 会话隔离、精简模型设置、官方订阅入口和 HTTPS 发布运维;保留本地训练/调参与控制能力。同步 npm 版本及 CHANGELOG,记录公网真实 API 验收仍待用户凭据。
2026-09-24 09:57:41 +08:00

81 lines
2.9 KiB
Python

"""Package an explicit allowlist, never the working tree/.env/user assets wholesale."""
import argparse
import hashlib
import json
import re
import shutil
import tarfile
from pathlib import Path
ROOT = Path(__file__).resolve().parents[2]
def main():
parser = argparse.ArgumentParser()
parser.add_argument("release")
args = parser.parse_args()
if not re.fullmatch(r"[A-Za-z0-9][A-Za-z0-9_.-]{0,63}", args.release):
parser.error("invalid release")
output = ROOT / "build/website-deployment/bundles" / args.release
output.mkdir(parents=True, exist_ok=False)
def copy(source, target):
if source.is_symlink():
raise RuntimeError("symlinks not allowed in publish inputs")
target.parent.mkdir(parents=True, exist_ok=True)
shutil.copyfile(source, target)
for source in (ROOT / "decision_server").rglob("*"):
relative = source.relative_to(ROOT)
if (
source.is_file()
and "tests" not in relative.parts
and "__pycache__" not in relative.parts
and source.suffix in (".py", ".json", ".txt", ".md")
):
copy(source, output / "app" / relative)
copy(
ROOT / "contracts/lekiwi-agent-v1.schema.json",
output / "app/contracts/lekiwi-agent-v1.schema.json",
)
for source in (ROOT / "deploy/cadworld").iterdir():
if source.is_file():
copy(source, output / "deploy" / source.name)
copy(ROOT / "deploy/cadworld/Dockerfile", output / "app/Dockerfile")
copy(ROOT / "deploy/cadworld/.dockerignore", output / "app/.dockerignore")
copy(
ROOT / "deploy/cadworld/requirements.lock.txt",
output / "app/deploy/cadworld/requirements.lock.txt",
)
vendor = ROOT / "build/website-deployment/vendor"
for source in [
vendor / "codex",
vendor / "codex-origin.json",
*sorted((vendor / "wheels").glob("*.whl")),
]:
copy(source, output / "app/vendor" / source.relative_to(vendor))
for source in (ROOT / "website-dist").rglob("*"):
if source.is_file():
copy(source, output / "static" / source.relative_to(ROOT / "website-dist"))
if not (output / "static/index.html").exists() or (output / "static/tuning.html").exists():
raise RuntimeError("website production build required")
manifest = {
str(p.relative_to(output)): hashlib.sha256(p.read_bytes()).hexdigest()
for p in sorted(output.rglob("*"))
if p.is_file()
}
(output / "manifest.json").write_text(
json.dumps({"release": args.release, "files": manifest}, indent=2)
)
archive = output.with_suffix(".tar.gz")
with tarfile.open(archive, "w:gz") as tar:
for path in sorted(output.iterdir()):
tar.add(path, arcname=path.name)
print(str(archive))
print("sha256", hashlib.sha256(archive.read_bytes()).hexdigest())
if __name__ == "__main__":
main()