fix(chv-guest): 客机镜像构建缺口补齐(B-02/B-03/B-04/B-05/B-06/B-07/B-08/B-09/B-10/B-13/B-15)
- B-10(实测):virt-customize chroot 里 sshd -t 必败,双因: 无 host key(exit 1)+ 缺 /run/sshd(exit 255);修为 mkdir -p /run/sshd + ssh-keygen -A 临时生成,断言通过后 立删临时 key,镜像仍不带 host key(已在 WSL 真机预演验证) - B-08:Playwright 装在第二次定制,须重写 pip freeze 否则 BUILDINFO 里无 playwright;Chromium 以 ms-playwright 缓存 目录名记录进 guest-versions-chromium.txt - B-09:codex --version 须含 CODEX_VERSION;REPO_COMMIT 须 等于 HEAD 短 hash;工作树脏即拒绝构建 - B-02/B-13:BUILDINFO 生成抽成 buildinfo.py(可单元测试), 补 disk.raw/vmlinux sha256+大小、ubuntu 镜像 sha、cmdline、 playwright 开关、image_sha256 字段 - generate_lockfile.py 改写:版本唯一来源改为 BUILDINFO.versions(客机读回),codex 三件套取 codex_version、/app/host.py 取 repo_commit、chromium 取 versions.chromium;不再查构建宿主 dpkg/pip(旧方法不成立) - check_lockfile.py 补强:条目格式、contents 全覆盖、冻结 清单双向比对 - B-03/B-04 输入格式校验、B-05 curl 重试、B-06 哈希不符 删文件重下、B-07 磁盘预检、B-15 set -euo pipefail - 同步改 test_chv_to10.py:generate 不再查宿主,改断言客机 版本来源 + 不回落宿主
This commit is contained in:
1 parent
8c8d62f70d
commit
7f18c2d13b
5 files changed
+372
-96
No files matched your search
@@ -0,0 +1,118 @@
|
||||
#!/usr/bin/env python3
|
||||
"""生成 CHV 客机镜像的 BUILDINFO.json(build.sh 调用)。
|
||||
|
||||
从 build.sh 抽出(B-02),使其可独立单元测试。输入全部是
|
||||
已落盘的构建产物与读回文件,不编造版本号:versions 来自
|
||||
客机读回的 dpkg-query / pip freeze(Playwright=1 时另有
|
||||
ms-playwright 缓存目录名作 chromium 标识);artifacts 的
|
||||
sha256/size 是对产物文件实测的;image_sha256 即 disk.raw
|
||||
的 sha256,供 generate_lockfile.py 沿用。
|
||||
|
||||
用法:
|
||||
python3 buildinfo.py OUT_DIR TAG UBUNTU CODEX_VERSION \\
|
||||
REPO_COMMIT UBUNTU_IMAGE_SHA256 PLAYWRIGHT(0|1)
|
||||
"""
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
|
||||
BASE_CONTENTS = [
|
||||
"git", "pandoc", "poppler-utils", "latexmk",
|
||||
"texlive-latex-base", "openssh-server", "cloud-init",
|
||||
"qemu-guest-agent", "python-docx", "openpyxl",
|
||||
"python-pptx", "PyMuPDF", "Pillow", "codex",
|
||||
"codex-code-mode-host", "codex-resources/bwrap",
|
||||
"/app/host.py",
|
||||
]
|
||||
|
||||
# 执行器默认内核 cmdline(config.py),构建产物须与它一起记录(B-12),
|
||||
# 否则换宿主/换执行器配置时无法复现。
|
||||
KERNEL_CMDLINE = "console=hvc0 root=/dev/vda1 rw"
|
||||
|
||||
|
||||
def _read_lines(path):
|
||||
try:
|
||||
with open(path) as fh:
|
||||
return [line.strip() for line in fh if line.strip()]
|
||||
except OSError:
|
||||
return []
|
||||
|
||||
|
||||
def _sha256_size(path):
|
||||
digest = hashlib.sha256()
|
||||
size = 0
|
||||
with open(path, "rb") as fh:
|
||||
for chunk in iter(lambda: fh.read(1 << 20), b""):
|
||||
digest.update(chunk)
|
||||
size += len(chunk)
|
||||
return digest.hexdigest(), size
|
||||
|
||||
|
||||
def build(outdir, tag, ubuntu, codex_version, repo_commit,
|
||||
ubuntu_image_sha256, playwright):
|
||||
disk_path = os.path.join(outdir, "disk.raw")
|
||||
vmlinux_path = os.path.join(outdir, "vmlinux")
|
||||
disk_sha, disk_size = _sha256_size(disk_path)
|
||||
vmlinux_sha, vmlinux_size = _sha256_size(vmlinux_path)
|
||||
contents = list(BASE_CONTENTS)
|
||||
versions = {
|
||||
"dpkg": _read_lines(
|
||||
os.path.join(outdir, "guest-versions-dpkg.txt")),
|
||||
"pip": _read_lines(
|
||||
os.path.join(outdir, "guest-versions-pip.txt")),
|
||||
}
|
||||
if playwright:
|
||||
contents += ["playwright", "chromium"]
|
||||
versions["chromium"] = _read_lines(
|
||||
os.path.join(outdir, "guest-versions-chromium.txt"))
|
||||
info = {
|
||||
"tag": tag,
|
||||
"ubuntu": ubuntu,
|
||||
"codex_version": codex_version,
|
||||
"repo_commit": repo_commit,
|
||||
"built_at": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()),
|
||||
"contents": contents,
|
||||
"versions": versions,
|
||||
"ubuntu_image_sha256": ubuntu_image_sha256,
|
||||
"ubuntu_image_sha256_set": True,
|
||||
"kernel_cmdline": KERNEL_CMDLINE,
|
||||
"playwright": bool(playwright),
|
||||
"image_sha256": disk_sha,
|
||||
"artifacts": {
|
||||
"disk.raw": {"sha256": disk_sha, "size": disk_size},
|
||||
"vmlinux": {"sha256": vmlinux_sha, "size": vmlinux_size},
|
||||
},
|
||||
}
|
||||
path = os.path.join(outdir, "BUILDINFO.json")
|
||||
with open(path, "w") as fh:
|
||||
json.dump(info, fh, indent=2)
|
||||
fh.write("\n")
|
||||
return info
|
||||
|
||||
|
||||
def main(argv):
|
||||
if len(argv) != 8:
|
||||
print("用法:buildinfo.py OUT TAG UBUNTU CODEX_VERSION "
|
||||
"REPO_COMMIT UBUNTU_IMAGE_SHA256 PLAYWRIGHT",
|
||||
file=sys.stderr)
|
||||
return 2
|
||||
_, outdir, tag, ubuntu, codex_version, repo_commit, \
|
||||
ubuntu_image_sha256, playwright = argv
|
||||
info = build(outdir, tag, ubuntu, codex_version, repo_commit,
|
||||
ubuntu_image_sha256, playwright == "1")
|
||||
if not info["versions"]["dpkg"]:
|
||||
print("BUILDINFO versions.dpkg 为空", file=sys.stderr)
|
||||
return 1
|
||||
if not info["versions"]["pip"]:
|
||||
print("BUILDINFO versions.pip 为空", file=sys.stderr)
|
||||
return 1
|
||||
if info["tag"] != tag:
|
||||
print("BUILDINFO tag 不一致", file=sys.stderr)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main(sys.argv))
|
||||
Reference in new issue
Block a user