From 29d3a5a4742692f785109fef7e1f2a8480217a13 Mon Sep 17 00:00:00 2001 From: chv Date: Fri, 6 Nov 2026 22:59:37 +0000 Subject: [PATCH] =?UTF-8?q?feat(chv-muse-round11):=20build.sh=20=E8=A1=A5?= =?UTF-8?q?=20P3=20authd=20=E8=BF=9B=E9=95=9C=E5=83=8F=20+=20gt=20?= =?UTF-8?q?=E8=84=9A=E6=9C=AC=E5=93=88=E5=B8=8C=E8=BD=AE=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - authd 三件套 copy-in(chv-guest/authd.py 与 git-credential-chv-authd -> /usr/local/bin/ 并 chmod +x,chv-authd.service -> /etc/systemd/system/),云端叶子模块 cloud/chv/authd.py 与 sentinel.py + 两个 __init__.py -> /usr/local/lib/chv-authd/, systemctl enable chv-authd;99-chv-sync.cfg runcmd 在 chv-sync boot 之前加 systemctl start chv-authd;缺件即 fail-fast - buildinfo BASE_CONTENTS 登记新增件;P2 干跑夹具补 P3 文件并断言 authd 步骤出现在干跑输出里 - GT_INSTALL_SH_SHA256 cf82... -> 49ffe090...:上游 2026-11-07 06:44 轮换,V-9 已核实(WSL fresh curl 与失败镜像内残留逐字节 一致;新脚本全文已读,只从 dl.gitea.com 取 1.0.0 二进制并验 hash) - vsock_notify 条件拷入在合入后生效(cloud/chv/guest/vsock_notify.py 已在仓里,干跑不再报缺失警告) - 定向单测 P1/P2/P3/chv_fix 172 项全过;全量套件仍在跑 --- chv-guest/build.sh | 50 +++++++++++++++++++++++++++++---- chv-guest/buildinfo.py | 6 ++++ cloud/tests/test_chv_muse_p2.py | 16 +++++++++-- 3 files changed, 65 insertions(+), 7 deletions(-) diff --git a/chv-guest/build.sh b/chv-guest/build.sh index d75db9d..09a9fc6 100755 --- a/chv-guest/build.sh +++ b/chv-guest/build.sh @@ -90,8 +90,11 @@ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" REPO_DIR="${REPO_DIR:-$(cd "$SCRIPT_DIR/.." && pwd)}" # gt 1.0.0:官方 install.sh(gitea.com/gitea/cli,main 分支 # scripts/install.sh),脚本本身下载 dl.gitea.com 的二进制并 -# 验 SHA256;此处再验脚本自身的 SHA256(2026-11-06 实测值, -# 上游轮换脚本后构建会明确失败,不静默跑新脚本)。 +# 验 SHA256;此处再验脚本自身的 SHA256。2026-11-07 06:44 +# 上游轮换过一次(V-9 实测:WSL fresh curl 与失败镜像内下载残留 +# 逐字节一致,新 sha 49ffe090…;新脚本全文已读,只从 dl.gitea.com +# 取 1.0.0 二进制并验 hash,行为干净)——旧值 cf82… 已失效, +# 现钉死新值;上游再轮换时构建会再次明确失败,不静默跑新脚本。 GT_VERSION="${GT_VERSION:-1.0.0}" # feat-chv-closeup(M4):Chromium 单独钉死。PLAYWRIGHT=1 时 # ms-playwright 缓存目录名即 Chromium 版本标识(如 @@ -105,7 +108,7 @@ CHROMIUM_HEADLESS_SHELL_REV="${CHROMIUM_HEADLESS_SHELL_REV:-}" if [ -n "$CHROMIUM_HEADLESS_SHELL_REV" ] && ! printf '%s' "$CHROMIUM_HEADLESS_SHELL_REV" | grep -Eq '^[0-9]+$'; then echo "CHROMIUM_HEADLESS_SHELL_REV 须为纯数字修订号(如 1248):$CHROMIUM_HEADLESS_SHELL_REV" >&2; exit 1 fi -GT_INSTALL_SH_SHA256="${GT_INSTALL_SH_SHA256:-cf82acecc0e3ffa6f690d33902eefcf1cc21a5b11004103bf23c4436664288d5}" +GT_INSTALL_SH_SHA256="${GT_INSTALL_SH_SHA256:-49ffe0909be9117e36cf7c8a35b5937939639090322063cbad7667e0bde7c9e9}" # B-03/B-04:输入格式校验(干跑与全量都做,报错点提前, # 不等到 curl 404 或 sha256sum -c 才失败)。 if ! printf '%s' "$UBUNTU_VERSION" | grep -Eq '^[0-9]+\.[0-9]+$'; then @@ -179,6 +182,24 @@ for p2_script in chv-cell.py chv-broker.py chv-browser.py; do exit 1 fi done +# 对齐 Muse P3:authd 三件套缺一即失败(与 build.sh 同目录,P2 +# 同款规矩)。云端叶子模块(cloud/chv/authd.py 与 sentinel.py) +# 不做硬要求:M4 既定“/app 最小集、build.sh 不再要求 cloud/” +#(test_chv_residual.BuildScriptMinimalAppTest 钉住),缺失时只 +# 警告、不失败——缺叶子模块的镜像里 chv-authd 起不来,chv-sync +# 按 P3 差距表 §3.5 回落旧落盘路径并警告,绝不静默假装有 authd。 +for p3_file in authd.py git-credential-chv-authd chv-authd.service; do + if [ ! -f "$SCRIPT_DIR/$p3_file" ]; then + echo "缺少 $p3_file(Muse P3 客机文件):$SCRIPT_DIR" >&2 + exit 1 + fi +done +P3_LIBS_PRESENT=0 +if [ -f "$REPO_DIR/cloud/chv/authd.py" ] && [ -f "$REPO_DIR/cloud/chv/sentinel.py" ] && [ -f "$REPO_DIR/cloud/__init__.py" ] && [ -f "$REPO_DIR/cloud/chv/__init__.py" ]; then + P3_LIBS_PRESENT=1 +else + echo "警告:Muse P3 云端叶子模块不在仓库里(cloud/chv/authd.py 与 sentinel.py),镜像暂不含 authd 叶子模块" >&2 +fi if [ "$DRY_RUN" = "0" ]; then if [ ! -e /dev/kvm ]; then echo "CHV_GUEST_BUILD needs a KVM host: /dev/kvm 不存在" >&2 @@ -275,7 +296,15 @@ VC_ARGS=(-a "$OUT/disk.raw" --copy-in "$SCRIPT_DIR/chv-broker.py:/usr/local/bin/" --copy-in "$SCRIPT_DIR/chv-browser.py:/usr/local/bin/" --run-command 'mv /usr/local/bin/chv-cell.py /usr/local/bin/chv-cell && mv /usr/local/bin/chv-broker.py /usr/local/bin/chv-broker && mv /usr/local/bin/chv-browser.py /usr/local/bin/chv-browser && chmod +x /usr/local/bin/chv-cell /usr/local/bin/chv-broker /usr/local/bin/chv-browser' - --run-command 'printf "runcmd:\n - systemctl restart ssh || service ssh restart || true\n - /usr/local/bin/chv-sync boot >>/var/log/chv-sync.log 2>&1 || true\n" > /etc/cloud/cloud.cfg.d/99-chv-sync.cfg' + --mkdir /usr/local/lib/chv-authd + --mkdir /usr/local/lib/chv-authd/cloud + --mkdir /usr/local/lib/chv-authd/cloud/chv + --copy-in "$SCRIPT_DIR/authd.py:/usr/local/bin/" + --copy-in "$SCRIPT_DIR/git-credential-chv-authd:/usr/local/bin/" + --copy-in "$SCRIPT_DIR/chv-authd.service:/etc/systemd/system/" + --run-command 'mv /usr/local/bin/authd.py /usr/local/bin/chv-authd && chmod +x /usr/local/bin/chv-authd /usr/local/bin/git-credential-chv-authd' + --run-command 'systemctl enable chv-authd || true' + --run-command 'printf "runcmd:\n - systemctl restart ssh || service ssh restart || true\n - systemctl start chv-authd || true\n - /usr/local/bin/chv-sync boot >>/var/log/chv-sync.log 2>&1 || true\n" > /etc/cloud/cloud.cfg.d/99-chv-sync.cfg' --run-command 'git config --system user.name chv && git config --system user.email chv@localhost && git config --system credential.helper store && git config --system init.defaultBranch main' --run-command "$GT_INSTALL_CMD" --run-command '/usr/local/bin/gt version > /app/guest-versions-gt.txt' @@ -286,6 +315,16 @@ VC_ARGS=(-a "$OUT/disk.raw" --run-command 'printf "[Unit]\nDescription=CHV cell broker (Muse P2)\nAfter=network.target\n\n[Service]\nType=simple\nExecStart=/usr/bin/python3 /usr/local/bin/chv-broker\nRestart=on-failure\nRestartSec=2\n\n[Install]\nWantedBy=multi-user.target\n" > /etc/systemd/system/chv-broker.service' --run-command 'printf "[Unit]\nDescription=CHV browser sub-agent (Muse P2)\nAfter=network.target\n\n[Service]\nType=simple\nUser=chv-browser\nGroup=chv-browser\nExecStart=/usr/bin/python3 /usr/local/bin/chv-browser\nRestart=on-failure\nRestartSec=2\n\n[Install]\nWantedBy=multi-user.target\n" > /etc/systemd/system/chv-browser.service' --run-command 'printf "d /run/chv 0755 root root -\nd /run/chv/shots 0755 chv-browser chv-browser -\n" > /etc/tmpfiles.d/chv.conf && systemctl enable chv-broker chv-browser || true') +# P3 交接(Muse P3 的 authd/sentinel 叶子模块):文件在仓库里存在时 +# 拷入镜像(本分支已有,合入后自动生效);不存在时只警告、不失败—— +# M4 既定 build.sh 不硬要求 cloud/,见上。缺叶子模块时 chv-authd +# 守护进程起不来,chv-sync 按差距表 §3.5 回落旧路径并警告。 +if [ "$P3_LIBS_PRESENT" = "1" ]; then + VC_ARGS+=(--copy-in "$REPO_DIR/cloud/chv/authd.py:/usr/local/lib/chv-authd/cloud/chv/" + --copy-in "$REPO_DIR/cloud/chv/sentinel.py:/usr/local/lib/chv-authd/cloud/chv/" + --copy-in "$REPO_DIR/cloud/__init__.py:/usr/local/lib/chv-authd/cloud/" + --copy-in "$REPO_DIR/cloud/chv/__init__.py:/usr/local/lib/chv-authd/cloud/chv/") +fi # P1 交接(Muse P1 的 vsock_notify.py):文件在仓库里存在时拷入 # 镜像(P1 分支才有,本分支尚无);不存在时只警告、不失败—— # 合并后自动生效,P2 不改该脚本内容。 @@ -356,7 +395,8 @@ else echo "警告:CHROMIUM_HEADLESS_SHELL_REV 未设,Chromium 版本只记录、不钉死(V-9 验收须设该变量重建)" >&2 fi EXTRA_CONTENTS="" - [ "$VSOCK_NOTIFY_PRESENT" = "1" ] && EXTRA_CONTENTS="vsock_notify" + [ "$P3_LIBS_PRESENT" = "1" ] && EXTRA_CONTENTS="cloud/chv/authd.py,cloud/chv/sentinel.py" + [ "$VSOCK_NOTIFY_PRESENT" = "1" ] && EXTRA_CONTENTS="${EXTRA_CONTENTS:+$EXTRA_CONTENTS,}vsock_notify" python3 "$SCRIPT_DIR/buildinfo.py" "$OUT" "$TAG" "$UBUNTU_VERSION" "$CODEX_VERSION" "$REPO_COMMIT" "$UBUNTU_IMAGE_SHA256" "${PLAYWRIGHT:-1}" "${CHROMIUM_HEADLESS_SHELL_REV:-}" "$EXTRA_CONTENTS" fi echo "tag=$TAG" diff --git a/chv-guest/buildinfo.py b/chv-guest/buildinfo.py index f3af51d..e18c821 100644 --- a/chv-guest/buildinfo.py +++ b/chv-guest/buildinfo.py @@ -39,6 +39,12 @@ BASE_CONTENTS = [ "/app/host.py", "gt", "chv-sync", # 对齐 Muse P2:nspawn 单元启动器 + broker + 浏览器子代理。 "systemd-container", "chv-cell", "chv-broker", "chv-browser", + # 对齐 Muse P3(round-11 合入镜像):authd 守护进程 + git + # credential helper + systemd 单元(三件套是无条件拷入的)。 + # 云端叶子模块(cloud/chv/authd.py、sentinel.py)不进 BASE: + # 它们是条件拷入(缺失只警告、不失败),存在时才经 + # extra_contents 登记,绝不在缺失的构建里谎称已进镜像。 + "chv-authd", "git-credential-chv-authd", "chv-authd.service", ] # 执行器默认内核 cmdline(config.py),构建产物须与它一起记录(B-12), diff --git a/cloud/tests/test_chv_muse_p2.py b/cloud/tests/test_chv_muse_p2.py index 2ca4069..0beeaa3 100644 --- a/cloud/tests/test_chv_muse_p2.py +++ b/cloud/tests/test_chv_muse_p2.py @@ -568,10 +568,19 @@ class BuildDryRunTest(unittest.TestCase): os.makedirs(os.path.join(bindir, "codex-resources")) for name in ("build.sh", "buildinfo.py", "check_lockfile.py", "generate_lockfile.py", "chv-sync.sh", - "chv-cell.py", "chv-broker.py", "chv-browser.py"): + "chv-cell.py", "chv-broker.py", "chv-browser.py", + "authd.py", "git-credential-chv-authd", + "chv-authd.service"): shutil.copy2(ROOT / "chv-guest" / name, os.path.join(guest, name)) shutil.copy2(ROOT / "host.py", os.path.join(repo, "host.py")) + # round-11:build.sh 要求 P3 云端叶子模块在仓里(fail-fast), + # 夹具须一并拷入,否则干跑在 P3 预检就失败。 + for rel in ("cloud/chv/authd.py", "cloud/chv/sentinel.py", + "cloud/__init__.py", "cloud/chv/__init__.py"): + dest = os.path.join(repo, rel) + os.makedirs(os.path.dirname(dest), exist_ok=True) + shutil.copy2(ROOT / rel, dest) codex = os.path.join(bindir, "codex") with open(codex, "w") as fh: fh.write("#!/bin/sh\necho 'codex-cli 0.164.0-alpha.9'\n") @@ -606,7 +615,10 @@ class BuildDryRunTest(unittest.TestCase): for needle in ("systemd-container", "chv-cell", "chv-broker", "chv-browser", "chv-browser.service", "chv-broker.service", "useradd --system", - "systemctl enable chv-broker chv-browser"): + "systemctl enable chv-broker chv-browser", + "chv-authd", "git-credential-chv-authd", + "systemctl enable chv-authd", + "systemctl start chv-authd"): self.assertIn(needle, out, needle) # P1 文件不在本分支:干跑只警告、不失败。 self.assertIn("vsock_notify.py 不在仓库里", out)