Files
Mujoco_WASM/deploy/cadworld/prepare_bundle.py
T
chenlin 0d986f60bd
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
feat: release v1.0.2 LeKiwi 语言控制与网站嵌入
集成服务器托管模型、自然语言移动与有界抓放、内置 LeKiwi URL 导入和双摄像头;同步部署契约与指定域名 iframe 白名单,保留原有物理安全、会话及调用预算防护。

更新 npm 包及锁文件版本、CHANGELOG 与发布文档。提交前 typecheck、120 项定向前端测试和 44 项后端测试通过(3 项可选跳过);真实 v2 云模型抓放仍待单独验收,不包含运行密钥或构建产物。
2026-09-24 15:29:49 +08:00

83 lines
3.0 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)
for name in (
"lekiwi-agent-v1.schema.json",
"lekiwi-language-task-v2.schema.json",
"lekiwi-language-scene-v2.json",
):
copy(ROOT / "contracts" / name, output / "app/contracts" / name)
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()