Give pin materialize the CI git channel and a private database
Why: test-pg has no SSH known_hosts, and the shared agent_test database already holds another instance identity. Evidence: SELF python3 -m unittest tests.test_ci_credentials.CheckoutTests.test_rdm_pin_fetch_is_three_shas_on_the_allowlist tests.integration.lifecycle.test_lifecycle_real (1 pass, 24 skip). Impact: lifecycle children forward GIT_CONFIG_* only; serve stays env -i. Login and rdm.ping stay NOT_RUN. Refs: .task/feature-svc-d3-real-scenarios.md Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -447,14 +447,20 @@ jobs:
|
||||
- name: Real-combination lifecycle gate (make test-lifecycle, required)
|
||||
env:
|
||||
AGENT_PG_TEST_DSN: postgres://ci_agent:ci_job_local_only@127.0.0.1:5432/agent_test?sslmode=disable
|
||||
SUBMODULE_TOKEN: ${{ secrets.SUBMODULE_TOKEN }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
# 路径变量在脚本内解析(YAML env: 不做 shell 展开)。
|
||||
# 不设 SVC_RDM_ORIGIN:全轨 git 部署由 svc-realcombo 作业覆盖。
|
||||
# pins 物化没有 SSH known_hosts。token 只经 SVC_CI_GIT_TOKEN 进
|
||||
# ci_git_env 的 URL 级头,不写文件。
|
||||
export SVC_TEST_REAL=1 SVC_TEST_PG=1
|
||||
export SVC_REAL_BIN="$PWD/bin/agent-system"
|
||||
export SVC_REAL_RDM_BIN="$PWD/rdm/bin/agent-system-rdm"
|
||||
export SVC_RDM_SRC_DIR="$PWD/rdm"
|
||||
export SVC_CI_GIT_SERVER="$(printf '%s' "$GITHUB_SERVER_URL" | sed 's:/*$::')"
|
||||
export SVC_CI_GIT_TOKEN="$SUBMODULE_TOKEN"
|
||||
unset SUBMODULE_TOKEN
|
||||
make test-lifecycle
|
||||
|
||||
# U3(统一部署方案):真实 Dev/RDM 制品的 svc.sh 生命周期门禁——桩套件
|
||||
|
||||
+4
-3
@@ -1435,8 +1435,9 @@ svc_launch_serve() {
|
||||
}
|
||||
|
||||
# svc_lifecycle_child ACTION [extra args...]:用清空的环境拉起本脚本的
|
||||
# __lifecycle。白名单:PATH/HOME/USER/LOGNAME/LANG/LC_*/TZ/TMPDIR、代理、SVC_*。
|
||||
# 从不传入 AGENT_SYSTEM_*。
|
||||
# __lifecycle。白名单:PATH/HOME/USER/LOGNAME/LANG/LC_*/TZ/TMPDIR、代理、SVC_*、
|
||||
# GIT_CONFIG_*(运行器把 SSH pin 改写成受信 HTTPS,token 只在环境里)。
|
||||
# 从不传入 AGENT_SYSTEM_*。serve 仍是 env -i,不继承这些变量。
|
||||
svc_lifecycle_child() {
|
||||
local -a args=(env -i "PATH=${PATH:-/usr/bin:/bin}" "HOME=${HOME:-/tmp}"
|
||||
"USER=${USER:-}" "LOGNAME=${LOGNAME:-${USER:-}}" "LANG=${LANG:-C.UTF-8}"
|
||||
@@ -1450,7 +1451,7 @@ svc_lifecycle_child() {
|
||||
while IFS= read -r k; do
|
||||
[ -n "$k" ] || continue
|
||||
args+=("$k=${!k}")
|
||||
done < <(compgen -e | grep -E '^(SVC_|LC_)' || true)
|
||||
done < <(compgen -e | grep -E '^(SVC_|LC_|GIT_CONFIG_)' || true)
|
||||
if [ -n "${RDM_DISABLE_EXEC_TOOLS:-}" ]; then
|
||||
args+=("RDM_DISABLE_EXEC_TOOLS=$RDM_DISABLE_EXEC_TOOLS")
|
||||
fi
|
||||
|
||||
@@ -15,8 +15,14 @@ import time
|
||||
import unittest
|
||||
import urllib.error
|
||||
import urllib.request
|
||||
from urllib.parse import urlparse, urlunparse
|
||||
from pathlib import Path
|
||||
|
||||
from tests.test_svc_realcombo import ci_git_env
|
||||
from urllib.parse import urlparse, urlunparse
|
||||
|
||||
from tests.test_svc_realcombo import ci_git_env
|
||||
|
||||
SOURCE = Path(__file__).resolve().parents[3]
|
||||
PIN = Path(__file__).resolve().parent / "rdm.pin"
|
||||
|
||||
@@ -55,6 +61,7 @@ class LifecycleRealTests(tsr.SvcAutoRecoverTests):
|
||||
self.pin = load_pin()
|
||||
self.env["SVC_RDM_SRC_DIR"] = SRC
|
||||
self.env["RDM_DISABLE_EXEC_TOOLS"] = "1"
|
||||
self.env.update(ci_git_env())
|
||||
self.env.pop("AGENT_SYSTEM_DSN", None)
|
||||
self.env.pop("AGENT_SYSTEM_DATA", None)
|
||||
|
||||
@@ -516,6 +523,7 @@ class LifecycleRealTests(tsr.SvcAutoRecoverTests):
|
||||
dsn = os.environ.get("AGENT_PG_TEST_DSN", "")
|
||||
if not dsn:
|
||||
self.skipTest("PG 跨实例 NOT_RUN:未设置 AGENT_PG_TEST_DSN")
|
||||
dsn = self.private_pg_dsn(dsn)
|
||||
port = self.free_port()
|
||||
self.seed_established("pga", port)
|
||||
self.svc("pga", "stop")
|
||||
@@ -572,6 +580,23 @@ class LifecycleRealTests(tsr.SvcAutoRecoverTests):
|
||||
self.assertNotIn(sentinel, text, path)
|
||||
self.svc("cred", "stop")
|
||||
|
||||
def private_pg_dsn(self, dsn):
|
||||
"""共享的 AGENT_PG_TEST_DSN 已被其他用例写入身份。本用例单独建库。"""
|
||||
parsed = urlparse(dsn)
|
||||
name = "d3pg_" + hashlib.sha256(os.urandom(8)).hexdigest()[:12]
|
||||
created = subprocess.run(
|
||||
["psql", dsn, "-v", "ON_ERROR_STOP=1", "-c",
|
||||
'CREATE DATABASE "%s"' % name],
|
||||
text=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, timeout=30)
|
||||
self.assertEqual(created.returncode, 0, created.stdout.replace(dsn, "<dsn>"))
|
||||
self.addCleanup(self.drop_private_pg, dsn, name)
|
||||
return urlunparse(parsed._replace(path="/" + name))
|
||||
|
||||
def drop_private_pg(self, dsn, name):
|
||||
subprocess.run(
|
||||
["psql", dsn, "-c", 'DROP DATABASE IF EXISTS "%s" WITH (FORCE)' % name],
|
||||
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, timeout=30)
|
||||
|
||||
def event_count(self, name):
|
||||
db = self.runtime(name) / "data" / "rdm.db"
|
||||
con = sqlite3.connect("file:%s?mode=ro" % db, uri=True)
|
||||
|
||||
@@ -286,6 +286,11 @@ class CheckoutTests(unittest.TestCase):
|
||||
digests = (work / "rdm" / "pin-build-digests.txt").read_text()
|
||||
for sha in shas:
|
||||
self.assertIn(sha, digests)
|
||||
gate = WORKFLOW.read_text().split(
|
||||
"Real-combination lifecycle gate", 1)[1].split("\n svc-realcombo:", 1)[0]
|
||||
self.assertIn('export SVC_CI_GIT_TOKEN="$SUBMODULE_TOKEN"', gate)
|
||||
self.assertNotRegex(gate, r"(?m)^\s*source\s")
|
||||
self.assertNotIn(">>", gate)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
Reference in New Issue
Block a user