Fetch and build the three pinned RDM SHAs in CI

Why: test-pg only cloned the default branch, so prev_sha and legacy_sha were never built or attested.
Evidence: SELF python3 -m unittest tests.test_ci_credentials tests.test_lifecycle_pin (11 tests, exit 0).
Impact: the lifecycle suite prints the combination inventory and keeps login and rdm.ping as NOT_RUN.
Refs: .task/feature-svc-d3-real-scenarios.md
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-10-13 02:59:44 +00:00
co-authored by Cursor
parent 4bd8d2a340
commit 8dda121c0d
3 changed files with 146 additions and 13 deletions
+33 -5
View File
@@ -387,7 +387,7 @@ jobs:
# 凭据纪律与 Checkout 块同源:经 GIT_CONFIG_* 环境注入 URL 级 token 头,
# 不落文件/命令行;allowlist 扩项 = Agent-System-RDM 及其 pins(同一
# 组件集合),由本 PR 评审背书。SSH pins URL 以 insteadOf 改写到受信
# https 基址后再取。
# https 基址后再取。只追加 pin 的三个 40 位 hex,不 source pin 文件。
SERVER="$(printf '%s' "$GITHUB_SERVER_URL" | sed 's:/*$::')"
scheme="${GITHUB_SERVER_URL%%://*}"
export GIT_CONFIG_COUNT=4
@@ -400,15 +400,43 @@ jobs:
export GIT_CONFIG_KEY_3="core.hooksPath"
export GIT_CONFIG_VALUE_3="/dev/null"
git clone --depth=1 "$SERVER/weichen/Agent-System-RDM.git" rdm
# 凭据环境须保持到 pins 子模块取完(insteadOf + token 头覆盖嵌套 SSH URL),
# 之后再 unset。
git -C rdm submodule update --init --recursive
mapfile -t pins < <(python3 - <<'PY'
import pathlib
got = {}
for line in pathlib.Path("tests/integration/lifecycle/rdm.pin").read_text().splitlines():
line = line.strip()
if not line or line.startswith("#") or "=" not in line:
continue
key, value = line.split("=", 1)
if key not in ("sha", "prev_sha", "legacy_sha") or len(value) != 40:
raise SystemExit("rdm.pin rejected")
if any(c not in "0123456789abcdef" for c in value):
raise SystemExit("rdm.pin rejected")
got[key] = value
if set(got) != {"sha", "prev_sha", "legacy_sha"}:
raise SystemExit("rdm.pin rejected")
print(got["prev_sha"])
print(got["legacy_sha"])
print(got["sha"])
PY
)
[ "${#pins[@]}" -eq 3 ]
git -C rdm fetch --depth=1 origin "${pins[@]}"
for rev in "${pins[@]}"; do
git -C rdm checkout --detach "$rev"
git -C rdm submodule update --init --recursive
done
echo "RDM commit: $(git -C rdm rev-parse HEAD)"
unset GIT_CONFIG_COUNT GIT_CONFIG_KEY_0 GIT_CONFIG_VALUE_0 \
GIT_CONFIG_KEY_1 GIT_CONFIG_VALUE_1 GIT_CONFIG_KEY_2 \
GIT_CONFIG_VALUE_2 GIT_CONFIG_KEY_3 GIT_CONFIG_VALUE_3
unset SUBMODULE_TOKEN
make -C rdm build
: > rdm/pin-build-digests.txt
for rev in "${pins[@]}"; do
git -C rdm checkout --detach "$rev"
make -C rdm build
sha256sum rdm/bin/agent-system-rdm | awk -v rev="$rev" '{print rev, $1}' >> rdm/pin-build-digests.txt
done
- name: Install Node 22
run: |
set -euo pipefail
+62 -8
View File
@@ -1,18 +1,77 @@
"""真实 Dev/RDM 组合门禁。由 make test-lifecycle 调用。
缺 PostgreSQL、RDM 源码或制品时直接失败,不静默跳过。
登录依赖账户 CLI 公共化(账户方案 U7/U5),单独标 NOT_RUN,
登录与 rdm.ping 依赖账户 CLI 公共化,单独标 NOT_RUN,
不因此把已经跑过的真实组合场景记成失败。
"""
import hashlib
import os
import subprocess
import sys
from pathlib import Path
from urllib.parse import urlparse
ROOT = Path(__file__).resolve().parents[3]
PIN = Path(__file__).resolve().parent / "rdm.pin"
def sha256_file(path):
digest = hashlib.sha256()
with open(path, "rb") as handle:
for chunk in iter(lambda: handle.read(1024 * 1024), b""):
digest.update(chunk)
return digest.hexdigest()
def print_inventory(src, dev, rdm):
print("组合清单")
head = subprocess.run(["git", "-C", str(ROOT), "rev-parse", "HEAD"],
capture_output=True, text=True)
print("dev_sha", head.stdout.strip() if head.returncode == 0 else "NOT_RUN")
modules = subprocess.run(
["git", "-C", str(ROOT), "submodule", "status", "--recursive"],
capture_output=True, text=True)
if modules.returncode == 0:
for line in modules.stdout.splitlines():
print("submodule", " ".join(line.split()[:2]))
else:
print("submodule NOT_RUN")
print("pin")
for line in PIN.read_text().splitlines():
if line.strip() and not line.startswith("#"):
print(" ", line.strip())
print("dev_bin", dev, sha256_file(dev))
print("rdm_bin", rdm, sha256_file(rdm))
digests = Path(src) / "pin-build-digests.txt"
if digests.is_file():
for line in digests.read_text().splitlines():
print("pin_build", line)
else:
print("pin_build NOT_RUN:本进程没有预构建三个 pin")
print("pg_version", pg_version())
print("登录 NOT_RUN:RDM 二进制没有 user/apikey,工作台登录依赖账户方案 U7/U5")
print("rdm.ping NOT_RUN:需要已登录会话,本轮不公共化账户 CLI")
def pg_version():
parsed = urlparse(os.environ.get("AGENT_PG_TEST_DSN", ""))
if not parsed.hostname:
return "NOT_RUN"
env = os.environ.copy()
env.update({
"PGHOST": parsed.hostname,
"PGPORT": str(parsed.port or 5432),
"PGUSER": parsed.username or "",
"PGPASSWORD": parsed.password or "",
"PGDATABASE": parsed.path.lstrip("/"),
})
proc = subprocess.run(["psql", "-tAc", "SHOW server_version"],
env=env, capture_output=True, text=True)
if proc.returncode != 0:
return "NOT_RUN"
return proc.stdout.strip() or "NOT_RUN"
def main():
missing = []
if not os.environ.get("AGENT_PG_TEST_DSN"):
@@ -30,18 +89,12 @@ def main():
print("test-lifecycle 失败。缺:%s" % ", ".join(missing))
return 1
print("组合清单")
print("pin", PIN.read_text().strip())
print("rdm_src", src)
print("dev_bin", dev)
print("rdm_bin", rdm)
print("将运行 tests.test_svc_realcombo:SQLite 身份、RDM 二进制生命周期、PostgreSQL 身份环境交付")
print("将运行 tests.integration.lifecycle.test_lifecycle_real:pin 上的真实候选与切换")
if os.environ.get("SVC_RDM_ORIGIN"):
print("将运行全轨部署:SVC_RDM_ORIGIN 已设置")
else:
print("全轨部署 NOT_RUN:未设置 SVC_RDM_ORIGIN(由 svc-realcombo 作业覆盖)")
print("登录 NOT_RUN:RDM 二进制没有 user/apikey,工作台登录依赖账户方案 U7/U5")
env = os.environ.copy()
env["SVC_TEST_REAL"] = "1"
env["SVC_TEST_PG"] = "1"
@@ -52,10 +105,11 @@ def main():
"tests.test_svc_realcombo",
"tests.integration.lifecycle.test_lifecycle_real", "-q"],
cwd=str(ROOT), env=env)
print_inventory(src, dev, rdm)
if proc.returncode != 0:
print("test-lifecycle 失败:真实组合用例未通过")
return proc.returncode
print("test-lifecycle 可跑场景通过;登录与未设 origin 的全轨部署保持 NOT_RUN")
print("test-lifecycle 可跑场景通过;登录与 rdm.ping 保持 NOT_RUN")
return 0
+51
View File
@@ -25,6 +25,14 @@ def checkout_script():
return textwrap.dedent("\n".join(lines[start:end]))
def rdm_clone_script():
lines = WORKFLOW.read_text().splitlines()
start = next(i for i, line in enumerate(lines) if "Clone Agent-System-RDM" in line)
start = next(i for i in range(start, len(lines)) if lines[i].strip() == "run: |") + 1
end = next(i for i in range(start, len(lines)) if lines[i].startswith(" - name:"))
return textwrap.dedent("\n".join(lines[start:end]))
class CheckoutTests(unittest.TestCase):
def setUp(self):
self.temp = tempfile.TemporaryDirectory()
@@ -236,6 +244,49 @@ class CheckoutTests(unittest.TestCase):
self.assertNotEqual(result.returncode, 0)
self.assertFalse(any("untrusted" in path for path, auth in self.requests))
def test_rdm_pin_fetch_is_three_shas_on_the_allowlist(self):
source = self.base / "Agent-System-RDM"
source.mkdir()
self.git(source, "init", "-q", "-b", "main")
shas = []
for index in range(3):
(source / "Makefile").write_text(
"build:\n\tmkdir -p bin\n\tprintf 'rev%d\\n' > bin/agent-system-rdm\n" % index)
self.git(source, "add", ".")
self.git(source, "-c", "user.name=Fixture",
"-c", "user.email=fixture@example.invalid",
"commit", "-q", "-m", "rev %d" % index)
shas.append(self.git(source, "rev-parse", "HEAD"))
target = self.published / "weichen" / "Agent-System-RDM.git"
target.parent.mkdir(parents=True, exist_ok=True)
self.git(self.base, "clone", "-q", "--bare", str(source), str(target))
self.git(target, "config", "uploadpack.allowReachableSHA1InWant", "true")
self.git(target, "config", "uploadpack.allowAnySHA1InWant", "true")
work = self.base / "rdm-job"
pin = work / "tests" / "integration" / "lifecycle"
pin.mkdir(parents=True)
(pin / "rdm.pin").write_text(
"sha=%s\nprev_sha=%s\nlegacy_sha=%s\n" % (shas[2], shas[1], shas[0]))
script = rdm_clone_script()
self.assertNotRegex(script, r"(?m)^\s*source\s")
self.requests.clear()
result = subprocess.run(
["bash", "-c", script], cwd=work,
env=self.env | {"SUBMODULE_TOKEN": SUB_TOKEN, "GITHUB_SERVER_URL": self.url},
capture_output=True, text=True, timeout=60)
self.assertEqual(result.returncode, 0, result.stdout + result.stderr)
self.assertNotIn(SUB_TOKEN, result.stdout + result.stderr)
self.assertTrue(self.requests)
for path, auth in self.requests:
self.assertRegex(path, r"^/weichen/Agent-System-RDM\.git/")
self.assertEqual(auth, "token " + SUB_TOKEN)
for sha in shas:
self.assertEqual(self.git(work / "rdm", "cat-file", "-t", sha), "commit")
self.assertEqual(self.git(work / "rdm", "rev-parse", "HEAD"), shas[2])
digests = (work / "rdm" / "pin-build-digests.txt").read_text()
for sha in shas:
self.assertIn(sha, digests)
if __name__ == "__main__":
unittest.main()