Files
kefu/deploy/token-usage-20260917/prepare_release.py
T
2026-09-21 10:34:06 +08:00

59 lines
3.6 KiB
Python

"""Build a metadata-manifested overlay of the tested server/admin changes."""
from pathlib import Path
import hashlib
import json
import shutil
import tarfile
root = Path('C:/kefu')
release = root / 'deploy/token-usage-20260917'
old_release = root / 'deploy/ark-chat-config-20260917'
payload = release / 'payload'
assert not (release / 'manifest.json').exists(), 'Use a fresh release payload; do not overwrite an uploaded candidate'
backend = ['admin_backend', 'admin_api', 'model_gateway', 'model_protocol', 'model_usage', 'knowledge_worker']
tests = ['test_model_usage_collection', 'test_model_usage_recovery', 'test_model_usage_ledger',
'test_model_gateway', 'test_gateway_guard_audit', 'test_gateway_media_audit',
'test_gateway_failure_audit', 'test_knowledge_model_output', 'test_knowledge_tasks',
'test_knowledge', 'test_admin_api', 'test_ark_chat_config']
files = ['wechat_rpa/' + name + '.py' for name in backend + tests]
front = 'admin-web/apps/web-antd/src/'
files += [front + 'api/console.ts', front + 'views/console/call-stats.vue']
files += [front + 'views/console/' + name for name in (
'ModelUsageStats.vue', 'model-usage-format.ts', 'use-usage-request.ts',
'ModelUsageStats.test.ts', 'model-usage.test.ts')]
files += [str(p.relative_to(root)).replace('\\', '/') for p in (root / 'admin-web/apps/web-antd/dist').rglob('*') if p.is_file()]
manifest = []
for name in files:
source = root / name
target = payload / name
target.parent.mkdir(parents=True, exist_ok=True)
shutil.copyfile(source, target)
data = source.read_bytes()
manifest.append({'path': name, 'bytes': len(data), 'sha256': hashlib.sha256(data).hexdigest()})
(release / 'manifest.json').write_text(json.dumps(manifest, indent=2), encoding='utf-8')
with tarfile.open(release / 'payload.tar.gz', 'w:gz') as archive:
for row in manifest:
archive.add(payload / row['path'], arcname=row['path'])
previous_image = json.loads((release / 'baseline.json').read_text())['image']
for filename in ('01-stage.sh', '02-backup-build.sh', '03-deploy.sh', 'rollback.sh', 'Dockerfile.overlay'):
text = (old_release / filename).read_text(encoding='utf-8').replace('ark-chat-config-20260917', 'token-usage-20260917')
text = text.replace('sha256:1d6df0547b32c29ab28c6d96c0a434f5587cb1b62e97c7aaa0a454c4932c1976', previous_image)
if filename == '02-backup-build.sh':
text = text.replace('test_ark_chat_config test_model_gateway test_admin_api.ModelTestApiTest', ' '.join(tests))
if filename == '03-deploy.sh':
start = text.index("baseline=json.loads(")
end = text.index('\nPY', start)
text = text[:start] + '''baseline=json.loads((release/'baseline.json').read_text())['expected']
for name, expected in baseline.items():
assert hashlib.sha256((root/'wechat_rpa'/name).read_bytes()).hexdigest()==expected,name+' changed during staging'
''' + text[end:]
text = text.replace("print('Model configuration fix source and frontend installed.',flush=True)",
"print('Token usage source and frontend installed.',flush=True)")
# Complete in-flight generation where possible before replacing processes.
text = text.replace('docker compose config --quiet',
'docker compose config --quiet\ndocker compose stop -t 190 knowledge-worker\ndocker compose stop -t 65 gateway')
(release / filename).write_text(text, encoding='utf-8', newline='\n')
print(json.dumps({'files': len(manifest), 'package_bytes': (release / 'payload.tar.gz').stat().st_size,
'backend_tests': tests}, indent=2))