fix(qa): isolate legacy database clients with owned transport guard

This commit is contained in:
wangzhibiao committed 2026-10-15 02:54:00 +08:00
1 parent 65c567152e
commit 01e949093a
9 files changed
+577 -23

No files matched your search

+20 -3
View File
@@ -17,6 +17,7 @@ import sys
import time
import urllib.parse
import xml.etree.ElementTree as ET
import qa_isolation
ROOT = Path(__file__).resolve().parents[2]
DATABASE = 'railwaysystem_fusion_qa_20261013'
@@ -50,6 +51,8 @@ def environment(config):
raise ValueError('Refusing non-target database URL')
if any(k.lower() in ('user', 'password') for k in urllib.parse.parse_qs(parsed.query)):
raise ValueError('URL credentials forbidden')
if parsed.port == qa_isolation.LEGACY_PORT:
raise ValueError('Legacy database endpoint is forbidden')
password = config.get('FUSION_QA_APP_PASSWORD', '')
if not password:
raise ValueError('Missing FUSION_QA_APP_PASSWORD')
@@ -115,11 +118,14 @@ def launch(name, command, env):
child = subprocess.Popen(command, cwd=ROOT, env=env, stdout=log, stderr=subprocess.STDOUT, start_new_session=True)
log.close()
started = subprocess.run(['ps', '-p', str(child.pid), '-o', 'lstart='], text=True, capture_output=True).stdout.strip()
ledger.write_text(json.dumps({'pid': child.pid, 'command': command, 'cwd': str(ROOT), 'started': started}))
ledger.write_text(json.dumps({'pid': child.pid, 'command': command, 'cwd': str(ROOT), 'started': started,
'isolation_id': env.get('FUSION_QA_ISOLATION_ID')}))
print(name + ' PID=' + str(child.pid) + ' LOG=' + str(RUNTIME / (name + '.log')))
def start(config, env, backend_port, redis_port):
lease = qa_isolation.require(env.get('QA_DB_URL'))
env['FUSION_QA_ISOLATION_ID'] = lease['isolation_id']
if inspect(env, ['--require-migrated']):
raise ValueError('Backend not started: QA migration preflight failed')
available(backend_port)
@@ -189,13 +195,15 @@ def wait_for_exit(pid):
raise ValueError('Task-owned process did not stop; ledger retained, no forced kill')
def stop():
def stop(isolation_id=None):
private_directory()
for name in ['frontend', 'backend', 'redis']:
path = RUNTIME / (name + '.json')
if not path.exists():
continue
item = json.loads(path.read_text())
if isolation_id is not None and item.get('isolation_id') != isolation_id:
raise ValueError('Other isolation lease owns this runtime ledger; refusing to signal it')
actual = subprocess.run(['ps', '-p', str(item['pid']), '-o', 'command='], text=True, capture_output=True).stdout.strip()
if actual:
# macOS Python wrappers exec Python.app; Redis rewrites its process title.
@@ -233,11 +241,20 @@ def main():
stop()
return 0
if args.action == 'frontend':
lease = qa_isolation.require()
backend = json.loads((RUNTIME / 'backend.json').read_text())
if backend.get('isolation_id') != lease['isolation_id'] or '--server.port=' + str(args.backend_port) not in backend.get('command', []):
raise ValueError('Frontend backend belongs to another isolation lease')
available(args.frontend_port)
env = os.environ.copy()
env['FUSION_QA_ISOLATION_ID'] = lease['isolation_id']
launch('frontend', [sys.executable, str(ROOT / 'scripts/qa/serve_frontend.py'),
'--port', str(args.frontend_port), '--backend-port', str(args.backend_port)], os.environ.copy())
'--port', str(args.frontend_port), '--backend-port', str(args.backend_port)], env)
return 0
config = load_config(args.config)
if args.action == 'start' or (RUNTIME / qa_isolation.LEDGER).exists():
lease = qa_isolation.require()
config.setdefault('FUSION_QA_DB_URL', qa_isolation.url_for(lease))
env = environment(config)
if args.action == 'inspect':
return inspect(env, [])