fix(deploy): 修复组件版本解析和安装升级验收流程

This commit is contained in:
2026-10-18 00:18:00 +08:00
parent 895d92317e
commit b99eb849b4
30 changed files with 1579 additions and 270 deletions
+47
View File
@@ -0,0 +1,47 @@
#!/usr/bin/env python3
"""Both command-line shells honor a live stable source even when Git's snapshot differs."""
from functools import partial
from http.server import SimpleHTTPRequestHandler, ThreadingHTTPServer
import json
import os
from pathlib import Path
import subprocess
import tempfile
from threading import Thread
source = Path(__file__).resolve().parent.parent
with tempfile.TemporaryDirectory(prefix='easyai-release-source-') as temporary:
root = Path(temporary)
manifest = json.loads((source/'system-update/releases/3.29.0.20261014.2.json').read_text())
manifest['channel'] = 'stable'
manifest['components'] = [item for item in manifest['components'] if item['key'] in {'server-main','web','ws-gateway'}]
(root/'release-manifest.json').write_text(json.dumps(manifest))
class Handler(SimpleHTTPRequestHandler):
def log_message(self, *args): pass
server = ThreadingHTTPServer(('127.0.0.1',0),partial(Handler,directory=str(root)))
thread = Thread(target=server.serve_forever,daemon=True)
thread.start()
script = root/'plan.ps1'
script.write_text('param($Security,$Versions,$Path)\n$ErrorActionPreference="Stop"\n. $Security\n. $Versions\n@(Get-ApplicationVersionPlan -Path $Path) | ConvertTo-Json -Compress\n')
env = {k:v for k,v in os.environ.items() if not k.startswith(('UPDATE_','DEPLOY_'))}
try:
for mode, filename, expected in [('remote','release-manifest.json','3.29.0.20261014.2'),('remote','missing.json',None),('local','missing.json','3.30.2.20261017')]:
path = root/'.env'
path.write_text(f'VERSION=latest\nUPDATE_MANIFEST_SOURCE={mode}\nUPDATE_MANIFEST_URL=http://127.0.0.1:{server.server_port}/{filename}?token=synthetic-secret-must-not-appear\n')
before = path.read_bytes()
commands = [['python3',str(source/'scripts/resolve-deployment-release.py'),'--env-file',str(path),'--format','json'],
['pwsh','-NoProfile','-NonInteractive','-File',str(script),str(source/'scripts/Initialize-SecurityEnv.ps1'),str(source/'scripts/Initialize-ApplicationVersions.ps1'),str(path)]]
for command in commands:
result = subprocess.run(command,env=env,capture_output=True,text=True,timeout=90)
assert 'synthetic-secret-must-not-appear' not in result.stdout+result.stderr
assert (result.returncode==0)==bool(expected),(mode,filename,result.stdout,result.stderr)
if expected:
plan=json.loads(result.stdout)
values={entry['Key']:entry['Version'] for entry in plan}
assert values['VERSION']==expected
assert values['SERVER_VERSION'].startswith(expected+'@sha256:')
assert path.read_bytes()==before
print(mode+'/'+filename+': both shells selected the authoritative source without stale fallback or credential logging')
finally:
server.shutdown()
server.server_close()