Files
easyai/scripts/test-install-failures.py
T
wangbo b99eb849b4
Test deployment public URL (Linux) / test-linux (push) Waiting to run
Test start.ps1 (Windows) / test-windows (push) Waiting to run
fix(deploy): 修复组件版本解析和安装升级验收流程
2026-10-18 00:18:00 +08:00

74 lines
3.9 KiB
Python

#!/usr/bin/env python3
"""Exercise the actual installer with real Compose parsing and failing Docker transports."""
import json
import os
from pathlib import Path
import shutil
import subprocess
import tempfile
root = Path(__file__).resolve().parent.parent
real_docker = shutil.which('docker')
with tempfile.TemporaryDirectory(prefix='easyai-install-failures-') as temporary:
base = Path(temporary)
for phase in ('storage', 'manifest', 'pull', 'health'):
project = base / phase
project.mkdir()
for name in ('scripts', 'system-update'):
shutil.copytree(root / name, project / name, ignore=shutil.ignore_patterns('__pycache__'))
for name in ('start.sh', 'docker-compose.yml', 'easyai-proxy.conf.sample'):
shutil.copy2(root / name, project / name)
for sample in root.glob('.env*.sample'):
shutil.copy2(sample, project / sample.name)
sample = project / '.env.sample'
sample.write_text(sample.read_text().replace('UPDATE_MANIFEST_SOURCE=remote', 'UPDATE_MANIFEST_SOURCE=local'))
binaries = project / 'bin'
binaries.mkdir()
commands = project / 'commands.jsonl'
docker = binaries / 'docker'
docker.write_text('''#!/usr/bin/env python3
import json,os,subprocess,sys
args=sys.argv[1:]
with open(os.environ['TEST_COMMANDS'],'a') as log: log.write(json.dumps(args)+'\\n')
if args[:1]==['--config']: args=args[2:]
if args[:2]==['compose','config'] or args[:2]==['compose','version']:
sys.exit(subprocess.call([os.environ['REAL_DOCKER'],*args]))
if args[:2]==['manifest','inspect']:
if os.environ['TEST_PHASE']=='manifest': print('manifest unknown',file=sys.stderr);sys.exit(1)
print(json.dumps({'Descriptor':{'platform':{'os':'linux','architecture':'amd64'}}}));sys.exit(0)
if args[:2]==['compose','pull']: sys.exit(18 if os.environ['TEST_PHASE']=='pull' else 0)
if args[:3]==['compose','ps','-q']: print('test-'+args[-1]);sys.exit(0)
if args[:1]==['inspect']:
if '--format' in args: print('true|unhealthy');sys.exit(0)
sys.exit(1)
if args[:2]==['container','inspect']:
if os.environ['TEST_PHASE']=='storage' and args[-1]=='easyai-server':
print(json.dumps([{'Config':{'Labels':{'com.docker.compose.project':'unrelated-project'}},'Mounts':[]}]))
sys.exit(0)
sys.exit(1)
sys.exit(0)
''')
docker.chmod(0o755)
for name, code in [('sudo', '#!/bin/sh\nexec "$@"\n'), ('curl', '#!/bin/sh\nexit 0\n')]:
path = binaries / name
path.write_text(code)
path.chmod(0o755)
env = {k: v for k, v in os.environ.items() if not k.startswith(('UPDATE_', 'DEPLOY_', 'COMPOSE_'))}
env.update({'PATH': str(binaries) + os.pathsep + env['PATH'], 'REAL_DOCKER': real_docker,
'TEST_COMMANDS': str(commands), 'TEST_PHASE': phase, 'CI': 'true',
'DEPLOY_ACCESS': 'ip', 'DEPLOY_IP': '127.0.0.1', 'DEPLOY_NON_INTERACTIVE': '1',
'DEPLOY_HEALTH_TIMEOUT_SECONDS': '1'})
result = subprocess.run(['bash', 'start.sh'], cwd=project, env=env, capture_output=True, text=True, errors='replace', timeout=120)
assert result.returncode != 0, (phase, result.stdout, result.stderr)
assert '应用启动成功' not in result.stdout and '部署完成' not in result.stdout, result.stdout
calls = [json.loads(line) for line in commands.read_text().splitlines()]
if phase in ('storage', 'manifest'):
assert not any(call[:2] in (['compose', 'pull'], ['compose', 'up']) for call in calls)
if phase == 'pull':
assert ['compose', 'pull'] in calls, (result.stdout, result.stderr, calls)
assert not any(call[:2] == ['compose', 'up'] for call in calls)
if phase == 'health':
assert ['compose', 'up', '-d'] in calls
assert '部署未完成' in result.stdout + result.stderr
print(phase + ': installer failed without reporting success or continuing to the next stage')