agent-exec transport a843e40dbd0a9999047fd1c2d49d9ebd/e65c5571b4d1
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
# 组合指针一致:容器仓在 Dev 钉住的提交上,deps/ 里的每个 gitlink
|
||||
# 必须等于 Dev 顶层对应指针。development-guidelines 只告警。
|
||||
# 必须等于 Dev 顶层对应指针。development-guidelines / development-manager
|
||||
# 是治理规范与工具,版本由各项目固定采纳自行决定,不是运行时依赖,只告警。
|
||||
set -euo pipefail
|
||||
root=$(cd "$(dirname "$0")/.." && pwd)
|
||||
cd "$root"
|
||||
@@ -48,10 +49,10 @@ for container in "${containers[@]}"; do
|
||||
while read -r mode _typ sha name; do
|
||||
[ "$mode" = "160000" ] || continue
|
||||
base=${name#deps/}
|
||||
if [ "$base" = "development-guidelines" ]; then
|
||||
dev=$(pin_of deps/development-guidelines)
|
||||
if [ "$base" = "development-guidelines" ] || [ "$base" = "development-manager" ]; then
|
||||
dev=$(pin_of "deps/$base")
|
||||
if [ "$sha" != "$dev" ]; then
|
||||
echo "warn: $container deps/development-guidelines is ${sha:0:12}, Dev is ${dev:0:12}" >&2
|
||||
echo "warn: $container deps/$base is ${sha:0:12}, Dev is ${dev:0:12}" >&2
|
||||
fi
|
||||
continue
|
||||
fi
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
"""check-pins.sh:治理 gitlink 只告警,运行时依赖仍严格校验。"""
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import tempfile
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
SCRIPT = ROOT / "scripts" / "check-pins.sh"
|
||||
CONTAINERS = ("modules/backend", "deps/agent-native", "deps/agent-squad", "deps/agent-intent")
|
||||
|
||||
|
||||
class CheckPinsTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.tmp = Path(tempfile.mkdtemp())
|
||||
self.addCleanup(shutil.rmtree, self.tmp, ignore_errors=True)
|
||||
cfg = self.tmp / "gitconfig"
|
||||
cfg.write_text("")
|
||||
self.env = dict(
|
||||
os.environ,
|
||||
GIT_CONFIG_GLOBAL=str(cfg),
|
||||
GIT_CONFIG_NOSYSTEM="1",
|
||||
GIT_AUTHOR_NAME="t",
|
||||
GIT_AUTHOR_EMAIL="t@example.invalid",
|
||||
GIT_COMMITTER_NAME="t",
|
||||
GIT_COMMITTER_EMAIL="t@example.invalid",
|
||||
)
|
||||
self.dev = self.tmp / "dev"
|
||||
(self.dev / "scripts").mkdir(parents=True)
|
||||
shutil.copy(SCRIPT, self.dev / "scripts" / "check-pins.sh")
|
||||
self.git(self.dev, "init", "-q")
|
||||
|
||||
def git(self, cwd, *args):
|
||||
return subprocess.run(
|
||||
["git", *args], cwd=cwd, env=self.env, check=True, capture_output=True, text=True
|
||||
).stdout.strip()
|
||||
|
||||
def repo(self, rel, *contents):
|
||||
"""在 Dev 内建嵌套仓,按内容逐次提交,返回各提交 SHA。"""
|
||||
path = self.dev / rel
|
||||
path.mkdir(parents=True)
|
||||
self.git(path, "init", "-q")
|
||||
shas = []
|
||||
for text in contents:
|
||||
(path / "f").write_text(text)
|
||||
self.git(path, "add", "f")
|
||||
self.git(path, "commit", "-qm", text)
|
||||
shas.append(self.git(path, "rev-parse", "HEAD"))
|
||||
return shas
|
||||
|
||||
def link(self, repo, rel, sha):
|
||||
self.git(repo, "update-index", "--add", "--cacheinfo", f"160000,{sha},{rel}")
|
||||
|
||||
def build(self, backend_deps, dev_pins):
|
||||
"""backend_deps/dev_pins:{deps 名: sha};其余容器无 deps。"""
|
||||
for rel, sha in dev_pins.items():
|
||||
self.link(self.dev, rel, sha)
|
||||
for container in CONTAINERS:
|
||||
path = self.dev / container
|
||||
if not path.exists():
|
||||
self.repo(container, container)
|
||||
if container == "modules/backend":
|
||||
for name, sha in backend_deps.items():
|
||||
self.link(path, f"deps/{name}", sha)
|
||||
self.git(path, "commit", "-qm", "deps")
|
||||
self.link(self.dev, container, self.git(path, "rev-parse", "HEAD"))
|
||||
|
||||
def run_pins(self):
|
||||
return subprocess.run(
|
||||
["bash", "scripts/check-pins.sh"], cwd=self.dev, env=self.env, capture_output=True, text=True
|
||||
)
|
||||
|
||||
def test_governance_mismatch_warns_and_passes(self):
|
||||
g_old, g_new = self.repo("deps/development-guidelines", "g1", "g2")
|
||||
m_old, m_new = self.repo("deps/development-manager", "m1", "m2")
|
||||
self.build(
|
||||
{"development-guidelines": g_old, "development-manager": m_old},
|
||||
{"deps/development-guidelines": g_new, "deps/development-manager": m_new},
|
||||
)
|
||||
res = self.run_pins()
|
||||
self.assertEqual(res.returncode, 0, res.stderr)
|
||||
self.assertIn("warn: modules/backend deps/development-guidelines", res.stderr)
|
||||
self.assertIn("warn: modules/backend deps/development-manager", res.stderr)
|
||||
self.assertIn("pins ok", res.stdout)
|
||||
|
||||
def test_runtime_mismatch_fails(self):
|
||||
old, new = self.repo("deps/error-code-system", "e1", "e2")
|
||||
self.build({"error-code-system": old}, {"deps/error-code-system": new})
|
||||
res = self.run_pins()
|
||||
self.assertEqual(res.returncode, 1)
|
||||
self.assertIn("pin: modules/backend deps/error-code-system is", res.stderr)
|
||||
|
||||
def test_runtime_match_passes(self):
|
||||
(sha,) = self.repo("deps/error-code-system", "e1")
|
||||
self.build({"error-code-system": sha}, {"deps/error-code-system": sha})
|
||||
res = self.run_pins()
|
||||
self.assertEqual(res.returncode, 0, res.stderr)
|
||||
self.assertIn("ok modules/backend error-code-system", res.stdout)
|
||||
|
||||
def test_runtime_missing_object_fails(self):
|
||||
(sha,) = self.repo("deps/error-code-system", "e1")
|
||||
self.build({"error-code-system": "1" * 40}, {"deps/error-code-system": sha})
|
||||
res = self.run_pins()
|
||||
self.assertEqual(res.returncode, 1)
|
||||
self.assertIn("is missing locally", res.stderr)
|
||||
|
||||
def test_runtime_without_dev_pin_fails(self):
|
||||
(sha,) = self.repo("deps/logging-system", "l1")
|
||||
self.build({"logging-system": sha}, {})
|
||||
res = self.run_pins()
|
||||
self.assertEqual(res.returncode, 1)
|
||||
self.assertIn("has no Dev pin", res.stderr)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user